{"version":3,"file":"CSM.cjs","sources":["../../src/csm/CSM.js"],"sourcesContent":["import { Vector2, Vector3, DirectionalLight, MathUtils, ShaderChunk, Matrix4, Box3 } from 'three'\nimport { CSMFrustum } from './CSMFrustum'\nimport { CSMShader } from './CSMShader'\n\nconst _cameraToLightMatrix = /* @__PURE__ */ new Matrix4()\nconst _lightSpaceFrustum = /* @__PURE__ */ new CSMFrustum()\nconst _center = /* @__PURE__ */ new Vector3()\nconst _bbox = /* @__PURE__ */ new Box3()\nconst _uniformArray = []\nconst _logArray = []\n\nexport class CSM {\n constructor(data) {\n data = data || {}\n\n this.camera = data.camera\n this.parent = data.parent\n this.cascades = data.cascades || 3\n this.maxFar = data.maxFar || 100000\n this.mode = data.mode || 'practical'\n this.shadowMapSize = data.shadowMapSize || 2048\n this.shadowBias = data.shadowBias || 0.000001\n this.lightDirection = data.lightDirection || new Vector3(1, -1, 1).normalize()\n this.lightIntensity = data.lightIntensity || 1\n this.lightNear = data.lightNear || 1\n this.lightFar = data.lightFar || 2000\n this.lightMargin = data.lightMargin || 200\n this.customSplitsCallback = data.customSplitsCallback\n this.fade = false\n this.mainFrustum = new CSMFrustum()\n this.frustums = []\n this.breaks = []\n\n this.lights = []\n this.shaders = new Map()\n\n this.createLights()\n this.updateFrustums()\n this.injectInclude()\n }\n\n createLights() {\n for (let i = 0; i < this.cascades; i++) {\n const light = new DirectionalLight(0xffffff, this.lightIntensity)\n light.castShadow = true\n light.shadow.mapSize.width = this.shadowMapSize\n light.shadow.mapSize.height = this.shadowMapSize\n\n light.shadow.camera.near = this.lightNear\n light.shadow.camera.far = this.lightFar\n light.shadow.bias = this.shadowBias\n\n this.parent.add(light)\n this.parent.add(light.target)\n this.lights.push(light)\n }\n }\n\n initCascades() {\n const camera = this.camera\n camera.updateProjectionMatrix()\n this.mainFrustum.setFromProjectionMatrix(camera.projectionMatrix, this.maxFar)\n this.mainFrustum.split(this.breaks, this.frustums)\n }\n\n updateShadowBounds() {\n const frustums = this.frustums\n for (let i = 0; i < frustums.length; i++) {\n const light = this.lights[i]\n const shadowCam = light.shadow.camera\n const frustum = this.frustums[i]\n\n // Get the two points that represent that furthest points on the frustum assuming\n // that's either the diagonal across the far plane or the diagonal across the whole\n // frustum itself.\n const nearVerts = frustum.vertices.near\n const farVerts = frustum.vertices.far\n const point1 = farVerts[0]\n let point2\n if (point1.distanceTo(farVerts[2]) > point1.distanceTo(nearVerts[2])) {\n point2 = farVerts[2]\n } else {\n point2 = nearVerts[2]\n }\n\n let squaredBBWidth = point1.distanceTo(point2)\n if (this.fade) {\n // expand the shadow extents by the fade margin if fade is enabled.\n const camera = this.camera\n const far = Math.max(camera.far, this.maxFar)\n const linearDepth = frustum.vertices.far[0].z / (far - camera.near)\n const margin = 0.25 * Math.pow(linearDepth, 2.0) * (far - camera.near)\n\n squaredBBWidth += margin\n }\n\n shadowCam.left = -squaredBBWidth / 2\n shadowCam.right = squaredBBWidth / 2\n shadowCam.top = squaredBBWidth / 2\n shadowCam.bottom = -squaredBBWidth / 2\n shadowCam.updateProjectionMatrix()\n }\n }\n\n getBreaks() {\n const camera = this.camera\n const far = Math.min(camera.far, this.maxFar)\n this.breaks.length = 0\n\n switch (this.mode) {\n case 'uniform':\n uniformSplit(this.cascades, camera.near, far, this.breaks)\n break\n case 'logarithmic':\n logarithmicSplit(this.cascades, camera.near, far, this.breaks)\n break\n case 'practical':\n practicalSplit(this.cascades, camera.near, far, 0.5, this.breaks)\n break\n case 'custom':\n if (this.customSplitsCallback === undefined) console.error('CSM: Custom split scheme callback not defined.')\n this.customSplitsCallback(this.cascades, camera.near, far, this.breaks)\n break\n }\n\n function uniformSplit(amount, near, far, target) {\n for (let i = 1; i < amount; i++) {\n target.push((near + ((far - near) * i) / amount) / far)\n }\n\n target.push(1)\n }\n\n function logarithmicSplit(amount, near, far, target) {\n for (let i = 1; i < amount; i++) {\n target.push((near * (far / near) ** (i / amount)) / far)\n }\n\n target.push(1)\n }\n\n function practicalSplit(amount, near, far, lambda, target) {\n _uniformArray.length = 0\n _logArray.length = 0\n logarithmicSplit(amount, near, far, _logArray)\n uniformSplit(amount, near, far, _uniformArray)\n\n for (let i = 1; i < amount; i++) {\n target.push(MathUtils.lerp(_uniformArray[i - 1], _logArray[i - 1], lambda))\n }\n\n target.push(1)\n }\n }\n\n update() {\n const camera = this.camera\n const frustums = this.frustums\n for (let i = 0; i < frustums.length; i++) {\n const light = this.lights[i]\n const shadowCam = light.shadow.camera\n const texelWidth = (shadowCam.right - shadowCam.left) / this.shadowMapSize\n const texelHeight = (shadowCam.top - shadowCam.bottom) / this.shadowMapSize\n light.shadow.camera.updateMatrixWorld(true)\n _cameraToLightMatrix.multiplyMatrices(light.shadow.camera.matrixWorldInverse, camera.matrixWorld)\n frustums[i].toSpace(_cameraToLightMatrix, _lightSpaceFrustum)\n\n const nearVerts = _lightSpaceFrustum.vertices.near\n const farVerts = _lightSpaceFrustum.vertices.far\n _bbox.makeEmpty()\n for (let j = 0; j < 4; j++) {\n _bbox.expandByPoint(nearVerts[j])\n _bbox.expandByPoint(farVerts[j])\n }\n\n _bbox.getCenter(_center)\n _center.z = _bbox.max.z + this.lightMargin\n _center.x = Math.floor(_center.x / texelWidth) * texelWidth\n _center.y = Math.floor(_center.y / texelHeight) * texelHeight\n _center.applyMatrix4(light.shadow.camera.matrixWorld)\n\n light.position.copy(_center)\n light.target.position.copy(_center)\n\n light.target.position.x += this.lightDirection.x\n light.target.position.y += this.lightDirection.y\n light.target.position.z += this.lightDirection.z\n }\n }\n\n injectInclude() {\n ShaderChunk.lights_fragment_begin = CSMShader.lights_fragment_begin\n ShaderChunk.lights_pars_begin = CSMShader.lights_pars_begin\n }\n\n setupMaterial(material) {\n material.defines = material.defines || {}\n material.defines.USE_CSM = 1\n material.defines.CSM_CASCADES = this.cascades\n\n if (this.fade) {\n material.defines.CSM_FADE = ''\n }\n\n const breaksVec2 = []\n const scope = this\n const shaders = this.shaders\n\n material.onBeforeCompile = function (shader) {\n const far = Math.min(scope.camera.far, scope.maxFar)\n scope.getExtendedBreaks(breaksVec2)\n\n shader.uniforms.CSM_cascades = { value: breaksVec2 }\n shader.uniforms.cameraNear = { value: scope.camera.near }\n shader.uniforms.shadowFar = { value: far }\n\n shaders.set(material, shader)\n }\n\n shaders.set(material, null)\n }\n\n updateUniforms() {\n const far = Math.min(this.camera.far, this.maxFar)\n const shaders = this.shaders\n\n shaders.forEach(function (shader, material) {\n if (shader !== null) {\n const uniforms = shader.uniforms\n this.getExtendedBreaks(uniforms.CSM_cascades.value)\n uniforms.cameraNear.value = this.camera.near\n uniforms.shadowFar.value = far\n }\n\n if (!this.fade && 'CSM_FADE' in material.defines) {\n delete material.defines.CSM_FADE\n material.needsUpdate = true\n } else if (this.fade && !('CSM_FADE' in material.defines)) {\n material.defines.CSM_FADE = ''\n material.needsUpdate = true\n }\n }, this)\n }\n\n getExtendedBreaks(target) {\n while (target.length < this.breaks.length) {\n target.push(new Vector2())\n }\n\n target.length = this.breaks.length\n\n for (let i = 0; i < this.cascades; i++) {\n const amount = this.breaks[i]\n const prev = this.breaks[i - 1] || 0\n target[i].x = prev\n target[i].y = amount\n }\n }\n\n updateFrustums() {\n this.getBreaks()\n this.initCascades()\n this.updateShadowBounds()\n this.updateUniforms()\n }\n\n remove() {\n for (let i = 0; i < this.lights.length; i++) {\n this.parent.remove(this.lights[i])\n }\n }\n\n dispose() {\n const shaders = this.shaders\n shaders.forEach(function (shader, material) {\n delete material.onBeforeCompile\n delete material.defines.USE_CSM\n delete material.defines.CSM_CASCADES\n delete material.defines.CSM_FADE\n\n if (shader !== null) {\n delete shader.uniforms.CSM_cascades\n delete shader.uniforms.cameraNear\n delete shader.uniforms.shadowFar\n }\n\n material.needsUpdate = true\n })\n shaders.clear()\n }\n}\n"],"names":["Matrix4","CSMFrustum","Vector3","Box3","DirectionalLight","far","MathUtils","ShaderChunk","CSMShader","Vector2"],"mappings":"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"}