From 8b06406bfbde7b6ecd41f3f3b7d657d61d44d230 Mon Sep 17 00:00:00 2001 From: Felix Herbst Date: Fri, 21 Aug 2026 15:10:58 +0200 Subject: [PATCH 1/5] FBXLoader: Use global `URL` instead of `window.URL`. (#34328) --- examples/jsm/loaders/FBXLoader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/jsm/loaders/FBXLoader.js b/examples/jsm/loaders/FBXLoader.js index 411d99b8cbd632..23adc69e9faf63 100644 --- a/examples/jsm/loaders/FBXLoader.js +++ b/examples/jsm/loaders/FBXLoader.js @@ -378,7 +378,7 @@ class FBXTreeParser { } else { // Binary Format const array = new Uint8Array( content ); - return window.URL.createObjectURL( new Blob( [ array ], { type: type } ) ); + return URL.createObjectURL( new Blob( [ array ], { type: type } ) ); } From 7615db5d3dc8caba6a1ef510e466be0e2fd03e9f Mon Sep 17 00:00:00 2001 From: mrdoob Date: Fri, 21 Aug 2026 22:34:48 +0900 Subject: [PATCH 2/5] CI: Add Core to bundle size report. (#34330) Co-authored-by: Claude Fable 5 --- .github/workflows/read-size.yml | 7 ++++++- .github/workflows/report-size.yml | 30 ++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/.github/workflows/read-size.yml b/.github/workflows/read-size.yml index fdfaf26dbe4382..80e7d4b08ca165 100644 --- a/.github/workflows/read-size.yml +++ b/.github/workflows/read-size.yml @@ -38,10 +38,15 @@ jobs: id: read-size run: | # minify the builds to measure their size + npx terser build/three.core.js --module --compress --mangle --output build/three.core.min.js npx terser build/three.module.js --module --compress --mangle --output build/three.module.min.js npx terser build/three.webgpu.js --module --compress --mangle --output build/three.webgpu.min.js npx terser build/three.webgpu.nodes.js --module --compress --mangle --output build/three.webgpu.nodes.min.js + CORE_FILESIZE=$(stat --format=%s build/three.core.min.js) + gzip -k build/three.core.min.js + CORE_FILESIZE_GZIP=$(stat --format=%s build/three.core.min.js.gz) + WEBGL_FILESIZE=$(stat --format=%s build/three.module.min.js) gzip -k build/three.module.min.js WEBGL_FILESIZE_GZIP=$(stat --format=%s build/three.module.min.js.gz) @@ -66,7 +71,7 @@ jobs: PR=${{ github.event.pull_request.number }} # write the output in a json file to upload it as artifact - node -pe "JSON.stringify({ filesize: $WEBGL_FILESIZE, gzip: $WEBGL_FILESIZE_GZIP, treeshaken: $WEBGL_TREESHAKEN, treeshakenGzip: $WEBGL_TREESHAKEN_GZIP, filesize2: $WEBGPU_FILESIZE, gzip2: $WEBGPU_FILESIZE_GZIP, treeshaken2: $WEBGPU_TREESHAKEN, treeshakenGzip2: $WEBGPU_TREESHAKEN_GZIP, filesize3: $WEBGPU_NODES_FILESIZE, gzip3: $WEBGPU_NODES_FILESIZE_GZIP, treeshaken3: $WEBGPU_NODES_TREESHAKEN, treeshakenGzip3: $WEBGPU_NODES_TREESHAKEN_GZIP, pr: $PR })" > sizes.json + node -pe "JSON.stringify({ coreFilesize: $CORE_FILESIZE, coreGzip: $CORE_FILESIZE_GZIP, filesize: $WEBGL_FILESIZE, gzip: $WEBGL_FILESIZE_GZIP, treeshaken: $WEBGL_TREESHAKEN, treeshakenGzip: $WEBGL_TREESHAKEN_GZIP, filesize2: $WEBGPU_FILESIZE, gzip2: $WEBGPU_FILESIZE_GZIP, treeshaken2: $WEBGPU_TREESHAKEN, treeshakenGzip2: $WEBGPU_TREESHAKEN_GZIP, filesize3: $WEBGPU_NODES_FILESIZE, gzip3: $WEBGPU_NODES_FILESIZE_GZIP, treeshaken3: $WEBGPU_NODES_TREESHAKEN, treeshakenGzip3: $WEBGPU_NODES_TREESHAKEN_GZIP, pr: $PR })" > sizes.json - name: Upload artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: diff --git a/.github/workflows/report-size.yml b/.github/workflows/report-size.yml index 84aec2a467596d..56ad6d59cc1030 100644 --- a/.github/workflows/report-size.yml +++ b/.github/workflows/report-size.yml @@ -74,10 +74,15 @@ jobs: id: read-size run: | # minify the builds to measure their size + npx terser build/three.core.js --module --compress --mangle --output build/three.core.min.js npx terser build/three.module.js --module --compress --mangle --output build/three.module.min.js npx terser build/three.webgpu.js --module --compress --mangle --output build/three.webgpu.min.js npx terser build/three.webgpu.nodes.js --module --compress --mangle --output build/three.webgpu.nodes.min.js + CORE_FILESIZE_BASE=$(stat --format=%s build/three.core.min.js) + gzip -k build/three.core.min.js + CORE_FILESIZE_BASE_GZIP=$(stat --format=%s build/three.core.min.js.gz) + WEBGL_FILESIZE_BASE=$(stat --format=%s build/three.module.min.js) gzip -k build/three.module.min.js WEBGL_FILESIZE_BASE_GZIP=$(stat --format=%s build/three.module.min.js.gz) @@ -100,6 +105,12 @@ jobs: WEBGPU_NODES_TREESHAKEN_BASE_GZIP=$(stat --format=%s test/treeshake/index.webgpu.nodes.bundle.min.js.gz) # log to console + echo "CORE_FILESIZE_BASE=$CORE_FILESIZE_BASE" + echo "CORE_FILESIZE_BASE_GZIP=$CORE_FILESIZE_BASE_GZIP" + + echo "CORE_FILESIZE_BASE=$CORE_FILESIZE_BASE" >> $GITHUB_OUTPUT + echo "CORE_FILESIZE_BASE_GZIP=$CORE_FILESIZE_BASE_GZIP" >> $GITHUB_OUTPUT + echo "WEBGL_FILESIZE_BASE=$WEBGL_FILESIZE_BASE" echo "WEBGL_FILESIZE_BASE_GZIP=$WEBGL_FILESIZE_BASE_GZIP" echo "WEBGL_TREESHAKEN_BASE=$WEBGL_TREESHAKEN_BASE" @@ -135,6 +146,10 @@ jobs: # It's important these are passed as env variables. # https://securitylab.github.com/research/github-actions-untrusted-input/ env: + CORE_FILESIZE: ${{ fromJSON(steps.download-artifact.outputs.result).coreFilesize }} + CORE_FILESIZE_GZIP: ${{ fromJSON(steps.download-artifact.outputs.result).coreGzip }} + CORE_FILESIZE_BASE: ${{ steps.read-size.outputs.CORE_FILESIZE_BASE }} + CORE_FILESIZE_BASE_GZIP: ${{ steps.read-size.outputs.CORE_FILESIZE_BASE_GZIP }} WEBGL_FILESIZE: ${{ fromJSON(steps.download-artifact.outputs.result).filesize }} WEBGL_FILESIZE_GZIP: ${{ fromJSON(steps.download-artifact.outputs.result).gzip }} WEBGL_FILESIZE_BASE: ${{ steps.read-size.outputs.WEBGL_FILESIZE_BASE }} @@ -160,6 +175,13 @@ jobs: WEBGPU_NODES_TREESHAKEN_BASE: ${{ steps.read-size.outputs.WEBGPU_NODES_TREESHAKEN_BASE }} WEBGPU_NODES_TREESHAKEN_BASE_GZIP: ${{ steps.read-size.outputs.WEBGPU_NODES_TREESHAKEN_BASE_GZIP }} run: | + CORE_FILESIZE_FORM=$(node ./test/treeshake/utils/format-size.js "$CORE_FILESIZE") + CORE_FILESIZE_GZIP_FORM=$(node ./test/treeshake/utils/format-size.js "$CORE_FILESIZE_GZIP") + CORE_FILESIZE_BASE_FORM=$(node ./test/treeshake/utils/format-size.js "$CORE_FILESIZE_BASE") + CORE_FILESIZE_BASE_GZIP_FORM=$(node ./test/treeshake/utils/format-size.js "$CORE_FILESIZE_BASE_GZIP") + CORE_FILESIZE_DIFF=$(node ./test/treeshake/utils/format-diff.js "$CORE_FILESIZE" "$CORE_FILESIZE_BASE") + CORE_FILESIZE_DIFF_GZIP=$(node ./test/treeshake/utils/format-diff.js "$CORE_FILESIZE_GZIP" "$CORE_FILESIZE_BASE_GZIP") + WEBGL_FILESIZE_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGL_FILESIZE") WEBGL_FILESIZE_GZIP_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGL_FILESIZE_GZIP") WEBGL_FILESIZE_BASE_FORM=$(node ./test/treeshake/utils/format-size.js "$WEBGL_FILESIZE_BASE") @@ -202,6 +224,13 @@ jobs: WEBGPU_NODES_TREESHAKEN_DIFF=$(node ./test/treeshake/utils/format-diff.js "$WEBGPU_NODES_TREESHAKEN" "$WEBGPU_NODES_TREESHAKEN_BASE") WEBGPU_NODES_TREESHAKEN_DIFF_GZIP=$(node ./test/treeshake/utils/format-diff.js "$WEBGPU_NODES_TREESHAKEN_GZIP" "$WEBGPU_NODES_TREESHAKEN_BASE_GZIP") + echo "CORE_FILESIZE=$CORE_FILESIZE_FORM" >> $GITHUB_OUTPUT + echo "CORE_FILESIZE_GZIP=$CORE_FILESIZE_GZIP_FORM" >> $GITHUB_OUTPUT + echo "CORE_FILESIZE_BASE=$CORE_FILESIZE_BASE_FORM" >> $GITHUB_OUTPUT + echo "CORE_FILESIZE_BASE_GZIP=$CORE_FILESIZE_BASE_GZIP_FORM" >> $GITHUB_OUTPUT + echo "CORE_FILESIZE_DIFF=$CORE_FILESIZE_DIFF" >> $GITHUB_OUTPUT + echo "CORE_FILESIZE_DIFF_GZIP=$CORE_FILESIZE_DIFF_GZIP" >> $GITHUB_OUTPUT + echo "WEBGL_FILESIZE=$WEBGL_FILESIZE_FORM" >> $GITHUB_OUTPUT echo "WEBGL_FILESIZE_GZIP=$WEBGL_FILESIZE_GZIP_FORM" >> $GITHUB_OUTPUT echo "WEBGL_FILESIZE_BASE=$WEBGL_FILESIZE_BASE_FORM" >> $GITHUB_OUTPUT @@ -264,6 +293,7 @@ jobs: || Before | After | Diff | |:-:|:-:|:-:|:-:| + | Core | ${{ steps.format.outputs.CORE_FILESIZE_BASE }}
**${{ steps.format.outputs.CORE_FILESIZE_BASE_GZIP }}** | ${{ steps.format.outputs.CORE_FILESIZE }}
**${{ steps.format.outputs.CORE_FILESIZE_GZIP }}** | ${{ steps.format.outputs.CORE_FILESIZE_DIFF }}
**${{ steps.format.outputs.CORE_FILESIZE_DIFF_GZIP }}** | | WebGL | ${{ steps.format.outputs.WEBGL_FILESIZE_BASE }}
**${{ steps.format.outputs.WEBGL_FILESIZE_BASE_GZIP }}** | ${{ steps.format.outputs.WEBGL_FILESIZE }}
**${{ steps.format.outputs.WEBGL_FILESIZE_GZIP }}** | ${{ steps.format.outputs.WEBGL_FILESIZE_DIFF }}
**${{ steps.format.outputs.WEBGL_FILESIZE_DIFF_GZIP }}** | | WebGPU | ${{ steps.format.outputs.WEBGPU_FILESIZE_BASE }}
**${{ steps.format.outputs.WEBGPU_FILESIZE_BASE_GZIP }}** | ${{ steps.format.outputs.WEBGPU_FILESIZE }}
**${{ steps.format.outputs.WEBGPU_FILESIZE_GZIP }}** | ${{ steps.format.outputs.WEBGPU_FILESIZE_DIFF }}
**${{ steps.format.outputs.WEBGPU_FILESIZE_DIFF_GZIP }}** | | WebGPU Nodes | ${{ steps.format.outputs.WEBGPU_NODES_FILESIZE_BASE }}
**${{ steps.format.outputs.WEBGPU_NODES_FILESIZE_BASE_GZIP }}** | ${{ steps.format.outputs.WEBGPU_NODES_FILESIZE }}
**${{ steps.format.outputs.WEBGPU_NODES_FILESIZE_GZIP }}** | ${{ steps.format.outputs.WEBGPU_NODES_FILESIZE_DIFF }}
**${{ steps.format.outputs.WEBGPU_NODES_FILESIZE_DIFF_GZIP }}** | From 47f6bcb7a37e764c458a38d8da2be51ac74f6c19 Mon Sep 17 00:00:00 2001 From: mrdoob Date: Fri, 21 Aug 2026 22:59:05 +0900 Subject: [PATCH 3/5] SunLight: Move to addons. (#34326) Co-authored-by: Claude Fable 5 --- {src => examples/jsm}/lights/SunLight.js | 4 +- .../jsm}/lights/SunLightShadow.js | 15 +- examples/webgl_animation_multiple.html | 3 +- ..._animation_skinning_additive_blending.html | 3 +- .../webgl_animation_skinning_blending.html | 3 +- examples/webgl_animation_walk.html | 3 +- examples/webgl_gpgpu_water.html | 3 +- examples/webgl_instancing_morph.html | 3 +- examples/webgl_lightprobes_sponza.html | 3 +- examples/webgl_lights_sunlight.html | 3 +- examples/webgl_loader_3mf_materials.html | 3 +- examples/webgl_loader_fbx.html | 3 +- examples/webgl_loader_md2_control.html | 3 +- examples/webgl_postprocessing_outline.html | 3 +- examples/webgl_shadowmap_performance.html | 3 +- src/Three.Core.js | 2 +- src/loaders/ObjectLoader.js | 7 - test/unit/src/lights/SunLight.tests.js | 80 ------ test/unit/src/lights/SunLightShadow.tests.js | 271 ------------------ test/unit/three.source.unit.js | 2 - 20 files changed, 38 insertions(+), 382 deletions(-) rename {src => examples/jsm}/lights/SunLight.js (93%) rename {src => examples/jsm}/lights/SunLightShadow.js (96%) delete mode 100644 test/unit/src/lights/SunLight.tests.js delete mode 100644 test/unit/src/lights/SunLightShadow.tests.js diff --git a/src/lights/SunLight.js b/examples/jsm/lights/SunLight.js similarity index 93% rename from src/lights/SunLight.js rename to examples/jsm/lights/SunLight.js index 189a50d4ced37b..30ad955a158ee4 100644 --- a/src/lights/SunLight.js +++ b/examples/jsm/lights/SunLight.js @@ -1,6 +1,5 @@ -import { Light } from './Light.js'; +import { Light, Object3D } from 'three'; import { SunLightShadow } from './SunLightShadow.js'; -import { Object3D } from '../core/Object3D.js'; /** * A sun-like light that gets emitted in a specific direction, with rays that @@ -23,6 +22,7 @@ import { Object3D } from '../core/Object3D.js'; * use {@link DirectionalLight} with `CSMShadowNode` instead. * * @augments Light + * @three_import import { SunLight } from 'three/addons/lights/SunLight.js'; */ class SunLight extends Light { diff --git a/src/lights/SunLightShadow.js b/examples/jsm/lights/SunLightShadow.js similarity index 96% rename from src/lights/SunLightShadow.js rename to examples/jsm/lights/SunLightShadow.js index bd4f791ceed6f9..47b0abd930ad14 100644 --- a/src/lights/SunLightShadow.js +++ b/examples/jsm/lights/SunLightShadow.js @@ -1,9 +1,11 @@ -import { LightShadow } from './LightShadow.js'; -import { OrthographicCamera } from '../cameras/OrthographicCamera.js'; -import { Frustum } from '../math/Frustum.js'; -import { Matrix4 } from '../math/Matrix4.js'; -import { Vector3 } from '../math/Vector3.js'; -import { Vector4 } from '../math/Vector4.js'; +import { + Frustum, + LightShadow, + Matrix4, + OrthographicCamera, + Vector3, + Vector4 +} from 'three'; const _lightOrientationMatrix = /*@__PURE__*/ new Matrix4(); const _viewToLightMatrix = /*@__PURE__*/ new Matrix4(); @@ -56,6 +58,7 @@ const _cascadeFade = 0.1; * The default `mapSize` is `1024x1024` per cascade. * * @augments LightShadow + * @three_import import { SunLightShadow } from 'three/addons/lights/SunLightShadow.js'; */ class SunLightShadow extends LightShadow { diff --git a/examples/webgl_animation_multiple.html b/examples/webgl_animation_multiple.html index 87233925bee5b7..f970e632df42b9 100644 --- a/examples/webgl_animation_multiple.html +++ b/examples/webgl_animation_multiple.html @@ -29,6 +29,7 @@ import * as THREE from 'three'; + import { SunLight } from 'three/addons/lights/SunLight.js'; import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; import * as SkeletonUtils from 'three/addons/utils/SkeletonUtils.js'; import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; @@ -61,7 +62,7 @@ hemiLight.position.set( 0, 20, 0 ); scene.add( hemiLight ); - const sunLight = new THREE.SunLight( 0xffffff, 3 ); + const sunLight = new SunLight( 0xffffff, 3 ); sunLight.position.set( - 3, 10, - 10 ); sunLight.castShadow = true; sunLight.shadow.camera.far = 20; diff --git a/examples/webgl_animation_skinning_additive_blending.html b/examples/webgl_animation_skinning_additive_blending.html index 36f3725be13f22..3ec59e04ef25dd 100644 --- a/examples/webgl_animation_skinning_additive_blending.html +++ b/examples/webgl_animation_skinning_additive_blending.html @@ -40,6 +40,7 @@ import Stats from 'three/addons/libs/stats.module.js'; import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; + import { SunLight } from 'three/addons/lights/SunLight.js'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; @@ -79,7 +80,7 @@ hemiLight.position.set( 0, 20, 0 ); scene.add( hemiLight ); - const sunLight = new THREE.SunLight( 0xffffff, 3 ); + const sunLight = new SunLight( 0xffffff, 3 ); sunLight.position.set( 3, 10, 10 ); sunLight.castShadow = true; sunLight.shadow.camera.far = 20; diff --git a/examples/webgl_animation_skinning_blending.html b/examples/webgl_animation_skinning_blending.html index db4df6bec73913..02a201e7691644 100644 --- a/examples/webgl_animation_skinning_blending.html +++ b/examples/webgl_animation_skinning_blending.html @@ -39,6 +39,7 @@ import Stats from 'three/addons/libs/stats.module.js'; import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; + import { SunLight } from 'three/addons/lights/SunLight.js'; import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; let scene, renderer, camera, stats; @@ -74,7 +75,7 @@ hemiLight.position.set( 0, 20, 0 ); scene.add( hemiLight ); - const sunLight = new THREE.SunLight( 0xffffff, 3 ); + const sunLight = new SunLight( 0xffffff, 3 ); sunLight.position.set( - 3, 10, - 10 ); sunLight.castShadow = true; sunLight.shadow.camera.far = 20; diff --git a/examples/webgl_animation_walk.html b/examples/webgl_animation_walk.html index a3e1c271b6232f..0787f0cbf104e1 100644 --- a/examples/webgl_animation_walk.html +++ b/examples/webgl_animation_walk.html @@ -36,6 +36,7 @@ import * as THREE from 'three'; + import { SunLight } from 'three/addons/lights/SunLight.js'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; @@ -91,7 +92,7 @@ group = new THREE.Group(); scene.add( group ); - const sunLight = new THREE.SunLight( 0xffffff, 5 ); + const sunLight = new SunLight( 0xffffff, 5 ); sunLight.position.set( - 2, 5, - 3 ); sunLight.castShadow = true; sunLight.shadow.camera.far = 20; diff --git a/examples/webgl_gpgpu_water.html b/examples/webgl_gpgpu_water.html index 71aa9f85d72d8a..ed20ac11d6d14b 100644 --- a/examples/webgl_gpgpu_water.html +++ b/examples/webgl_gpgpu_water.html @@ -145,6 +145,7 @@ import Stats from 'three/addons/libs/stats.module.js'; import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; + import { SunLight } from 'three/addons/lights/SunLight.js'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; import { GPUComputationRenderer } from 'three/addons/misc/GPUComputationRenderer.js'; @@ -216,7 +217,7 @@ scene = new THREE.Scene(); - sun = new THREE.SunLight( 0xFFFFFF, 4.0 ); + sun = new SunLight( 0xFFFFFF, 4.0 ); sun.position.set( - 1, 2.6, 1.4 ); scene.add( sun ); diff --git a/examples/webgl_instancing_morph.html b/examples/webgl_instancing_morph.html index ba3532303faa6a..237be093fc6dba 100644 --- a/examples/webgl_instancing_morph.html +++ b/examples/webgl_instancing_morph.html @@ -24,6 +24,7 @@ import * as THREE from 'three'; + import { SunLight } from 'three/addons/lights/SunLight.js'; import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; import Stats from 'three/addons/libs/stats.module.js'; @@ -55,7 +56,7 @@ scene.fog = new THREE.Fog( 0x99DDFF, 5000, 10000 ); - const light = new THREE.SunLight( 0xffffff, 2 ); + const light = new SunLight( 0xffffff, 2 ); light.position.set( 200, 1000, 50 ); diff --git a/examples/webgl_lightprobes_sponza.html b/examples/webgl_lightprobes_sponza.html index 922de361952266..ad2d205e78b0fd 100644 --- a/examples/webgl_lightprobes_sponza.html +++ b/examples/webgl_lightprobes_sponza.html @@ -32,6 +32,7 @@ import * as THREE from 'three'; + import { SunLight } from 'three/addons/lights/SunLight.js'; import { FirstPersonControls } from 'three/addons/controls/FirstPersonControls.js'; import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; @@ -137,7 +138,7 @@ let isBaking = false; let bakeQueued = false; - sunLight = new THREE.SunLight( 0xfff2dc, 100.0 ); + sunLight = new SunLight( 0xfff2dc, 100.0 ); sunLight.castShadow = true; sunLight.shadow.camera.far = 50; sunLight.shadow.mapSize.setScalar( 2048 ); diff --git a/examples/webgl_lights_sunlight.html b/examples/webgl_lights_sunlight.html index 0c855796ae566c..51067c33de860f 100644 --- a/examples/webgl_lights_sunlight.html +++ b/examples/webgl_lights_sunlight.html @@ -31,6 +31,7 @@ import * as THREE from 'three'; + import { SunLight } from 'three/addons/lights/SunLight.js'; import { FirstPersonControls } from 'three/addons/controls/FirstPersonControls.js'; import { Sky } from 'three/addons/objects/Sky.js'; import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; @@ -132,7 +133,7 @@ sky.material.uniforms.rayleigh.value = 2; sky.material.uniforms.showSunDisc.value = false; // the sun is represented by the light - sunLight = new THREE.SunLight(); + sunLight = new SunLight(); sunLight.castShadow = true; sunLight.shadow.camera.far = params.far; // maximum shadow distance sunLight.shadow.mapSize.setScalar( params.resolution ); diff --git a/examples/webgl_loader_3mf_materials.html b/examples/webgl_loader_3mf_materials.html index a0dac5fc4d70ea..fd9fd6d7bfa8ee 100644 --- a/examples/webgl_loader_3mf_materials.html +++ b/examples/webgl_loader_3mf_materials.html @@ -34,6 +34,7 @@ import * as THREE from 'three'; + import { SunLight } from 'three/addons/lights/SunLight.js'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; import { ThreeMFLoader } from 'three/addons/loaders/3MFLoader.js'; @@ -57,7 +58,7 @@ hemiLight.position.set( 0, 100, 0 ); scene.add( hemiLight ); - const sunLight = new THREE.SunLight( 0xffffff, 3 ); + const sunLight = new SunLight( 0xffffff, 3 ); sunLight.position.set( 0, 40, 50 ); sunLight.castShadow = true; sunLight.shadow.camera.far = 100; diff --git a/examples/webgl_loader_fbx.html b/examples/webgl_loader_fbx.html index f1e613f92241a5..2641eb196ece72 100644 --- a/examples/webgl_loader_fbx.html +++ b/examples/webgl_loader_fbx.html @@ -32,6 +32,7 @@ import Stats from 'three/addons/libs/stats.module.js'; + import { SunLight } from 'three/addons/lights/SunLight.js'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; import { FBXLoader } from 'three/addons/loaders/FBXLoader.js'; import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; @@ -90,7 +91,7 @@ hemiLight.position.set( 0, 200, 0 ); scene.add( hemiLight ); - const sunLight = new THREE.SunLight( 0xffffff, 5 ); + const sunLight = new SunLight( 0xffffff, 5 ); sunLight.position.set( 0, 200, 100 ); sunLight.castShadow = true; scene.add( sunLight ); diff --git a/examples/webgl_loader_md2_control.html b/examples/webgl_loader_md2_control.html index edff9fec2cbb0b..8de18e5f5899bc 100644 --- a/examples/webgl_loader_md2_control.html +++ b/examples/webgl_loader_md2_control.html @@ -41,6 +41,7 @@ import Stats from 'three/addons/libs/stats.module.js'; + import { SunLight } from 'three/addons/lights/SunLight.js'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; import { MD2CharacterComplex } from 'three/addons/misc/MD2CharacterComplex.js'; import { Gyroscope } from 'three/addons/misc/Gyroscope.js'; @@ -92,7 +93,7 @@ scene.add( new THREE.AmbientLight( 0x666666, 3 ) ); - const sunLight = new THREE.SunLight( 0xffffff, 7 ); + const sunLight = new SunLight( 0xffffff, 7 ); sunLight.position.set( 200, 450, 500 ); sunLight.castShadow = true; sunLight.shadow.camera.far = 2000; diff --git a/examples/webgl_postprocessing_outline.html b/examples/webgl_postprocessing_outline.html index 54b9973b6634bb..e192e5885eea07 100644 --- a/examples/webgl_postprocessing_outline.html +++ b/examples/webgl_postprocessing_outline.html @@ -31,6 +31,7 @@ import Stats from 'three/addons/libs/stats.module.js'; import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; + import { SunLight } from 'three/addons/lights/SunLight.js'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; import { OBJLoader } from 'three/addons/loaders/OBJLoader.js'; import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js'; @@ -151,7 +152,7 @@ scene.add( new THREE.AmbientLight( 0xaaaaaa, 0.6 ) ); - const light = new THREE.SunLight( 0xddffdd, 2 ); + const light = new SunLight( 0xddffdd, 2 ); light.position.set( 5, 5, 5 ); light.castShadow = true; light.shadow.camera.far = 40; diff --git a/examples/webgl_shadowmap_performance.html b/examples/webgl_shadowmap_performance.html index 6b96e126d2969a..3763ea2762b050 100644 --- a/examples/webgl_shadowmap_performance.html +++ b/examples/webgl_shadowmap_performance.html @@ -33,6 +33,7 @@ import Stats from 'three/addons/libs/stats.module.js'; + import { SunLight } from 'three/addons/lights/SunLight.js'; import { FirstPersonControls } from 'three/addons/controls/FirstPersonControls.js'; import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; import { FontLoader } from 'three/addons/loaders/FontLoader.js'; @@ -79,7 +80,7 @@ const ambient = new THREE.AmbientLight( 0xffffff ); scene.add( ambient ); - const sunLight = new THREE.SunLight( 0xffffff, 3 ); + const sunLight = new SunLight( 0xffffff, 3 ); sunLight.position.set( 0, 1500, 1000 ); sunLight.castShadow = true; sunLight.shadow.camera.far = FAR; diff --git a/src/Three.Core.js b/src/Three.Core.js index 211c3d49581798..458a9a84c763ab 100644 --- a/src/Three.Core.js +++ b/src/Three.Core.js @@ -60,10 +60,10 @@ export { SpotLight } from './lights/SpotLight.js'; export { PointLight } from './lights/PointLight.js'; export { RectAreaLight } from './lights/RectAreaLight.js'; export { HemisphereLight } from './lights/HemisphereLight.js'; -export { SunLight } from './lights/SunLight.js'; export { DirectionalLight } from './lights/DirectionalLight.js'; export { AmbientLight } from './lights/AmbientLight.js'; export { Light } from './lights/Light.js'; +export { LightShadow } from './lights/LightShadow.js'; export { LightProbe } from './lights/LightProbe.js'; export { StereoCamera } from './cameras/StereoCamera.js'; export { PerspectiveCamera } from './cameras/PerspectiveCamera.js'; diff --git a/src/loaders/ObjectLoader.js b/src/loaders/ObjectLoader.js index 56a9acf5cea24f..9be1220b963620 100644 --- a/src/loaders/ObjectLoader.js +++ b/src/loaders/ObjectLoader.js @@ -18,7 +18,6 @@ import { LinearMipmapLinearFilter } from '../constants.js'; import { InstancedBufferAttribute } from '../core/InstancedBufferAttribute.js'; -import { SunLight } from '../lights/SunLight.js'; import { Color } from '../math/Color.js'; import { Vector3 } from '../math/Vector3.js'; import { Object3D } from '../core/Object3D.js'; @@ -922,12 +921,6 @@ class ObjectLoader extends Loader { break; - case 'SunLight': - - object = new SunLight( data.color, data.intensity ); - - break; - case 'DirectionalLight': object = new DirectionalLight( data.color, data.intensity ); diff --git a/test/unit/src/lights/SunLight.tests.js b/test/unit/src/lights/SunLight.tests.js deleted file mode 100644 index 4aa1c0eb023dad..00000000000000 --- a/test/unit/src/lights/SunLight.tests.js +++ /dev/null @@ -1,80 +0,0 @@ -import { SunLight } from '../../../../src/lights/SunLight.js'; - -import { Light } from '../../../../src/lights/Light.js'; -import { ObjectLoader } from '../../../../src/loaders/ObjectLoader.js'; -import { Vector3 } from '../../../../src/math/Vector3.js'; - -export default QUnit.module( 'Lights', () => { - - QUnit.module( 'SunLight', () => { - - // INHERITANCE - QUnit.test( 'Extending', ( assert ) => { - - const object = new SunLight(); - assert.strictEqual( - object instanceof Light, true, - 'SunLight extends from Light' - ); - - } ); - - // INSTANCING - QUnit.test( 'Instancing', ( assert ) => { - - const object = new SunLight(); - assert.ok( object, 'Can instantiate a SunLight.' ); - - } ); - - // PROPERTIES - QUnit.test( 'type', ( assert ) => { - - const object = new SunLight(); - assert.ok( object.type === 'SunLight', 'SunLight.type should be SunLight' ); - - } ); - - QUnit.test( 'shadow', ( assert ) => { - - const object = new SunLight(); - assert.ok( object.shadow.isSunLightShadow, 'SunLight.shadow is a SunLightShadow' ); - - } ); - - // PUBLIC - QUnit.test( 'isSunLight', ( assert ) => { - - const object = new SunLight(); - assert.ok( object.isSunLight, 'SunLight.isSunLight should be true' ); - - } ); - - QUnit.test( 'position', ( assert ) => { - - const object = new SunLight(); - assert.ok( object.position.distanceTo( new Vector3( 0, 1, 0 ) ) < 1e-12, 'Shines straight down by default' ); - - } ); - - // OTHERS - QUnit.test( 'toJSON', ( assert ) => { - - const light = new SunLight( 0xffaa88, 2 ); - light.shadow.bias = 10; - light.position.setFromSphericalCoords( 1, 0.5, 1.2 ); - light.updateMatrix(); - - const json = light.toJSON(); - const newLight = new ObjectLoader().parse( json ); - - assert.ok( newLight.isSunLight, 'Reloaded light is a SunLight' ); - assert.ok( newLight.shadow.isSunLightShadow, 'Reloaded shadow is a SunLightShadow' ); - assert.ok( newLight.position.distanceTo( light.position ) < 1e-6, 'Reloaded light keeps its direction' ); - assert.smartEqual( newLight.shadow, light.shadow, 'Reloaded shadow is identical to the original one' ); - - } ); - - } ); - -} ); diff --git a/test/unit/src/lights/SunLightShadow.tests.js b/test/unit/src/lights/SunLightShadow.tests.js deleted file mode 100644 index 44cc1b616d6325..00000000000000 --- a/test/unit/src/lights/SunLightShadow.tests.js +++ /dev/null @@ -1,271 +0,0 @@ -import { SunLightShadow } from '../../../../src/lights/SunLightShadow.js'; - -import { LightShadow } from '../../../../src/lights/LightShadow.js'; -import { ObjectLoader } from '../../../../src/loaders/ObjectLoader.js'; -import { SunLight } from '../../../../src/lights/SunLight.js'; -import { PerspectiveCamera } from '../../../../src/cameras/PerspectiveCamera.js'; -import { OrthographicCamera } from '../../../../src/cameras/OrthographicCamera.js'; -import { Vector3 } from '../../../../src/math/Vector3.js'; - -export default QUnit.module( 'Lights', () => { - - QUnit.module( 'SunLightShadow', () => { - - // INHERITANCE - QUnit.test( 'Extending', ( assert ) => { - - const object = new SunLightShadow(); - assert.strictEqual( - object instanceof LightShadow, true, - 'SunLightShadow extends from LightShadow' - ); - - } ); - - // INSTANCING - QUnit.test( 'Instancing', ( assert ) => { - - const object = new SunLightShadow(); - assert.ok( object, 'Can instantiate a SunLightShadow.' ); - - } ); - - // PUBLIC - QUnit.test( 'isSunLightShadow', ( assert ) => { - - const object = new SunLightShadow(); - assert.ok( - object.isSunLightShadow, - 'SunLightShadow.isSunLightShadow should be true' - ); - - } ); - - QUnit.test( 'cascades', ( assert ) => { - - const light = new SunLight(); - const camera = new PerspectiveCamera( 60, 1, 0.1, 100 ); - const shadow = light.shadow; - light.position.setFromSphericalCoords( 1, Math.PI / 2 - 0.9, 0.7 ); - light.updateMatrixWorld(); - camera.updateMatrixWorld(); - - shadow.camera.far = 80; - shadow.updateMatrices( light, camera ); - - assert.strictEqual( shadow.getViewportCount(), 4, 'Creates four cascade viewports' ); - assert.deepEqual( shadow.getFrameExtents().toArray(), [ 2, 2 ], 'Uses a compact atlas layout' ); - assert.strictEqual( shadow._cascadeSplits.length, 5, 'Creates all cascade split boundaries' ); - assert.strictEqual( shadow._cascadeSplits[ 0 ], camera.near, 'Starts at the view camera near plane' ); - assert.strictEqual( shadow._cascadeSplits[ 4 ], shadow.camera.far, 'Ends at the shadow camera far plane' ); - - const orthographicCamera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 100 ); - orthographicCamera.updateMatrixWorld(); - shadow.updateMatrices( light, orthographicCamera ); - assert.ok( shadow._cascadeSplits.every( Number.isFinite ), 'Supports an orthographic view camera with a zero near plane' ); - - const infiniteCamera = new PerspectiveCamera( 60, 1, 0.1, 100 ); - infiniteCamera.projectionMatrix.elements[ 10 ] = - 1; - infiniteCamera.projectionMatrix.elements[ 14 ] = - 2 * infiniteCamera.near; - infiniteCamera.projectionMatrixInverse.copy( infiniteCamera.projectionMatrix ).invert(); - infiniteCamera.far = Infinity; - infiniteCamera.updateMatrixWorld(); - shadow.camera.far = 80; - shadow.updateMatrices( light, infiniteCamera ); - assert.ok( shadow._matrices.every( matrix => matrix.elements.every( Number.isFinite ) ), 'Supports an infinite-far projection matrix' ); - assert.strictEqual( shadow._cascadeSplits[ 4 ], shadow.camera.far, 'Falls back to the shadow camera for a non-finite view far plane' ); - - } ); - - QUnit.test( 'cascade fade', ( assert ) => { - - const light = new SunLight(); - const camera = new PerspectiveCamera( 60, 1, 0.1, 100 ); - const shadow = light.shadow; - light.position.setFromSphericalCoords( 1, Math.PI / 2 - 0.9, 0.7 ); - light.updateMatrixWorld(); - camera.updateMatrixWorld(); - - shadow.camera.far = 80; - shadow.updateMatrices( light, camera ); - - for ( let i = 0; i < 4; i ++ ) { - - const cascade = shadow._cascadeData[ i ]; - - assert.strictEqual( cascade.y, shadow._cascadeSplits[ i + 1 ], `Cascade ${i} ends at its split` ); - assert.ok( cascade.z < cascade.y && cascade.z >= shadow._cascadeSplits[ i ], `Cascade ${i} fades out within its own range` ); - - if ( i === 0 ) assert.ok( cascade.x < 0, 'First cascade is open below the near plane' ); - else assert.strictEqual( cascade.x, shadow._cascadeData[ i - 1 ].z, `Cascade ${i} begins where the previous fade starts` ); - - } - - } ); - - QUnit.test( 'cascade caster margin', ( assert ) => { - - const light = new SunLight(); - const camera = new PerspectiveCamera( 60, 1, 0.1, 100 ); - const shadow = light.shadow; - light.position.setFromSphericalCoords( 1, Math.PI / 2 - 0.9, 0.7 ); - light.updateMatrixWorld(); - camera.updateMatrixWorld(); - shadow.camera.far = 100; - shadow.updateMatrices( light, camera ); - - const lightDirection = light.position.clone().normalize().negate(); - - for ( let i = 0; i < 4; i ++ ) { - - const depth = ( shadow._cascadeSplits[ i ] + shadow._cascadeSplits[ i + 1 ] ) * 0.5; - const caster = new Vector3( 0, 0, - depth ).addScaledVector( lightDirection, - 90 ); - assert.ok( shadow.getFrustum( i ).containsPoint( caster ), `Cascade ${i} covers casters above the view frustum` ); - - } - - } ); - - QUnit.test( 'cascade containment', ( assert ) => { - - const light = new SunLight(); - const camera = new PerspectiveCamera( 60, 1, 0.01, 0.1 ); - const shadow = light.shadow; - light.position.setFromSphericalCoords( 1, Math.PI / 2 - 0.9, 0.7 ); - light.updateMatrixWorld(); - camera.updateMatrixWorld(); - shadow.camera.far = 1; - shadow.updateMatrices( light, camera ); - - for ( let i = 0; i < 4; i ++ ) { - - let containsSlice = true; - - for ( const depth of shadow._cascadeSplits.slice( i, i + 2 ) ) { - - const halfHeight = Math.tan( camera.fov * Math.PI / 360 ) * depth; - - for ( const x of [ - 1, 1 ] ) { - - for ( const y of [ - 1, 1 ] ) { - - containsSlice = containsSlice && shadow.getFrustum( i ).containsPoint( new Vector3( x * halfHeight, y * halfHeight, - depth ) ); - - } - - } - - } - - assert.ok( containsSlice, `Cascade ${i} contains its view slice` ); - - } - - } ); - - QUnit.test( 'cascade stabilization containment', ( assert ) => { - - const light = new SunLight(); - const camera = new PerspectiveCamera( 60, 1, 1, 10 ); - const shadow = light.shadow; - camera.updateMatrixWorld(); - light.position.setFromSphericalCoords( 1, Math.PI / 2 - 0.6, Math.PI / 4 ); - light.updateMatrixWorld(); - - shadow.mapSize.set( 16, 16 ); - shadow.updateMatrices( light, camera ); - - for ( const depth of shadow._cascadeSplits.slice( 0, 2 ) ) { - - const halfHeight = Math.tan( camera.fov * Math.PI / 360 ) * depth; - - for ( const x of [ - 1, 1 ] ) { - - for ( const y of [ - 1, 1 ] ) { - - const corner = new Vector3( x * halfHeight * camera.aspect, y * halfHeight, - depth ).applyMatrix4( camera.matrixWorld ); - assert.ok( shadow.getFrustum( 0 ).containsPoint( corner ), 'Texel stabilization keeps the slice corner inside its cascade' ); - - } - - } - - } - - } ); - - QUnit.test( 'reversed depth cascade containment', ( assert ) => { - - const light = new SunLight(); - const camera = new PerspectiveCamera( 60, 1, 0.1, 100 ); - const shadow = light.shadow; - light.position.setFromSphericalCoords( 1, Math.PI / 2 - 0.9, 0.7 ); - light.updateMatrixWorld(); - camera.updateMatrixWorld(); - - for ( const [ viewReversedDepth, shadowReversedDepth ] of [[ false, false ], [ false, true ], [ true, true ]] ) { - - camera._reversedDepth = viewReversedDepth; - camera.updateProjectionMatrix(); - shadow.camera._reversedDepth = shadowReversedDepth; - shadow.updateMatrices( light, camera ); - - for ( let i = 0; i < 4; i ++ ) { - - const cascadeCamera = shadow.getCamera( i ); - const depth = ( shadow._cascadeSplits[ i ] + shadow._cascadeSplits[ i + 1 ] ) * 0.5; - assert.strictEqual( cascadeCamera.reversedDepth, shadowReversedDepth, `Cascade ${i} uses the shadow map depth convention` ); - assert.ok( shadow.getMatrix( i ).elements.every( Number.isFinite ), `Cascade ${i} has a finite shadow matrix` ); - assert.ok( shadow.getFrustum( i ).containsPoint( new Vector3( 0, 0, - depth ) ), `Cascade ${i} contains its view slice` ); - - } - - } - - } ); - - // OTHERS - QUnit.test( 'clone/copy', ( assert ) => { - - const a = new SunLightShadow(); - const b = new SunLightShadow(); - - assert.notDeepEqual( a, b, 'Newly instanced shadows are not equal' ); - - const c = a.clone(); - assert.smartEqual( a, c, 'Shadows are identical after clone()' ); - - c.mapSize.set( 1024, 1024 ); - assert.notDeepEqual( a, c, 'Shadows are different again after change' ); - - b.copy( a ); - assert.smartEqual( a, b, 'Shadows are identical after copy()' ); - - b.mapSize.set( 512, 512 ); - assert.notDeepEqual( a, b, 'Shadows are different again after change' ); - - } ); - - QUnit.test( 'toJSON', ( assert ) => { - - const light = new SunLight(); - const shadow = light.shadow; - - shadow.bias = 10; - shadow.radius = 5; - shadow.mapSize.set( 1024, 1024 ); - - const json = light.toJSON(); - const newLight = new ObjectLoader().parse( json ); - - assert.ok( newLight.shadow.isSunLightShadow, 'Reloaded shadow is a SunLightShadow' ); - assert.smartEqual( - newLight.shadow, light.shadow, - 'Reloaded shadow is identical to the original one' - ); - - } ); - - } ); - -} ); diff --git a/test/unit/three.source.unit.js b/test/unit/three.source.unit.js index e4bb31ec642a1f..d545b5d81c438c 100644 --- a/test/unit/three.source.unit.js +++ b/test/unit/three.source.unit.js @@ -131,8 +131,6 @@ import './src/helpers/SpotLightHelper.tests.js'; import './src/lights/AmbientLight.tests.js'; import './src/lights/DirectionalLight.tests.js'; import './src/lights/DirectionalLightShadow.tests.js'; -import './src/lights/SunLight.tests.js'; -import './src/lights/SunLightShadow.tests.js'; import './src/lights/HemisphereLight.tests.js'; import './src/lights/Light.tests.js'; import './src/lights/LightProbe.tests.js'; From 52184ab39216913eb2984cbcffaf0efe1b677378 Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Fri, 21 Aug 2026 23:02:30 +0900 Subject: [PATCH 4/5] SunLight: Reduce cascade count to 2. Co-Authored-By: Claude Fable 5 --- examples/jsm/lights/SunLightShadow.js | 8 ++++---- examples/webgl_lights_sunlight.html | 2 +- .../ShaderChunk/shadowmap_pars_fragment.glsl.js | 8 ++++---- src/renderers/webgl/WebGLLights.js | 12 ++++++------ 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/examples/jsm/lights/SunLightShadow.js b/examples/jsm/lights/SunLightShadow.js index 47b0abd930ad14..a09094ec065544 100644 --- a/examples/jsm/lights/SunLightShadow.js +++ b/examples/jsm/lights/SunLightShadow.js @@ -40,14 +40,14 @@ const _cascadeCorners = [ // must match the cascade count in the sun shadow shader chunks -const _cascadeCount = 4; +const _cascadeCount = 2; // fraction of each cascade's depth range that blends into the next cascade const _cascadeFade = 0.1; /** - * Represents the shadow configuration of {@link SunLight}, using four + * Represents the shadow configuration of {@link SunLight}, using two * cascaded shadow maps (CSM). * * The shadow camera projection is fitted automatically to slices of the view @@ -90,7 +90,7 @@ class SunLightShadow extends LightShadow { this._cascadeData = []; this._viewportCount = _cascadeCount; - this._frameExtents.set( 2, 2 ); + this._frameExtents.set( 2, 1 ); for ( let i = 0; i < _cascadeCount; i ++ ) { @@ -160,7 +160,7 @@ class SunLightShadow extends LightShadow { for ( let i = 0; i < _cascadeCount; i ++ ) { - this._viewports[ i ].set( i % 2 + insetX, Math.floor( i / 2 ) + insetY, 1 - 2 * insetX, 1 - 2 * insetY ); + this._viewports[ i ].set( i + insetX, insetY, 1 - 2 * insetX, 1 - 2 * insetY ); } diff --git a/examples/webgl_lights_sunlight.html b/examples/webgl_lights_sunlight.html index 51067c33de860f..5be6907e4a7e3a 100644 --- a/examples/webgl_lights_sunlight.html +++ b/examples/webgl_lights_sunlight.html @@ -59,7 +59,7 @@ #if defined( USE_SHADOWMAP ) && NUM_SUN_LIGHT_SHADOWS > 0 float cascade = 0.0; - for ( int i = 0; i < 4; i ++ ) cascade += step( sunShadowCascade[ i ].y, vSunShadowWorldPosition.w ); + for ( int i = 0; i < 2; i ++ ) cascade += step( sunShadowCascade[ i ].y, vSunShadowWorldPosition.w ); gl_FragColor.rgb *= 0.7 + 0.3 * cos( cascade * 1.2 + vec3( 0.0, 4.2, 2.1 ) ); #endif diff --git a/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js index 748b3beaa7b001..a32bc3a44d948e 100644 --- a/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js @@ -25,8 +25,8 @@ export default /* glsl */` #endif - uniform mat4 sunShadowMatrix[ NUM_SUN_LIGHT_SHADOWS * 4 ]; - uniform vec4 sunShadowCascade[ NUM_SUN_LIGHT_SHADOWS * 4 ]; + uniform mat4 sunShadowMatrix[ NUM_SUN_LIGHT_SHADOWS * 2 ]; + uniform vec4 sunShadowCascade[ NUM_SUN_LIGHT_SHADOWS * 2 ]; varying vec4 vSunShadowWorldPosition; varying vec3 vSunShadowWorldNormal; @@ -301,13 +301,13 @@ export default /* glsl */` vec4 shadowWorldPosition = vec4( vSunShadowWorldPosition.xyz + vSunShadowWorldNormal * sunLightShadow.shadowNormalBias, 1.0 ); float viewDepth = vSunShadowWorldPosition.w; - int cascadeOffset = shadowIndex * 4; + int cascadeOffset = shadowIndex * 2; float shadow = 1.0; // walk the cascades back to front so each fade band can blend with the shadow behind it - for ( int i = 3; i >= 0; i -- ) { + for ( int i = 1; i >= 0; i -- ) { // ( begin, end, fade start ) view depths of the cascade diff --git a/src/renderers/webgl/WebGLLights.js b/src/renderers/webgl/WebGLLights.js index 5c0855221f1974..2b5887745a48e8 100644 --- a/src/renderers/webgl/WebGLLights.js +++ b/src/renderers/webgl/WebGLLights.js @@ -306,12 +306,12 @@ function WebGLLights( extensions ) { state.sunShadow[ numSunShadows ] = shadowUniforms; state.sunShadowMap[ numSunShadows ] = shadowMap; - // four cascades per sun light, matching the sun shadow shader chunks + // two cascades per sun light, matching the sun shadow shader chunks - for ( let j = 0; j < 4; j ++ ) { + for ( let j = 0; j < 2; j ++ ) { - state.sunShadowMatrix[ numSunShadows * 4 + j ] = shadow.getMatrix( j ); - state.sunShadowCascade[ numSunShadows * 4 + j ] = shadow._cascadeData[ j ]; + state.sunShadowMatrix[ numSunShadows * 2 + j ] = shadow.getMatrix( j ); + state.sunShadowCascade[ numSunShadows * 2 + j ] = shadow._cascadeData[ j ]; } @@ -510,8 +510,8 @@ function WebGLLights( extensions ) { state.sunShadow.length = numSunShadows; state.sunShadowMap.length = numSunShadows; - state.sunShadowMatrix.length = numSunShadows * 4; - state.sunShadowCascade.length = numSunShadows * 4; + state.sunShadowMatrix.length = numSunShadows * 2; + state.sunShadowCascade.length = numSunShadows * 2; state.directionalShadow.length = numDirectionalShadows; state.directionalShadowMap.length = numDirectionalShadows; state.directionalShadowMatrix.length = numDirectionalShadows; From 5c81184a805495f5394aa50ad4c33d5f332a4b37 Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Fri, 21 Aug 2026 23:48:27 +0900 Subject: [PATCH 5/5] Examples: Update webgl_lightprobes_sponza screenshot for two sun cascades. Co-Authored-By: Claude Fable 5 --- .../screenshots/webgl_lightprobes_sponza.jpg | Bin 37465 -> 37410 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/examples/screenshots/webgl_lightprobes_sponza.jpg b/examples/screenshots/webgl_lightprobes_sponza.jpg index eb5006834c14c660b9d76a7072974a951767a450..b92ef93804a4f3bb8e1c6ba072d947b66e5ebe2b 100644 GIT binary patch delta 35786 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 B?Pvf1 delta 35845 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 RYNAYsRT3lp+J-f`|Ji#7RT2OI