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 }}** |
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 94%
rename from src/lights/SunLightShadow.js
rename to examples/jsm/lights/SunLightShadow.js
index bd4f791ceed6f9..a09094ec065544 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();
@@ -38,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
@@ -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 {
@@ -87,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 ++ ) {
@@ -157,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/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 } ) );
}
diff --git a/examples/screenshots/webgl_lightprobes_sponza.jpg b/examples/screenshots/webgl_lightprobes_sponza.jpg
index eb5006834c14c6..b92ef93804a4f3 100644
Binary files a/examples/screenshots/webgl_lightprobes_sponza.jpg and b/examples/screenshots/webgl_lightprobes_sponza.jpg differ
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..5be6907e4a7e3a 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';
@@ -58,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
@@ -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/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;
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';