cione-comp-lib
Version:
`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`
696 lines (695 loc) • 26.3 kB
JavaScript
import Base from "../core/Base.mjs";
import glenum from "../core/glenum.mjs";
import Vector3 from "../math/Vector3.mjs";
import BoundingBox from "../math/BoundingBox.mjs";
import Frustum from "../math/Frustum.mjs";
import Matrix4 from "../math/Matrix4.mjs";
import Renderer from "../Renderer.mjs";
import Shader from "../Shader.mjs";
import Material from "../Material.mjs";
import FrameBuffer from "../FrameBuffer.mjs";
import Texture from "../Texture.mjs";
import Texture2D from "../Texture2D.mjs";
import TextureCube from "../TextureCube.mjs";
import PerspectiveCamera from "../camera/Perspective.mjs";
import OrthoCamera from "../camera/Orthographic.mjs";
import Pass from "../compositor/Pass.mjs";
import TexturePool from "../compositor/TexturePool.mjs";
import mat4 from "../glmatrix/mat4.mjs";
import shadowmapEssl from "../shader/source/shadowmap.glsl.mjs";
var targets = ["px", "nx", "py", "ny", "pz", "nz"];
Shader["import"](shadowmapEssl);
function getDepthMaterialUniform(renderable, depthMaterial, symbol) {
if (symbol === "alphaMap") {
return renderable.material.get("diffuseMap");
} else if (symbol === "alphaCutoff") {
if (renderable.material.isDefined("fragment", "ALPHA_TEST") && renderable.material.get("diffuseMap")) {
var alphaCutoff = renderable.material.get("alphaCutoff");
return alphaCutoff || 0;
}
return 0;
} else if (symbol === "uvRepeat") {
return renderable.material.get("uvRepeat");
} else if (symbol === "uvOffset") {
return renderable.material.get("uvOffset");
} else {
return depthMaterial.get(symbol);
}
}
function isDepthMaterialChanged(renderable, prevRenderable) {
var matA = renderable.material;
var matB = prevRenderable.material;
return matA.get("diffuseMap") !== matB.get("diffuseMap") || (matA.get("alphaCutoff") || 0) !== (matB.get("alphaCutoff") || 0);
}
var ShadowMapPass = Base.extend(function() {
return {
softShadow: ShadowMapPass.PCF,
shadowBlur: 1,
lightFrustumBias: "auto",
kernelPCF: new Float32Array([
1,
0,
1,
1,
-1,
1,
0,
1,
-1,
0,
-1,
-1,
1,
-1,
0,
-1
]),
precision: "highp",
_lastRenderNotCastShadow: false,
_frameBuffer: new FrameBuffer(),
_textures: {},
_shadowMapNumber: {
"POINT_LIGHT": 0,
"DIRECTIONAL_LIGHT": 0,
"SPOT_LIGHT": 0
},
_depthMaterials: {},
_distanceMaterials: {},
_receivers: [],
_lightsCastShadow: [],
_lightCameras: {},
_lightMaterials: {},
_texturePool: new TexturePool()
};
}, function() {
this._gaussianPassH = new Pass({
fragment: Shader.source("clay.compositor.gaussian_blur")
});
this._gaussianPassV = new Pass({
fragment: Shader.source("clay.compositor.gaussian_blur")
});
this._gaussianPassH.setUniform("blurSize", this.shadowBlur);
this._gaussianPassH.setUniform("blurDir", 0);
this._gaussianPassV.setUniform("blurSize", this.shadowBlur);
this._gaussianPassV.setUniform("blurDir", 1);
this._outputDepthPass = new Pass({
fragment: Shader.source("clay.sm.debug_depth")
});
}, {
render: function(renderer, scene, sceneCamera, notUpdateScene) {
if (!sceneCamera) {
sceneCamera = scene.getMainCamera();
}
this.trigger("beforerender", this, renderer, scene, sceneCamera);
this._renderShadowPass(renderer, scene, sceneCamera, notUpdateScene);
this.trigger("afterrender", this, renderer, scene, sceneCamera);
},
renderDebug: function(renderer, size) {
renderer.saveClear();
var viewport = renderer.viewport;
var x = 0, y = 0;
var width = size || viewport.width / 4;
var height = width;
if (this.softShadow === ShadowMapPass.VSM) {
this._outputDepthPass.material.define("fragment", "USE_VSM");
} else {
this._outputDepthPass.material.undefine("fragment", "USE_VSM");
}
for (var name in this._textures) {
var texture = this._textures[name];
renderer.setViewport(x, y, width * texture.width / texture.height, height);
this._outputDepthPass.setUniform("depthMap", texture);
this._outputDepthPass.render(renderer);
x += width * texture.width / texture.height;
}
renderer.setViewport(viewport);
renderer.restoreClear();
},
_updateReceivers: function(renderer, mesh) {
if (mesh.receiveShadow) {
this._receivers.push(mesh);
mesh.material.set("shadowEnabled", 1);
mesh.material.set("pcfKernel", this.kernelPCF);
} else {
mesh.material.set("shadowEnabled", 0);
}
if (this.softShadow === ShadowMapPass.VSM) {
mesh.material.define("fragment", "USE_VSM");
mesh.material.undefine("fragment", "PCF_KERNEL_SIZE");
} else {
mesh.material.undefine("fragment", "USE_VSM");
var kernelPCF = this.kernelPCF;
if (kernelPCF && kernelPCF.length) {
mesh.material.define("fragment", "PCF_KERNEL_SIZE", kernelPCF.length / 2);
} else {
mesh.material.undefine("fragment", "PCF_KERNEL_SIZE");
}
}
},
_update: function(renderer, scene) {
var self = this;
scene.traverse(function(renderable) {
if (renderable.isRenderable()) {
self._updateReceivers(renderer, renderable);
}
});
for (var i = 0; i < scene.lights.length; i++) {
var light = scene.lights[i];
if (light.castShadow && !light.invisible) {
this._lightsCastShadow.push(light);
}
}
},
_renderShadowPass: function(renderer, scene, sceneCamera, notUpdateScene) {
for (var name in this._shadowMapNumber) {
this._shadowMapNumber[name] = 0;
}
this._lightsCastShadow.length = 0;
this._receivers.length = 0;
var _gl = renderer.gl;
if (!notUpdateScene) {
scene.update();
}
if (sceneCamera) {
sceneCamera.update();
}
scene.updateLights();
this._update(renderer, scene);
if (!this._lightsCastShadow.length && this._lastRenderNotCastShadow) {
return;
}
this._lastRenderNotCastShadow = this._lightsCastShadow === 0;
_gl.enable(_gl.DEPTH_TEST);
_gl.depthMask(true);
_gl.disable(_gl.BLEND);
_gl.clearColor(1, 1, 1, 1);
var spotLightShadowMaps = [];
var spotLightMatrices = [];
var directionalLightShadowMaps = [];
var directionalLightMatrices = [];
var shadowCascadeClips = [];
var pointLightShadowMaps = [];
var dirLightHasCascade;
for (var i = 0; i < this._lightsCastShadow.length; i++) {
var light = this._lightsCastShadow[i];
if (light.type === "DIRECTIONAL_LIGHT") {
if (dirLightHasCascade) {
console.warn("Only one direectional light supported with shadow cascade");
continue;
}
if (light.shadowCascade > 4) {
console.warn("Support at most 4 cascade");
continue;
}
if (light.shadowCascade > 1) {
dirLightHasCascade = light;
}
this.renderDirectionalLightShadow(
renderer,
scene,
sceneCamera,
light,
shadowCascadeClips,
directionalLightMatrices,
directionalLightShadowMaps
);
} else if (light.type === "SPOT_LIGHT") {
this.renderSpotLightShadow(
renderer,
scene,
light,
spotLightMatrices,
spotLightShadowMaps
);
} else if (light.type === "POINT_LIGHT") {
this.renderPointLightShadow(
renderer,
scene,
light,
pointLightShadowMaps
);
}
this._shadowMapNumber[light.type]++;
}
for (var lightType in this._shadowMapNumber) {
var number = this._shadowMapNumber[lightType];
var key = lightType + "_SHADOWMAP_COUNT";
for (var i = 0; i < this._receivers.length; i++) {
var mesh = this._receivers[i];
var material = mesh.material;
if (material.fragmentDefines[key] !== number) {
if (number > 0) {
material.define("fragment", key, number);
} else if (material.isDefined("fragment", key)) {
material.undefine("fragment", key);
}
}
}
}
for (var i = 0; i < this._receivers.length; i++) {
var mesh = this._receivers[i];
var material = mesh.material;
if (dirLightHasCascade) {
material.define("fragment", "SHADOW_CASCADE", dirLightHasCascade.shadowCascade);
} else {
material.undefine("fragment", "SHADOW_CASCADE");
}
}
var shadowUniforms = scene.shadowUniforms;
function getSize(texture) {
return texture.height;
}
if (directionalLightShadowMaps.length > 0) {
var directionalLightShadowMapSizes = directionalLightShadowMaps.map(getSize);
shadowUniforms.directionalLightShadowMaps = { value: directionalLightShadowMaps, type: "tv" };
shadowUniforms.directionalLightMatrices = { value: directionalLightMatrices, type: "m4v" };
shadowUniforms.directionalLightShadowMapSizes = { value: directionalLightShadowMapSizes, type: "1fv" };
if (dirLightHasCascade) {
var shadowCascadeClipsNear = shadowCascadeClips.slice();
var shadowCascadeClipsFar = shadowCascadeClips.slice();
shadowCascadeClipsNear.pop();
shadowCascadeClipsFar.shift();
shadowCascadeClipsNear.reverse();
shadowCascadeClipsFar.reverse();
directionalLightMatrices.reverse();
shadowUniforms.shadowCascadeClipsNear = { value: shadowCascadeClipsNear, type: "1fv" };
shadowUniforms.shadowCascadeClipsFar = { value: shadowCascadeClipsFar, type: "1fv" };
}
}
if (spotLightShadowMaps.length > 0) {
var spotLightShadowMapSizes = spotLightShadowMaps.map(getSize);
var shadowUniforms = scene.shadowUniforms;
shadowUniforms.spotLightShadowMaps = { value: spotLightShadowMaps, type: "tv" };
shadowUniforms.spotLightMatrices = { value: spotLightMatrices, type: "m4v" };
shadowUniforms.spotLightShadowMapSizes = { value: spotLightShadowMapSizes, type: "1fv" };
}
if (pointLightShadowMaps.length > 0) {
shadowUniforms.pointLightShadowMaps = { value: pointLightShadowMaps, type: "tv" };
}
},
renderDirectionalLightShadow: function() {
var splitFrustum = new Frustum();
var splitProjMatrix = new Matrix4();
var cropBBox = new BoundingBox();
var cropMatrix = new Matrix4();
var lightViewMatrix = new Matrix4();
var lightViewProjMatrix = new Matrix4();
var lightProjMatrix = new Matrix4();
return function(renderer, scene, sceneCamera, light, shadowCascadeClips, directionalLightMatrices, directionalLightShadowMaps) {
var defaultShadowMaterial = this._getDepthMaterial(light);
var passConfig = {
getMaterial: function(renderable) {
return renderable.shadowDepthMaterial || defaultShadowMaterial;
},
isMaterialChanged: isDepthMaterialChanged,
getUniform: getDepthMaterialUniform,
ifRender: function(renderable) {
return renderable.castShadow;
},
sortCompare: Renderer.opaqueSortCompare
};
if (!scene.viewBoundingBoxLastFrame.isFinite()) {
var boundingBox = scene.getBoundingBox();
scene.viewBoundingBoxLastFrame.copy(boundingBox).applyTransform(sceneCamera.viewMatrix);
}
var clippedFar = Math.min(-scene.viewBoundingBoxLastFrame.min.z, sceneCamera.far);
var clippedNear = Math.max(-scene.viewBoundingBoxLastFrame.max.z, sceneCamera.near);
var lightCamera = this._getDirectionalLightCamera(light, scene, sceneCamera);
var lvpMat4Arr = lightViewProjMatrix.array;
lightProjMatrix.copy(lightCamera.projectionMatrix);
mat4.invert(lightViewMatrix.array, lightCamera.worldTransform.array);
mat4.multiply(lightViewMatrix.array, lightViewMatrix.array, sceneCamera.worldTransform.array);
mat4.multiply(lvpMat4Arr, lightProjMatrix.array, lightViewMatrix.array);
var clipPlanes = [];
var isPerspective = sceneCamera instanceof PerspectiveCamera;
var scaleZ = (sceneCamera.near + sceneCamera.far) / (sceneCamera.near - sceneCamera.far);
var offsetZ = 2 * sceneCamera.near * sceneCamera.far / (sceneCamera.near - sceneCamera.far);
for (var i = 0; i <= light.shadowCascade; i++) {
var clog = clippedNear * Math.pow(clippedFar / clippedNear, i / light.shadowCascade);
var cuni = clippedNear + (clippedFar - clippedNear) * i / light.shadowCascade;
var c = clog * light.cascadeSplitLogFactor + cuni * (1 - light.cascadeSplitLogFactor);
clipPlanes.push(c);
shadowCascadeClips.push(-(-c * scaleZ + offsetZ) / -c);
}
var texture = this._getTexture(light, light.shadowCascade);
directionalLightShadowMaps.push(texture);
var viewport = renderer.viewport;
var _gl = renderer.gl;
this._frameBuffer.attach(texture);
this._frameBuffer.bind(renderer);
_gl.clear(_gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT);
for (var i = 0; i < light.shadowCascade; i++) {
var nearPlane = clipPlanes[i];
var farPlane = clipPlanes[i + 1];
if (isPerspective) {
mat4.perspective(splitProjMatrix.array, sceneCamera.fov / 180 * Math.PI, sceneCamera.aspect, nearPlane, farPlane);
} else {
mat4.ortho(
splitProjMatrix.array,
sceneCamera.left,
sceneCamera.right,
sceneCamera.bottom,
sceneCamera.top,
nearPlane,
farPlane
);
}
splitFrustum.setFromProjection(splitProjMatrix);
splitFrustum.getTransformedBoundingBox(cropBBox, lightViewMatrix);
cropBBox.applyProjection(lightProjMatrix);
var _min = cropBBox.min.array;
var _max = cropBBox.max.array;
_min[0] = Math.max(_min[0], -1);
_min[1] = Math.max(_min[1], -1);
_max[0] = Math.min(_max[0], 1);
_max[1] = Math.min(_max[1], 1);
cropMatrix.ortho(_min[0], _max[0], _min[1], _max[1], 1, -1);
lightCamera.projectionMatrix.multiplyLeft(cropMatrix);
var shadowSize = light.shadowResolution || 512;
renderer.setViewport((light.shadowCascade - i - 1) * shadowSize, 0, shadowSize, shadowSize, 1);
var renderList = scene.updateRenderList(lightCamera);
renderer.renderPass(renderList.opaque, lightCamera, passConfig);
if (this.softShadow === ShadowMapPass.VSM) {
this._gaussianFilter(renderer, texture, texture.width);
}
var matrix = new Matrix4();
matrix.copy(lightCamera.viewMatrix).multiplyLeft(lightCamera.projectionMatrix);
directionalLightMatrices.push(matrix.array);
lightCamera.projectionMatrix.copy(lightProjMatrix);
}
this._frameBuffer.unbind(renderer);
renderer.setViewport(viewport);
};
}(),
renderSpotLightShadow: function(renderer, scene, light, spotLightMatrices, spotLightShadowMaps) {
var texture = this._getTexture(light);
var lightCamera = this._getSpotLightCamera(light);
var _gl = renderer.gl;
this._frameBuffer.attach(texture);
this._frameBuffer.bind(renderer);
_gl.clear(_gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT);
var defaultShadowMaterial = this._getDepthMaterial(light);
var passConfig = {
getMaterial: function(renderable) {
return renderable.shadowDepthMaterial || defaultShadowMaterial;
},
isMaterialChanged: isDepthMaterialChanged,
getUniform: getDepthMaterialUniform,
ifRender: function(renderable) {
return renderable.castShadow;
},
sortCompare: Renderer.opaqueSortCompare
};
var renderList = scene.updateRenderList(lightCamera);
renderer.renderPass(renderList.opaque, lightCamera, passConfig);
this._frameBuffer.unbind(renderer);
if (this.softShadow === ShadowMapPass.VSM) {
this._gaussianFilter(renderer, texture, texture.width);
}
var matrix = new Matrix4();
matrix.copy(lightCamera.worldTransform).invert().multiplyLeft(lightCamera.projectionMatrix);
spotLightShadowMaps.push(texture);
spotLightMatrices.push(matrix.array);
},
renderPointLightShadow: function(renderer, scene, light, pointLightShadowMaps) {
var texture = this._getTexture(light);
var _gl = renderer.gl;
pointLightShadowMaps.push(texture);
var defaultShadowMaterial = this._getDepthMaterial(light);
var passConfig = {
getMaterial: function(renderable) {
return renderable.shadowDepthMaterial || defaultShadowMaterial;
},
getUniform: getDepthMaterialUniform,
sortCompare: Renderer.opaqueSortCompare
};
var renderListEachSide = {
px: [],
py: [],
pz: [],
nx: [],
ny: [],
nz: []
};
var bbox = new BoundingBox();
var lightWorldPosition = light.getWorldPosition().array;
var lightBBox = new BoundingBox();
var range = light.range;
lightBBox.min.setArray(lightWorldPosition);
lightBBox.max.setArray(lightWorldPosition);
var extent = new Vector3(range, range, range);
lightBBox.max.add(extent);
lightBBox.min.sub(extent);
var targetsNeedRender = { px: false, py: false, pz: false, nx: false, ny: false, nz: false };
scene.traverse(function(renderable) {
if (renderable.isRenderable() && renderable.castShadow) {
var geometry = renderable.geometry;
if (!geometry.boundingBox) {
for (var i2 = 0; i2 < targets.length; i2++) {
renderListEachSide[targets[i2]].push(renderable);
}
return;
}
bbox.transformFrom(geometry.boundingBox, renderable.worldTransform);
if (!bbox.intersectBoundingBox(lightBBox)) {
return;
}
bbox.updateVertices();
for (var i2 = 0; i2 < targets.length; i2++) {
targetsNeedRender[targets[i2]] = false;
}
for (var i2 = 0; i2 < 8; i2++) {
var vtx = bbox.vertices[i2];
var x = vtx[0] - lightWorldPosition[0];
var y = vtx[1] - lightWorldPosition[1];
var z = vtx[2] - lightWorldPosition[2];
var absx = Math.abs(x);
var absy = Math.abs(y);
var absz = Math.abs(z);
if (absx > absy) {
if (absx > absz) {
targetsNeedRender[x > 0 ? "px" : "nx"] = true;
} else {
targetsNeedRender[z > 0 ? "pz" : "nz"] = true;
}
} else {
if (absy > absz) {
targetsNeedRender[y > 0 ? "py" : "ny"] = true;
} else {
targetsNeedRender[z > 0 ? "pz" : "nz"] = true;
}
}
}
for (var i2 = 0; i2 < targets.length; i2++) {
if (targetsNeedRender[targets[i2]]) {
renderListEachSide[targets[i2]].push(renderable);
}
}
}
});
for (var i = 0; i < 6; i++) {
var target = targets[i];
var camera = this._getPointLightCamera(light, target);
this._frameBuffer.attach(texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i);
this._frameBuffer.bind(renderer);
_gl.clear(_gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT);
renderer.renderPass(renderListEachSide[target], camera, passConfig);
}
this._frameBuffer.unbind(renderer);
},
_getDepthMaterial: function(light) {
var shadowMaterial = this._lightMaterials[light.__uid__];
var isPointLight = light.type === "POINT_LIGHT";
if (!shadowMaterial) {
var shaderPrefix = isPointLight ? "clay.sm.distance." : "clay.sm.depth.";
shadowMaterial = new Material({
precision: this.precision,
shader: new Shader(Shader.source(shaderPrefix + "vertex"), Shader.source(shaderPrefix + "fragment"))
});
this._lightMaterials[light.__uid__] = shadowMaterial;
}
if (light.shadowSlopeScale != null) {
shadowMaterial.setUniform("slopeScale", light.shadowSlopeScale);
}
if (light.shadowBias != null) {
shadowMaterial.setUniform("bias", light.shadowBias);
}
if (this.softShadow === ShadowMapPass.VSM) {
shadowMaterial.define("fragment", "USE_VSM");
} else {
shadowMaterial.undefine("fragment", "USE_VSM");
}
if (isPointLight) {
shadowMaterial.set("lightPosition", light.getWorldPosition().array);
shadowMaterial.set("range", light.range);
}
return shadowMaterial;
},
_gaussianFilter: function(renderer, texture, size) {
var parameter = {
width: size,
height: size,
type: Texture.FLOAT
};
var tmpTexture = this._texturePool.get(parameter);
this._frameBuffer.attach(tmpTexture);
this._frameBuffer.bind(renderer);
this._gaussianPassH.setUniform("texture", texture);
this._gaussianPassH.setUniform("textureWidth", size);
this._gaussianPassH.render(renderer);
this._frameBuffer.attach(texture);
this._gaussianPassV.setUniform("texture", tmpTexture);
this._gaussianPassV.setUniform("textureHeight", size);
this._gaussianPassV.render(renderer);
this._frameBuffer.unbind(renderer);
this._texturePool.put(tmpTexture);
},
_getTexture: function(light, cascade) {
var key = light.__uid__;
var texture = this._textures[key];
var resolution = light.shadowResolution || 512;
cascade = cascade || 1;
if (!texture) {
if (light.type === "POINT_LIGHT") {
texture = new TextureCube();
} else {
texture = new Texture2D();
}
texture.width = resolution * cascade;
texture.height = resolution;
if (this.softShadow === ShadowMapPass.VSM) {
texture.type = Texture.FLOAT;
texture.anisotropic = 4;
} else {
texture.minFilter = glenum.NEAREST;
texture.magFilter = glenum.NEAREST;
texture.useMipmap = false;
}
this._textures[key] = texture;
}
return texture;
},
_getPointLightCamera: function(light, target) {
if (!this._lightCameras.point) {
this._lightCameras.point = {
px: new PerspectiveCamera(),
nx: new PerspectiveCamera(),
py: new PerspectiveCamera(),
ny: new PerspectiveCamera(),
pz: new PerspectiveCamera(),
nz: new PerspectiveCamera()
};
}
var camera = this._lightCameras.point[target];
camera.far = light.range;
camera.fov = 90;
camera.position.set(0, 0, 0);
switch (target) {
case "px":
camera.lookAt(Vector3.POSITIVE_X, Vector3.NEGATIVE_Y);
break;
case "nx":
camera.lookAt(Vector3.NEGATIVE_X, Vector3.NEGATIVE_Y);
break;
case "py":
camera.lookAt(Vector3.POSITIVE_Y, Vector3.POSITIVE_Z);
break;
case "ny":
camera.lookAt(Vector3.NEGATIVE_Y, Vector3.NEGATIVE_Z);
break;
case "pz":
camera.lookAt(Vector3.POSITIVE_Z, Vector3.NEGATIVE_Y);
break;
case "nz":
camera.lookAt(Vector3.NEGATIVE_Z, Vector3.NEGATIVE_Y);
break;
}
light.getWorldPosition(camera.position);
camera.update();
return camera;
},
_getDirectionalLightCamera: function() {
var lightViewMatrix = new Matrix4();
var sceneViewBoundingBox = new BoundingBox();
var lightViewBBox = new BoundingBox();
return function(light, scene, sceneCamera) {
if (!this._lightCameras.directional) {
this._lightCameras.directional = new OrthoCamera();
}
var camera = this._lightCameras.directional;
sceneViewBoundingBox.copy(scene.viewBoundingBoxLastFrame);
sceneViewBoundingBox.intersection(sceneCamera.frustum.boundingBox);
camera.position.copy(sceneViewBoundingBox.min).add(sceneViewBoundingBox.max).scale(0.5).transformMat4(sceneCamera.worldTransform);
camera.rotation.copy(light.rotation);
camera.scale.copy(light.scale);
camera.updateWorldTransform();
Matrix4.invert(lightViewMatrix, camera.worldTransform);
Matrix4.multiply(lightViewMatrix, lightViewMatrix, sceneCamera.worldTransform);
lightViewBBox.copy(sceneViewBoundingBox).applyTransform(lightViewMatrix);
var min = lightViewBBox.min.array;
var max = lightViewBBox.max.array;
camera.position.set((min[0] + max[0]) / 2, (min[1] + max[1]) / 2, max[2]).transformMat4(camera.worldTransform);
camera.near = 0;
camera.far = -min[2] + max[2];
if (isNaN(this.lightFrustumBias)) {
camera.far *= 4;
} else {
camera.far += this.lightFrustumBias;
}
camera.left = min[0];
camera.right = max[0];
camera.top = max[1];
camera.bottom = min[1];
camera.update(true);
return camera;
};
}(),
_getSpotLightCamera: function(light) {
if (!this._lightCameras.spot) {
this._lightCameras.spot = new PerspectiveCamera();
}
var camera = this._lightCameras.spot;
camera.fov = light.penumbraAngle * 2;
camera.far = light.range;
camera.worldTransform.copy(light.worldTransform);
camera.updateProjectionMatrix();
mat4.invert(camera.viewMatrix.array, camera.worldTransform.array);
return camera;
},
dispose: function(renderer) {
var _gl = renderer.gl || renderer;
if (this._frameBuffer) {
this._frameBuffer.dispose(_gl);
}
for (var name in this._textures) {
this._textures[name].dispose(_gl);
}
this._texturePool.clear(renderer.gl);
this._depthMaterials = {};
this._distanceMaterials = {};
this._textures = {};
this._lightCameras = {};
this._shadowMapNumber = {
"POINT_LIGHT": 0,
"DIRECTIONAL_LIGHT": 0,
"SPOT_LIGHT": 0
};
this._meshMaterials = {};
for (var i = 0; i < this._receivers.length; i++) {
var mesh = this._receivers[i];
if (mesh.material) {
var material = mesh.material;
material.undefine("fragment", "POINT_LIGHT_SHADOW_COUNT");
material.undefine("fragment", "DIRECTIONAL_LIGHT_SHADOW_COUNT");
material.undefine("fragment", "AMBIENT_LIGHT_SHADOW_COUNT");
material.set("shadowEnabled", 0);
}
}
this._receivers = [];
this._lightsCastShadow = [];
}
});
ShadowMapPass.VSM = 1;
ShadowMapPass.PCF = 2;
var ShadowMapPass$1 = ShadowMapPass;
export { ShadowMapPass$1 as default };