k-l-lambda's picture
feat: add Python ML services (CPU mode) with model download
2b7aae2
import {
FrontSide,
BackSide,
DoubleSide,
RGBAFormat,
NearestFilter,
LinearFilter,
PCFShadowMap,
VSMShadowMap,
RGBADepthPacking,
NoBlending,
} from '../../constants.js';
import { WebGLRenderTarget } from '../WebGLRenderTarget.js';
import { MeshDepthMaterial } from '../../materials/MeshDepthMaterial.js';
import { MeshDistanceMaterial } from '../../materials/MeshDistanceMaterial.js';
import { ShaderMaterial } from '../../materials/ShaderMaterial.js';
import { BufferAttribute } from '../../core/BufferAttribute.js';
import { BufferGeometry } from '../../core/BufferGeometry.js';
import { Mesh } from '../../objects/Mesh.js';
import { Vector4 } from '../../math/Vector4.js';
import { Vector2 } from '../../math/Vector2.js';
import { Frustum } from '../../math/Frustum.js';
import * as vsm from '../shaders/ShaderLib/vsm.glsl.js';
function WebGLShadowMap(_renderer, _objects, _capabilities) {
let _frustum = new Frustum();
const _shadowMapSize = new Vector2(),
_viewportSize = new Vector2(),
_viewport = new Vector4(),
_depthMaterial = new MeshDepthMaterial({ depthPacking: RGBADepthPacking }),
_distanceMaterial = new MeshDistanceMaterial(),
_materialCache = {},
_maxTextureSize = _capabilities.maxTextureSize;
const shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };
const shadowMaterialVertical = new ShaderMaterial({
defines: {
VSM_SAMPLES: 8,
},
uniforms: {
shadow_pass: { value: null },
resolution: { value: new Vector2() },
radius: { value: 4.0 },
},
vertexShader: vsm.vertex,
fragmentShader: vsm.fragment,
});
const shadowMaterialHorizontal = shadowMaterialVertical.clone();
shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1;
const fullScreenTri = new BufferGeometry();
fullScreenTri.setAttribute('position', new BufferAttribute(new Float32Array([-1, -1, 0.5, 3, -1, 0.5, -1, 3, 0.5]), 3));
const fullScreenMesh = new Mesh(fullScreenTri, shadowMaterialVertical);
const scope = this;
this.enabled = false;
this.autoUpdate = true;
this.needsUpdate = false;
this.type = PCFShadowMap;
this.render = function (lights, scene, camera) {
if (scope.enabled === false) return;
if (scope.autoUpdate === false && scope.needsUpdate === false) return;
if (lights.length === 0) return;
const currentRenderTarget = _renderer.getRenderTarget();
const activeCubeFace = _renderer.getActiveCubeFace();
const activeMipmapLevel = _renderer.getActiveMipmapLevel();
const _state = _renderer.state;
// Set GL state for depth map.
_state.setBlending(NoBlending);
_state.buffers.color.setClear(1, 1, 1, 1);
_state.buffers.depth.setTest(true);
_state.setScissorTest(false);
// render depth map
for (let i = 0, il = lights.length; i < il; i++) {
const light = lights[i];
const shadow = light.shadow;
if (shadow === undefined) {
console.warn('THREE.WebGLShadowMap:', light, 'has no shadow.');
continue;
}
if (shadow.autoUpdate === false && shadow.needsUpdate === false) continue;
_shadowMapSize.copy(shadow.mapSize);
const shadowFrameExtents = shadow.getFrameExtents();
_shadowMapSize.multiply(shadowFrameExtents);
_viewportSize.copy(shadow.mapSize);
if (_shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize) {
if (_shadowMapSize.x > _maxTextureSize) {
_viewportSize.x = Math.floor(_maxTextureSize / shadowFrameExtents.x);
_shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x;
shadow.mapSize.x = _viewportSize.x;
}
if (_shadowMapSize.y > _maxTextureSize) {
_viewportSize.y = Math.floor(_maxTextureSize / shadowFrameExtents.y);
_shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y;
shadow.mapSize.y = _viewportSize.y;
}
}
if (shadow.map === null && !shadow.isPointLightShadow && this.type === VSMShadowMap) {
const pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat };
shadow.map = new WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y, pars);
shadow.map.texture.name = light.name + '.shadowMap';
shadow.mapPass = new WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y, pars);
shadow.camera.updateProjectionMatrix();
}
if (shadow.map === null) {
const pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };
shadow.map = new WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y, pars);
shadow.map.texture.name = light.name + '.shadowMap';
shadow.camera.updateProjectionMatrix();
}
_renderer.setRenderTarget(shadow.map);
_renderer.clear();
const viewportCount = shadow.getViewportCount();
for (let vp = 0; vp < viewportCount; vp++) {
const viewport = shadow.getViewport(vp);
_viewport.set(_viewportSize.x * viewport.x, _viewportSize.y * viewport.y, _viewportSize.x * viewport.z, _viewportSize.y * viewport.w);
_state.viewport(_viewport);
shadow.updateMatrices(light, vp);
_frustum = shadow.getFrustum();
renderObject(scene, camera, shadow.camera, light, this.type);
}
// do blur pass for VSM
if (!shadow.isPointLightShadow && this.type === VSMShadowMap) {
VSMPass(shadow, camera);
}
shadow.needsUpdate = false;
}
scope.needsUpdate = false;
_renderer.setRenderTarget(currentRenderTarget, activeCubeFace, activeMipmapLevel);
};
function VSMPass(shadow, camera) {
const geometry = _objects.update(fullScreenMesh);
if (shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples) {
shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples;
shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples;
shadowMaterialVertical.needsUpdate = true;
shadowMaterialHorizontal.needsUpdate = true;
}
// vertical pass
shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;
shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;
shadowMaterialVertical.uniforms.radius.value = shadow.radius;
_renderer.setRenderTarget(shadow.mapPass);
_renderer.clear();
_renderer.renderBufferDirect(camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null);
// horizontal pass
shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture;
shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize;
shadowMaterialHorizontal.uniforms.radius.value = shadow.radius;
_renderer.setRenderTarget(shadow.map);
_renderer.clear();
_renderer.renderBufferDirect(camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null);
}
function getDepthMaterial(object, geometry, material, light, shadowCameraNear, shadowCameraFar, type) {
let result = null;
const customMaterial = light.isPointLight === true ? object.customDistanceMaterial : object.customDepthMaterial;
if (customMaterial !== undefined) {
result = customMaterial;
} else {
result = light.isPointLight === true ? _distanceMaterial : _depthMaterial;
}
if (
(_renderer.localClippingEnabled && material.clipShadows === true && material.clippingPlanes.length !== 0) ||
(material.displacementMap && material.displacementScale !== 0) ||
(material.alphaMap && material.alphaTest > 0)
) {
// in this case we need a unique material instance reflecting the
// appropriate state
const keyA = result.uuid,
keyB = material.uuid;
let materialsForVariant = _materialCache[keyA];
if (materialsForVariant === undefined) {
materialsForVariant = {};
_materialCache[keyA] = materialsForVariant;
}
let cachedMaterial = materialsForVariant[keyB];
if (cachedMaterial === undefined) {
cachedMaterial = result.clone();
materialsForVariant[keyB] = cachedMaterial;
}
result = cachedMaterial;
}
result.visible = material.visible;
result.wireframe = material.wireframe;
if (type === VSMShadowMap) {
result.side = material.shadowSide !== null ? material.shadowSide : material.side;
} else {
result.side = material.shadowSide !== null ? material.shadowSide : shadowSide[material.side];
}
result.alphaMap = material.alphaMap;
result.alphaTest = material.alphaTest;
result.clipShadows = material.clipShadows;
result.clippingPlanes = material.clippingPlanes;
result.clipIntersection = material.clipIntersection;
result.displacementMap = material.displacementMap;
result.displacementScale = material.displacementScale;
result.displacementBias = material.displacementBias;
result.wireframeLinewidth = material.wireframeLinewidth;
result.linewidth = material.linewidth;
if (light.isPointLight === true && result.isMeshDistanceMaterial === true) {
result.referencePosition.setFromMatrixPosition(light.matrixWorld);
result.nearDistance = shadowCameraNear;
result.farDistance = shadowCameraFar;
}
return result;
}
function renderObject(object, camera, shadowCamera, light, type) {
if (object.visible === false) return;
const visible = object.layers.test(camera.layers);
if (visible && (object.isMesh || object.isLine || object.isPoints)) {
if ((object.castShadow || (object.receiveShadow && type === VSMShadowMap)) && (!object.frustumCulled || _frustum.intersectsObject(object))) {
object.modelViewMatrix.multiplyMatrices(shadowCamera.matrixWorldInverse, object.matrixWorld);
const geometry = _objects.update(object);
const material = object.material;
if (Array.isArray(material)) {
const groups = geometry.groups;
for (let k = 0, kl = groups.length; k < kl; k++) {
const group = groups[k];
const groupMaterial = material[group.materialIndex];
if (groupMaterial && groupMaterial.visible) {
const depthMaterial = getDepthMaterial(object, geometry, groupMaterial, light, shadowCamera.near, shadowCamera.far, type);
_renderer.renderBufferDirect(shadowCamera, null, geometry, depthMaterial, object, group);
}
}
} else if (material.visible) {
const depthMaterial = getDepthMaterial(object, geometry, material, light, shadowCamera.near, shadowCamera.far, type);
_renderer.renderBufferDirect(shadowCamera, null, geometry, depthMaterial, object, null);
}
}
}
const children = object.children;
for (let i = 0, l = children.length; i < l; i++) {
renderObject(children[i], camera, shadowCamera, light, type);
}
}
}
export { WebGLShadowMap };