diff --git a/build/three.core.js b/build/three.core.js
index 55ea0f5a29713f..48326e23385880 100644
--- a/build/three.core.js
+++ b/build/three.core.js
@@ -16435,13 +16435,13 @@ class Box3 {
}
// compute box center and extents
- this.getCenter( _center$1 );
- _extents.subVectors( this.max, _center$1 );
+ this.getCenter( _center );
+ _extents.subVectors( this.max, _center );
// translate triangle to aabb origin
- _v0$1.subVectors( triangle.a, _center$1 );
- _v1$4.subVectors( triangle.b, _center$1 );
- _v2$3.subVectors( triangle.c, _center$1 );
+ _v0$1.subVectors( triangle.a, _center );
+ _v1$4.subVectors( triangle.b, _center );
+ _v2$3.subVectors( triangle.c, _center );
// compute edge vectors for triangle
_f0.subVectors( _v1$4, _v0$1 );
@@ -16679,7 +16679,7 @@ const _f0 = /*@__PURE__*/ new Vector3();
const _f1 = /*@__PURE__*/ new Vector3();
const _f2 = /*@__PURE__*/ new Vector3();
-const _center$1 = /*@__PURE__*/ new Vector3();
+const _center = /*@__PURE__*/ new Vector3();
const _extents = /*@__PURE__*/ new Vector3();
const _triangleNormal = /*@__PURE__*/ new Vector3();
const _testAxis = /*@__PURE__*/ new Vector3();
@@ -46079,6 +46079,77 @@ class Light extends Object3D {
}
+/**
+ * A light source positioned directly above the scene, with color fading from
+ * the sky color to the ground color.
+ *
+ * This light cannot be used to cast shadows.
+ *
+ * ```js
+ * const light = new THREE.HemisphereLight( 0xffffbb, 0x080820, 1 );
+ * scene.add( light );
+ * ```
+ *
+ * @augments Light
+ */
+class HemisphereLight extends Light {
+
+ /**
+ * Constructs a new hemisphere light.
+ *
+ * @param {(number|Color|string)} [skyColor=0xffffff] - The light's sky color.
+ * @param {(number|Color|string)} [groundColor=0xffffff] - The light's ground color.
+ * @param {number} [intensity=1] - The light's strength/intensity.
+ */
+ constructor( skyColor, groundColor, intensity ) {
+
+ super( skyColor, intensity );
+
+ /**
+ * This flag can be used for type testing.
+ *
+ * @type {boolean}
+ * @readonly
+ * @default true
+ */
+ this.isHemisphereLight = true;
+
+ this.type = 'HemisphereLight';
+
+ this.position.copy( Object3D.DEFAULT_UP );
+ this.updateMatrix();
+
+ /**
+ * The light's ground color.
+ *
+ * @type {Color}
+ */
+ this.groundColor = new Color( groundColor );
+
+ }
+
+ copy( source, recursive ) {
+
+ super.copy( source, recursive );
+
+ this.groundColor.copy( source.groundColor );
+
+ return this;
+
+ }
+
+ toJSON( meta ) {
+
+ const data = super.toJSON( meta );
+
+ data.object.groundColor = this.groundColor.getHex();
+
+ return data;
+
+ }
+
+}
+
const _projScreenMatrix = /*@__PURE__*/ new Matrix4();
const _lightPositionWorld = /*@__PURE__*/ new Vector3();
const _lookTarget = /*@__PURE__*/ new Vector3();
@@ -46602,33 +46673,34 @@ class Camera extends Object3D {
}
+const _v3$1 = /*@__PURE__*/ new Vector3();
+const _minTarget = /*@__PURE__*/ new Vector2();
+const _maxTarget = /*@__PURE__*/ new Vector2();
+
/**
- * Camera that uses [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection).
+ * Camera that uses [perspective projection](https://en.wikipedia.org/wiki/Perspective_(graphical)).
*
- * In this projection mode, an object's size in the rendered image stays
- * constant regardless of its distance from the camera. This can be useful
- * for rendering 2D scenes and UI elements, amongst other things.
+ * This projection mode is designed to mimic the way the human eye sees. It
+ * is the most common projection mode used for rendering a 3D scene.
*
* ```js
- * const camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 );
+ * const camera = new THREE.PerspectiveCamera( 45, width / height, 1, 1000 );
* scene.add( camera );
* ```
*
* @augments Camera
*/
-class OrthographicCamera extends Camera {
+class PerspectiveCamera extends Camera {
/**
- * Constructs a new orthographic camera.
+ * Constructs a new perspective camera.
*
- * @param {number} [left=-1] - The left plane of the camera's frustum.
- * @param {number} [right=1] - The right plane of the camera's frustum.
- * @param {number} [top=1] - The top plane of the camera's frustum.
- * @param {number} [bottom=-1] - The bottom plane of the camera's frustum.
+ * @param {number} [fov=50] - The vertical field of view.
+ * @param {number} [aspect=1] - The aspect ratio.
* @param {number} [near=0.1] - The camera's near plane.
* @param {number} [far=2000] - The camera's far plane.
*/
- constructor( left = -1, right = 1, top = 1, bottom = -1, near = 0.1, far = 2000 ) {
+ constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) {
super();
@@ -46639,9 +46711,18 @@ class OrthographicCamera extends Camera {
* @readonly
* @default true
*/
- this.isOrthographicCamera = true;
+ this.isPerspectiveCamera = true;
- this.type = 'OrthographicCamera';
+ this.type = 'PerspectiveCamera';
+
+ /**
+ * The vertical field of view, from bottom to top of view,
+ * in degrees.
+ *
+ * @type {number}
+ * @default 50
+ */
+ this.fov = fov;
/**
* The zoom factor of the camera.
@@ -46652,66 +46733,70 @@ class OrthographicCamera extends Camera {
this.zoom = 1;
/**
- * Represents the frustum window specification. This property should not be edited
- * directly but via {@link PerspectiveCamera#setViewOffset} and {@link PerspectiveCamera#clearViewOffset}.
+ * The camera's near plane. The valid range is greater than `0`
+ * and less than the current value of {@link PerspectiveCamera#far}.
*
- * @type {?Object}
- * @default null
+ * Note that, unlike for the {@link OrthographicCamera}, `0` is not a
+ * valid value for a perspective camera's near plane.
+ *
+ * @type {number}
+ * @default 0.1
*/
- this.view = null;
+ this.near = near;
/**
- * The left plane of the camera's frustum.
+ * The camera's far plane. Must be greater than the
+ * current value of {@link PerspectiveCamera#near}.
*
* @type {number}
- * @default -1
+ * @default 2000
*/
- this.left = left;
+ this.far = far;
/**
- * The right plane of the camera's frustum.
+ * Object distance used for stereoscopy and depth-of-field effects. This
+ * parameter does not influence the projection matrix unless a
+ * {@link StereoCamera} is being used.
*
* @type {number}
- * @default 1
+ * @default 10
*/
- this.right = right;
+ this.focus = 10;
/**
- * The top plane of the camera's frustum.
+ * The aspect ratio, usually the canvas width / canvas height.
*
* @type {number}
* @default 1
*/
- this.top = top;
+ this.aspect = aspect;
/**
- * The bottom plane of the camera's frustum.
+ * Represents the frustum window specification. This property should not be edited
+ * directly but via {@link PerspectiveCamera#setViewOffset} and {@link PerspectiveCamera#clearViewOffset}.
*
- * @type {number}
- * @default -1
+ * @type {?Object}
+ * @default null
*/
- this.bottom = bottom;
+ this.view = null;
/**
- * The camera's near plane. The valid range is greater than `0`
- * and less than the current value of {@link OrthographicCamera#far}.
- *
- * Note that, unlike for the {@link PerspectiveCamera}, `0` is a
- * valid value for an orthographic camera's near plane.
+ * Film size used for the larger axis. Default is `35` (millimeters). This
+ * parameter does not influence the projection matrix unless {@link PerspectiveCamera#filmOffset}
+ * is set to a nonzero value.
*
* @type {number}
- * @default 0.1
+ * @default 35
*/
- this.near = near;
+ this.filmGauge = 35;
/**
- * The camera's far plane. Must be greater than the
- * current value of {@link OrthographicCamera#near}.
+ * Horizontal off-center offset in the same unit as {@link PerspectiveCamera#filmGauge}.
*
* @type {number}
- * @default 2000
+ * @default 0
*/
- this.far = far;
+ this.filmOffset = 0;
this.updateProjectionMatrix();
@@ -46721,895 +46806,174 @@ class OrthographicCamera extends Camera {
super.copy( source, recursive );
- this.left = source.left;
- this.right = source.right;
- this.top = source.top;
- this.bottom = source.bottom;
+ this.fov = source.fov;
+ this.zoom = source.zoom;
+
this.near = source.near;
this.far = source.far;
+ this.focus = source.focus;
- this.zoom = source.zoom;
+ this.aspect = source.aspect;
this.view = source.view === null ? null : Object.assign( {}, source.view );
+ this.filmGauge = source.filmGauge;
+ this.filmOffset = source.filmOffset;
+
return this;
}
+ /**
+ * Sets the FOV by focal length in respect to the current {@link PerspectiveCamera#filmGauge}.
+ *
+ * The default film gauge is 35, so that the focal length can be specified for
+ * a 35mm (full frame) camera.
+ *
+ * @param {number} focalLength - Values for focal length and film gauge must have the same unit.
+ */
+ setFocalLength( focalLength ) {
+
+ /** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */
+ const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
+
+ this.fov = RAD2DEG * 2 * Math.atan( vExtentSlope );
+ this.updateProjectionMatrix();
+
+ }
+
+ /**
+ * Returns the focal length from the current {@link PerspectiveCamera#fov} and
+ * {@link PerspectiveCamera#filmGauge}.
+ *
+ * @return {number} The computed focal length.
+ */
+ getFocalLength() {
+
+ const vExtentSlope = Math.tan( DEG2RAD * 0.5 * this.fov );
+
+ return 0.5 * this.getFilmHeight() / vExtentSlope;
+
+ }
+
+ /**
+ * Returns the current vertical field of view angle in degrees considering {@link PerspectiveCamera#zoom}.
+ *
+ * @return {number} The effective FOV.
+ */
+ getEffectiveFOV() {
+
+ return RAD2DEG * 2 * Math.atan(
+ Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom );
+
+ }
+
+ /**
+ * Returns the width of the image on the film. If {@link PerspectiveCamera#aspect} is greater than or
+ * equal to one (landscape format), the result equals {@link PerspectiveCamera#filmGauge}.
+ *
+ * @return {number} The film width.
+ */
+ getFilmWidth() {
+
+ // film not completely covered in portrait format (aspect < 1)
+ return this.filmGauge * Math.min( this.aspect, 1 );
+
+ }
+
+ /**
+ * Returns the height of the image on the film. If {@link PerspectiveCamera#aspect} is greater than or
+ * equal to one (landscape format), the result equals {@link PerspectiveCamera#filmGauge}.
+ *
+ * @return {number} The film width.
+ */
+ getFilmHeight() {
+
+ // film not completely covered in landscape format (aspect > 1)
+ return this.filmGauge / Math.max( this.aspect, 1 );
+
+ }
+
+ /**
+ * Computes the 2D bounds of the camera's viewable rectangle at a given distance along the viewing direction.
+ * Sets `minTarget` and `maxTarget` to the coordinates of the lower-left and upper-right corners of the view rectangle.
+ *
+ * @param {number} distance - The viewing distance.
+ * @param {Vector2} minTarget - The lower-left corner of the view rectangle is written into this vector.
+ * @param {Vector2} maxTarget - The upper-right corner of the view rectangle is written into this vector.
+ */
+ getViewBounds( distance, minTarget, maxTarget ) {
+
+ _v3$1.set( -1, -1, 0.5 ).applyMatrix4( this.projectionMatrixInverse );
+
+ minTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z );
+
+ _v3$1.set( 1, 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse );
+
+ maxTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z );
+
+ }
+
+ /**
+ * Computes the width and height of the camera's viewable rectangle at a given distance along the viewing direction.
+ *
+ * @param {number} distance - The viewing distance.
+ * @param {Vector2} target - The target vector that is used to store result where x is width and y is height.
+ * @returns {Vector2} The view size.
+ */
+ getViewSize( distance, target ) {
+
+ this.getViewBounds( distance, _minTarget, _maxTarget );
+
+ return target.subVectors( _maxTarget, _minTarget );
+
+ }
+
/**
* Sets an offset in a larger frustum. This is useful for multi-window or
* multi-monitor/multi-machine setups.
*
+ * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
+ * the monitors are in grid like this
+ *```
+ * +---+---+---+
+ * | A | B | C |
+ * +---+---+---+
+ * | D | E | F |
+ * +---+---+---+
+ *```
+ * then for each monitor you would call it like this:
+ *```js
+ * const w = 1920;
+ * const h = 1080;
+ * const fullWidth = w * 3;
+ * const fullHeight = h * 2;
+ *
+ * // --A--
+ * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
+ * // --B--
+ * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
+ * // --C--
+ * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
+ * // --D--
+ * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
+ * // --E--
+ * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
+ * // --F--
+ * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
+ * ```
+ *
+ * Note there is no reason monitors have to be the same size or in a grid.
+ *
* @param {number} fullWidth - The full width of multiview setup.
* @param {number} fullHeight - The full height of multiview setup.
* @param {number} x - The horizontal offset of the subcamera.
* @param {number} y - The vertical offset of the subcamera.
* @param {number} width - The width of subcamera.
* @param {number} height - The height of subcamera.
- * @see {@link PerspectiveCamera#setViewOffset}
*/
setViewOffset( fullWidth, fullHeight, x, y, width, height ) {
-
- if ( this.view === null ) {
-
- this.view = {
- enabled: true,
- fullWidth: 1,
- fullHeight: 1,
- offsetX: 0,
- offsetY: 0,
- width: 1,
- height: 1
- };
-
- }
-
- this.view.enabled = true;
- this.view.fullWidth = fullWidth;
- this.view.fullHeight = fullHeight;
- this.view.offsetX = x;
- this.view.offsetY = y;
- this.view.width = width;
- this.view.height = height;
-
- this.updateProjectionMatrix();
-
- }
-
- /**
- * Removes the view offset from the projection matrix.
- */
- clearViewOffset() {
-
- if ( this.view !== null ) {
-
- this.view.enabled = false;
-
- }
-
- this.updateProjectionMatrix();
-
- }
-
- /**
- * Updates the camera's projection matrix. Must be called after any change of
- * camera properties.
- */
- updateProjectionMatrix() {
-
- const dx = ( this.right - this.left ) / ( 2 * this.zoom );
- const dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
- const cx = ( this.right + this.left ) / 2;
- const cy = ( this.top + this.bottom ) / 2;
-
- let left = cx - dx;
- let right = cx + dx;
- let top = cy + dy;
- let bottom = cy - dy;
-
- if ( this.view !== null && this.view.enabled ) {
-
- const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom;
- const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom;
-
- left += scaleW * this.view.offsetX;
- right = left + scaleW * this.view.width;
- top -= scaleH * this.view.offsetY;
- bottom = top - scaleH * this.view.height;
-
- }
-
- this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem, this.reversedDepth );
-
- this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
-
- }
-
- toJSON( meta ) {
-
- const data = super.toJSON( meta );
-
- data.object.zoom = this.zoom;
- data.object.left = this.left;
- data.object.right = this.right;
- data.object.top = this.top;
- data.object.bottom = this.bottom;
- data.object.near = this.near;
- data.object.far = this.far;
-
- if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
-
- return data;
-
- }
-
-}
-
-const _lightOrientationMatrix = /*@__PURE__*/ new Matrix4();
-const _viewToLightMatrix = /*@__PURE__*/ new Matrix4();
-const _lightDirection = /*@__PURE__*/ new Vector3();
-const _up$1 = /*@__PURE__*/ new Vector3();
-const _center = /*@__PURE__*/ new Vector3();
-
-const _nearCorners = [
- /*@__PURE__*/ new Vector3(),
- /*@__PURE__*/ new Vector3(),
- /*@__PURE__*/ new Vector3(),
- /*@__PURE__*/ new Vector3()
-];
-
-const _farCorners = [
- /*@__PURE__*/ new Vector3(),
- /*@__PURE__*/ new Vector3(),
- /*@__PURE__*/ new Vector3(),
- /*@__PURE__*/ new Vector3()
-];
-
-const _cascadeCorners = [
- /*@__PURE__*/ new Vector3(),
- /*@__PURE__*/ new Vector3(),
- /*@__PURE__*/ new Vector3(),
- /*@__PURE__*/ new Vector3(),
- /*@__PURE__*/ new Vector3(),
- /*@__PURE__*/ new Vector3(),
- /*@__PURE__*/ new Vector3(),
- /*@__PURE__*/ new Vector3()
-];
-
-// must match the cascade count in the sun shadow shader chunks
-
-const _cascadeCount = 4;
-
-// 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
- * cascaded shadow maps (CSM).
- *
- * The shadow camera projection is fitted automatically to slices of the view
- * frustum, up to a distance of `camera.far` (or the view camera's far plane,
- * whichever is smaller), and adjacent cascades blend into each other over a
- * small depth range. `camera.left/right/top/bottom` are ignored.
- *
- * The default `mapSize` is `1024x1024` per cascade.
- *
- * @augments LightShadow
- */
-class SunLightShadow extends LightShadow {
-
- /**
- * Constructs a new sun light shadow.
- */
- constructor() {
-
- super( new OrthographicCamera( -5, 5, 5, -5, 0.5, 500 ) );
-
- /**
- * This flag can be used for type testing.
- *
- * @type {boolean}
- * @readonly
- * @default true
- */
- this.isSunLightShadow = true;
-
- this.mapSize.set( 1024, 1024 );
-
- this._cameras = [];
- this._matrices = [];
- this._frustums = [];
- this._cascadeSplits = new Array( _cascadeCount + 1 ).fill( 0 );
-
- // per cascade ( begin, end, fade start ) view depths, consumed by the renderer
-
- this._cascadeData = [];
-
- this._viewportCount = _cascadeCount;
- this._frameExtents.set( 2, 2 );
-
- for ( let i = 0; i < _cascadeCount; i ++ ) {
-
- this._cameras.push( new OrthographicCamera() );
- this._matrices.push( new Matrix4() );
- this._frustums.push( new Frustum() );
- this._cascadeData.push( new Vector4() );
-
- }
-
- while ( this._viewports.length < _cascadeCount ) this._viewports.push( new Vector4() );
-
- }
-
- /**
- * Returns the shadow camera of the given cascade.
- *
- * @param {number} [cascadeIndex=0] - The cascade index.
- * @return {OrthographicCamera} The shadow camera.
- */
- getCamera( cascadeIndex = 0 ) {
-
- return this._cameras[ cascadeIndex ];
-
- }
-
- /**
- * Returns the shadow matrix of the given cascade.
- *
- * @param {number} [cascadeIndex=0] - The cascade index.
- * @return {Matrix4} The shadow matrix.
- */
- getMatrix( cascadeIndex = 0 ) {
-
- return this._matrices[ cascadeIndex ];
-
- }
-
- /**
- * Returns the shadow camera frustum of the given cascade. Used internally by
- * the renderer to cull objects.
- *
- * @param {number} [cascadeIndex=0] - The cascade index.
- * @return {Frustum} The shadow camera frustum.
- */
- getFrustum( cascadeIndex = 0 ) {
-
- return this._frustums[ cascadeIndex ];
-
- }
-
- /**
- * Update the matrices for the cascade cameras and shadows, used internally
- * by the renderer.
- *
- * @param {Light} light - The light for which the shadow is being rendered.
- * @param {Camera} viewCamera - The camera the scene is rendered with.
- */
- updateMatrices( light, viewCamera ) {
-
- if ( viewCamera === undefined ) return;
-
- // inset the cascade viewports so shadow filtering cannot read across atlas tiles
-
- const insetX = Math.min( 0.25, ( Math.ceil( this.radius ) + 1 ) / this.mapSize.x );
- const insetY = Math.min( 0.25, ( Math.ceil( this.radius ) + 1 ) / this.mapSize.y );
-
- 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 );
-
- }
-
- const resolutionX = this.mapSize.x * ( 1 - 2 * insetX );
- const resolutionY = this.mapSize.y * ( 1 - 2 * insetY );
- const resolution = Math.min( resolutionX, resolutionY );
-
- const camera = this.camera;
- const cameraNear = viewCamera.near;
- const cameraFar = Math.max( cameraNear + 1e-6, Math.min( camera.far, viewCamera.far ) );
-
- // practical split scheme: the average of uniform and logarithmic splits
-
- const splits = this._cascadeSplits;
- splits[ 0 ] = cameraNear;
-
- for ( let i = 1; i < _cascadeCount; i ++ ) {
-
- const amount = i / _cascadeCount;
- const uniform = cameraNear + ( cameraFar - cameraNear ) * amount;
- const logarithmic = cameraNear > 0 ? cameraNear * Math.pow( cameraFar / cameraNear, amount ) : uniform;
- splits[ i ] = ( uniform + logarithmic ) * 0.5;
-
- }
-
- splits[ _cascadeCount ] = cameraFar;
-
- _lightDirection.setFromMatrixPosition( light.matrixWorld ).negate().normalize();
-
- _up$1.set( 0, 1, 0 );
- if ( Math.abs( _up$1.dot( _lightDirection ) ) > 0.99 ) _up$1.set( 0, 0, 1 );
-
- _lightOrientationMatrix.lookAt( _center.set( 0, 0, 0 ), _lightDirection, _up$1 );
- _viewToLightMatrix.copy( _lightOrientationMatrix ).transpose().multiply( viewCamera.matrixWorld );
-
- // view frustum corners in light space; the rotation preserves distances,
- // so the cascades can be fitted and snapped directly in this space
-
- const zNear = viewCamera.reversedDepth ? 1 : -1;
- const inverseProjectionMatrix = viewCamera.projectionMatrixInverse;
-
- let globalMaxZ = - Infinity;
-
- for ( let i = 0; i < 4; i ++ ) {
-
- const x = i === 0 || i === 1 ? 1 : -1;
- const y = i === 0 || i === 3 ? 1 : -1;
-
- const nearCorner = _nearCorners[ i ].set( x, y, zNear ).applyMatrix4( inverseProjectionMatrix );
- const farCorner = _farCorners[ i ];
-
- if ( viewCamera.isPerspectiveCamera === true ) {
-
- farCorner.copy( nearCorner ).multiplyScalar( cameraFar / cameraNear );
-
- } else {
-
- farCorner.set( nearCorner.x, nearCorner.y, - cameraFar );
-
- }
-
- nearCorner.applyMatrix4( _viewToLightMatrix );
- farCorner.applyMatrix4( _viewToLightMatrix );
-
- globalMaxZ = Math.max( globalMaxZ, nearCorner.z, farCorner.z );
-
- }
-
- // raise the ceiling one shadow range towards the light so casters outside
- // the view frustum still cast into it
-
- globalMaxZ += cameraFar;
-
- const shadowNear = camera.near;
-
- for ( let i = 0; i < _cascadeCount; i ++ ) {
-
- // each cascade covers the fade band of the previous one so both can be sampled while blending
-
- const cascadeNear = i === 0 ? splits[ 0 ] : this._cascadeData[ i - 1 ].z;
- const cascadeFar = splits[ i + 1 ];
- const fadeStart = cascadeFar - _cascadeFade * ( cascadeFar - splits[ i ] );
-
- this._cascadeData[ i ].set( i === 0 ? -1e10 : cascadeNear, cascadeFar, fadeStart, 0 );
-
- // bounding sphere of the cascade slice for a rotation-stable projection
-
- const nearAlpha = ( cascadeNear - cameraNear ) / ( cameraFar - cameraNear );
- const farAlpha = ( cascadeFar - cameraNear ) / ( cameraFar - cameraNear );
-
- _center.set( 0, 0, 0 );
-
- for ( let j = 0; j < 4; j ++ ) {
-
- _cascadeCorners[ j * 2 ].lerpVectors( _nearCorners[ j ], _farCorners[ j ], nearAlpha );
- _cascadeCorners[ j * 2 + 1 ].lerpVectors( _nearCorners[ j ], _farCorners[ j ], farAlpha );
- _center.add( _cascadeCorners[ j * 2 ] ).add( _cascadeCorners[ j * 2 + 1 ] );
-
- }
-
- _center.multiplyScalar( 1 / 8 );
-
- let radiusSq = 0;
- let minZ = Infinity;
-
- for ( let j = 0; j < 8; j ++ ) {
-
- radiusSq = Math.max( radiusSq, _cascadeCorners[ j ].distanceToSquared( _center ) );
- minZ = Math.min( minZ, _cascadeCorners[ j ].z );
-
- }
-
- let radius = Math.sqrt( radiusSq );
-
- // snap to the texel grid to avoid shimmering when the view camera moves
-
- if ( resolution > 1 ) {
-
- // pad by half a texel so snapping cannot clip a frustum corner
- radius /= 1 - 1 / resolution;
- const texelSizeX = 2 * radius / resolutionX;
- const texelSizeY = 2 * radius / resolutionY;
- _center.x = Math.round( _center.x / texelSizeX ) * texelSizeX;
- _center.y = Math.round( _center.y / texelSizeY ) * texelSizeY;
-
- }
-
- // place the near plane at the caster ceiling
-
- _center.z = globalMaxZ + shadowNear;
- _center.applyMatrix4( _lightOrientationMatrix );
-
- const cascadeCamera = this._cameras[ i ];
- cascadeCamera.position.copy( _center );
- cascadeCamera.quaternion.setFromRotationMatrix( _lightOrientationMatrix );
- cascadeCamera.left = - radius;
- cascadeCamera.right = radius;
- cascadeCamera.top = radius;
- cascadeCamera.bottom = - radius;
- cascadeCamera.near = shadowNear;
- cascadeCamera.far = globalMaxZ - minZ + 2 * shadowNear;
- cascadeCamera.coordinateSystem = camera.coordinateSystem;
- cascadeCamera._reversedDepth = camera.reversedDepth;
- cascadeCamera.updateProjectionMatrix();
- cascadeCamera.updateMatrixWorld();
-
- this._updateMatrix( cascadeCamera, this._matrices[ i ], this._frustums[ i ], this._viewports[ i ] );
-
- }
-
- }
-
-}
-
-/**
- * A sun-like light that gets emitted in a specific direction, with rays that
- * are all parallel, and casts cascaded shadow maps via {@link SunLightShadow},
- * suited for lighting large scenes.
- *
- * Unlike {@link DirectionalLight}, the light has no target: like
- * {@link HemisphereLight}, its direction is defined by its position. The
- * light shines from its position towards the origin and points straight
- * down by default.
- *
- * ```js
- * const sun = new SunLight( 0xfff2e3, 3 );
- * sun.position.set( 1, 1, 1 );
- * sun.castShadow = true;
- * scene.add( sun );
- * ```
- *
- * This light is only supported by `WebGLRenderer`. When using `WebGPURenderer`,
- * use {@link DirectionalLight} with `CSMShadowNode` instead.
- *
- * @augments Light
- */
-class SunLight extends Light {
-
- /**
- * Constructs a new sun light.
- *
- * @param {(number|Color|string)} [color=0xffffff] - The light's color.
- * @param {number} [intensity=1] - The light's strength/intensity.
- */
- constructor( color, intensity ) {
-
- super( color, intensity );
-
- /**
- * This flag can be used for type testing.
- *
- * @type {boolean}
- * @readonly
- * @default true
- */
- this.isSunLight = true;
-
- this.type = 'SunLight';
-
- this.position.copy( Object3D.DEFAULT_UP );
- this.updateMatrix();
-
- /**
- * This property holds the light's shadow configuration.
- *
- * @type {SunLightShadow}
- */
- this.shadow = new SunLightShadow();
-
- }
-
- dispose() {
-
- super.dispose();
-
- this.shadow.dispose();
-
- }
-
- copy( source ) {
-
- super.copy( source );
-
- this.shadow = source.shadow.clone();
-
- return this;
-
- }
-
- toJSON( meta ) {
-
- const data = super.toJSON( meta );
-
- data.object.shadow = this.shadow.toJSON();
-
- return data;
-
- }
-
-}
-
-/**
- * A light source positioned directly above the scene, with color fading from
- * the sky color to the ground color.
- *
- * This light cannot be used to cast shadows.
- *
- * ```js
- * const light = new THREE.HemisphereLight( 0xffffbb, 0x080820, 1 );
- * scene.add( light );
- * ```
- *
- * @augments Light
- */
-class HemisphereLight extends Light {
-
- /**
- * Constructs a new hemisphere light.
- *
- * @param {(number|Color|string)} [skyColor=0xffffff] - The light's sky color.
- * @param {(number|Color|string)} [groundColor=0xffffff] - The light's ground color.
- * @param {number} [intensity=1] - The light's strength/intensity.
- */
- constructor( skyColor, groundColor, intensity ) {
-
- super( skyColor, intensity );
-
- /**
- * This flag can be used for type testing.
- *
- * @type {boolean}
- * @readonly
- * @default true
- */
- this.isHemisphereLight = true;
-
- this.type = 'HemisphereLight';
-
- this.position.copy( Object3D.DEFAULT_UP );
- this.updateMatrix();
-
- /**
- * The light's ground color.
- *
- * @type {Color}
- */
- this.groundColor = new Color( groundColor );
-
- }
-
- copy( source, recursive ) {
-
- super.copy( source, recursive );
-
- this.groundColor.copy( source.groundColor );
-
- return this;
-
- }
-
- toJSON( meta ) {
-
- const data = super.toJSON( meta );
-
- data.object.groundColor = this.groundColor.getHex();
-
- return data;
-
- }
-
-}
-
-const _v3$1 = /*@__PURE__*/ new Vector3();
-const _minTarget = /*@__PURE__*/ new Vector2();
-const _maxTarget = /*@__PURE__*/ new Vector2();
-
-/**
- * Camera that uses [perspective projection](https://en.wikipedia.org/wiki/Perspective_(graphical)).
- *
- * This projection mode is designed to mimic the way the human eye sees. It
- * is the most common projection mode used for rendering a 3D scene.
- *
- * ```js
- * const camera = new THREE.PerspectiveCamera( 45, width / height, 1, 1000 );
- * scene.add( camera );
- * ```
- *
- * @augments Camera
- */
-class PerspectiveCamera extends Camera {
-
- /**
- * Constructs a new perspective camera.
- *
- * @param {number} [fov=50] - The vertical field of view.
- * @param {number} [aspect=1] - The aspect ratio.
- * @param {number} [near=0.1] - The camera's near plane.
- * @param {number} [far=2000] - The camera's far plane.
- */
- constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) {
-
- super();
-
- /**
- * This flag can be used for type testing.
- *
- * @type {boolean}
- * @readonly
- * @default true
- */
- this.isPerspectiveCamera = true;
-
- this.type = 'PerspectiveCamera';
-
- /**
- * The vertical field of view, from bottom to top of view,
- * in degrees.
- *
- * @type {number}
- * @default 50
- */
- this.fov = fov;
-
- /**
- * The zoom factor of the camera.
- *
- * @type {number}
- * @default 1
- */
- this.zoom = 1;
-
- /**
- * The camera's near plane. The valid range is greater than `0`
- * and less than the current value of {@link PerspectiveCamera#far}.
- *
- * Note that, unlike for the {@link OrthographicCamera}, `0` is not a
- * valid value for a perspective camera's near plane.
- *
- * @type {number}
- * @default 0.1
- */
- this.near = near;
-
- /**
- * The camera's far plane. Must be greater than the
- * current value of {@link PerspectiveCamera#near}.
- *
- * @type {number}
- * @default 2000
- */
- this.far = far;
-
- /**
- * Object distance used for stereoscopy and depth-of-field effects. This
- * parameter does not influence the projection matrix unless a
- * {@link StereoCamera} is being used.
- *
- * @type {number}
- * @default 10
- */
- this.focus = 10;
-
- /**
- * The aspect ratio, usually the canvas width / canvas height.
- *
- * @type {number}
- * @default 1
- */
- this.aspect = aspect;
-
- /**
- * Represents the frustum window specification. This property should not be edited
- * directly but via {@link PerspectiveCamera#setViewOffset} and {@link PerspectiveCamera#clearViewOffset}.
- *
- * @type {?Object}
- * @default null
- */
- this.view = null;
-
- /**
- * Film size used for the larger axis. Default is `35` (millimeters). This
- * parameter does not influence the projection matrix unless {@link PerspectiveCamera#filmOffset}
- * is set to a nonzero value.
- *
- * @type {number}
- * @default 35
- */
- this.filmGauge = 35;
-
- /**
- * Horizontal off-center offset in the same unit as {@link PerspectiveCamera#filmGauge}.
- *
- * @type {number}
- * @default 0
- */
- this.filmOffset = 0;
-
- this.updateProjectionMatrix();
-
- }
-
- copy( source, recursive ) {
-
- super.copy( source, recursive );
-
- this.fov = source.fov;
- this.zoom = source.zoom;
-
- this.near = source.near;
- this.far = source.far;
- this.focus = source.focus;
-
- this.aspect = source.aspect;
- this.view = source.view === null ? null : Object.assign( {}, source.view );
-
- this.filmGauge = source.filmGauge;
- this.filmOffset = source.filmOffset;
-
- return this;
-
- }
-
- /**
- * Sets the FOV by focal length in respect to the current {@link PerspectiveCamera#filmGauge}.
- *
- * The default film gauge is 35, so that the focal length can be specified for
- * a 35mm (full frame) camera.
- *
- * @param {number} focalLength - Values for focal length and film gauge must have the same unit.
- */
- setFocalLength( focalLength ) {
-
- /** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */
- const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
-
- this.fov = RAD2DEG * 2 * Math.atan( vExtentSlope );
- this.updateProjectionMatrix();
-
- }
-
- /**
- * Returns the focal length from the current {@link PerspectiveCamera#fov} and
- * {@link PerspectiveCamera#filmGauge}.
- *
- * @return {number} The computed focal length.
- */
- getFocalLength() {
-
- const vExtentSlope = Math.tan( DEG2RAD * 0.5 * this.fov );
-
- return 0.5 * this.getFilmHeight() / vExtentSlope;
-
- }
-
- /**
- * Returns the current vertical field of view angle in degrees considering {@link PerspectiveCamera#zoom}.
- *
- * @return {number} The effective FOV.
- */
- getEffectiveFOV() {
-
- return RAD2DEG * 2 * Math.atan(
- Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom );
-
- }
-
- /**
- * Returns the width of the image on the film. If {@link PerspectiveCamera#aspect} is greater than or
- * equal to one (landscape format), the result equals {@link PerspectiveCamera#filmGauge}.
- *
- * @return {number} The film width.
- */
- getFilmWidth() {
-
- // film not completely covered in portrait format (aspect < 1)
- return this.filmGauge * Math.min( this.aspect, 1 );
-
- }
-
- /**
- * Returns the height of the image on the film. If {@link PerspectiveCamera#aspect} is greater than or
- * equal to one (landscape format), the result equals {@link PerspectiveCamera#filmGauge}.
- *
- * @return {number} The film width.
- */
- getFilmHeight() {
-
- // film not completely covered in landscape format (aspect > 1)
- return this.filmGauge / Math.max( this.aspect, 1 );
-
- }
-
- /**
- * Computes the 2D bounds of the camera's viewable rectangle at a given distance along the viewing direction.
- * Sets `minTarget` and `maxTarget` to the coordinates of the lower-left and upper-right corners of the view rectangle.
- *
- * @param {number} distance - The viewing distance.
- * @param {Vector2} minTarget - The lower-left corner of the view rectangle is written into this vector.
- * @param {Vector2} maxTarget - The upper-right corner of the view rectangle is written into this vector.
- */
- getViewBounds( distance, minTarget, maxTarget ) {
-
- _v3$1.set( -1, -1, 0.5 ).applyMatrix4( this.projectionMatrixInverse );
-
- minTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z );
-
- _v3$1.set( 1, 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse );
-
- maxTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z );
-
- }
-
- /**
- * Computes the width and height of the camera's viewable rectangle at a given distance along the viewing direction.
- *
- * @param {number} distance - The viewing distance.
- * @param {Vector2} target - The target vector that is used to store result where x is width and y is height.
- * @returns {Vector2} The view size.
- */
- getViewSize( distance, target ) {
-
- this.getViewBounds( distance, _minTarget, _maxTarget );
-
- return target.subVectors( _maxTarget, _minTarget );
-
- }
-
- /**
- * Sets an offset in a larger frustum. This is useful for multi-window or
- * multi-monitor/multi-machine setups.
- *
- * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
- * the monitors are in grid like this
- *```
- * +---+---+---+
- * | A | B | C |
- * +---+---+---+
- * | D | E | F |
- * +---+---+---+
- *```
- * then for each monitor you would call it like this:
- *```js
- * const w = 1920;
- * const h = 1080;
- * const fullWidth = w * 3;
- * const fullHeight = h * 2;
- *
- * // --A--
- * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
- * // --B--
- * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
- * // --C--
- * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
- * // --D--
- * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
- * // --E--
- * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
- * // --F--
- * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
- * ```
- *
- * Note there is no reason monitors have to be the same size or in a grid.
- *
- * @param {number} fullWidth - The full width of multiview setup.
- * @param {number} fullHeight - The full height of multiview setup.
- * @param {number} x - The horizontal offset of the subcamera.
- * @param {number} y - The vertical offset of the subcamera.
- * @param {number} width - The width of subcamera.
- * @param {number} height - The height of subcamera.
- */
- setViewOffset( fullWidth, fullHeight, x, y, width, height ) {
-
- this.aspect = fullWidth / fullHeight;
+
+ this.aspect = fullWidth / fullHeight;
if ( this.view === null ) {
@@ -48146,6 +47510,248 @@ class PointLight extends Light {
}
+/**
+ * Camera that uses [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection).
+ *
+ * In this projection mode, an object's size in the rendered image stays
+ * constant regardless of its distance from the camera. This can be useful
+ * for rendering 2D scenes and UI elements, amongst other things.
+ *
+ * ```js
+ * const camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 );
+ * scene.add( camera );
+ * ```
+ *
+ * @augments Camera
+ */
+class OrthographicCamera extends Camera {
+
+ /**
+ * Constructs a new orthographic camera.
+ *
+ * @param {number} [left=-1] - The left plane of the camera's frustum.
+ * @param {number} [right=1] - The right plane of the camera's frustum.
+ * @param {number} [top=1] - The top plane of the camera's frustum.
+ * @param {number} [bottom=-1] - The bottom plane of the camera's frustum.
+ * @param {number} [near=0.1] - The camera's near plane.
+ * @param {number} [far=2000] - The camera's far plane.
+ */
+ constructor( left = -1, right = 1, top = 1, bottom = -1, near = 0.1, far = 2000 ) {
+
+ super();
+
+ /**
+ * This flag can be used for type testing.
+ *
+ * @type {boolean}
+ * @readonly
+ * @default true
+ */
+ this.isOrthographicCamera = true;
+
+ this.type = 'OrthographicCamera';
+
+ /**
+ * The zoom factor of the camera.
+ *
+ * @type {number}
+ * @default 1
+ */
+ this.zoom = 1;
+
+ /**
+ * Represents the frustum window specification. This property should not be edited
+ * directly but via {@link PerspectiveCamera#setViewOffset} and {@link PerspectiveCamera#clearViewOffset}.
+ *
+ * @type {?Object}
+ * @default null
+ */
+ this.view = null;
+
+ /**
+ * The left plane of the camera's frustum.
+ *
+ * @type {number}
+ * @default -1
+ */
+ this.left = left;
+
+ /**
+ * The right plane of the camera's frustum.
+ *
+ * @type {number}
+ * @default 1
+ */
+ this.right = right;
+
+ /**
+ * The top plane of the camera's frustum.
+ *
+ * @type {number}
+ * @default 1
+ */
+ this.top = top;
+
+ /**
+ * The bottom plane of the camera's frustum.
+ *
+ * @type {number}
+ * @default -1
+ */
+ this.bottom = bottom;
+
+ /**
+ * The camera's near plane. The valid range is greater than `0`
+ * and less than the current value of {@link OrthographicCamera#far}.
+ *
+ * Note that, unlike for the {@link PerspectiveCamera}, `0` is a
+ * valid value for an orthographic camera's near plane.
+ *
+ * @type {number}
+ * @default 0.1
+ */
+ this.near = near;
+
+ /**
+ * The camera's far plane. Must be greater than the
+ * current value of {@link OrthographicCamera#near}.
+ *
+ * @type {number}
+ * @default 2000
+ */
+ this.far = far;
+
+ this.updateProjectionMatrix();
+
+ }
+
+ copy( source, recursive ) {
+
+ super.copy( source, recursive );
+
+ this.left = source.left;
+ this.right = source.right;
+ this.top = source.top;
+ this.bottom = source.bottom;
+ this.near = source.near;
+ this.far = source.far;
+
+ this.zoom = source.zoom;
+ this.view = source.view === null ? null : Object.assign( {}, source.view );
+
+ return this;
+
+ }
+
+ /**
+ * Sets an offset in a larger frustum. This is useful for multi-window or
+ * multi-monitor/multi-machine setups.
+ *
+ * @param {number} fullWidth - The full width of multiview setup.
+ * @param {number} fullHeight - The full height of multiview setup.
+ * @param {number} x - The horizontal offset of the subcamera.
+ * @param {number} y - The vertical offset of the subcamera.
+ * @param {number} width - The width of subcamera.
+ * @param {number} height - The height of subcamera.
+ * @see {@link PerspectiveCamera#setViewOffset}
+ */
+ setViewOffset( fullWidth, fullHeight, x, y, width, height ) {
+
+ if ( this.view === null ) {
+
+ this.view = {
+ enabled: true,
+ fullWidth: 1,
+ fullHeight: 1,
+ offsetX: 0,
+ offsetY: 0,
+ width: 1,
+ height: 1
+ };
+
+ }
+
+ this.view.enabled = true;
+ this.view.fullWidth = fullWidth;
+ this.view.fullHeight = fullHeight;
+ this.view.offsetX = x;
+ this.view.offsetY = y;
+ this.view.width = width;
+ this.view.height = height;
+
+ this.updateProjectionMatrix();
+
+ }
+
+ /**
+ * Removes the view offset from the projection matrix.
+ */
+ clearViewOffset() {
+
+ if ( this.view !== null ) {
+
+ this.view.enabled = false;
+
+ }
+
+ this.updateProjectionMatrix();
+
+ }
+
+ /**
+ * Updates the camera's projection matrix. Must be called after any change of
+ * camera properties.
+ */
+ updateProjectionMatrix() {
+
+ const dx = ( this.right - this.left ) / ( 2 * this.zoom );
+ const dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
+ const cx = ( this.right + this.left ) / 2;
+ const cy = ( this.top + this.bottom ) / 2;
+
+ let left = cx - dx;
+ let right = cx + dx;
+ let top = cy + dy;
+ let bottom = cy - dy;
+
+ if ( this.view !== null && this.view.enabled ) {
+
+ const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom;
+ const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom;
+
+ left += scaleW * this.view.offsetX;
+ right = left + scaleW * this.view.width;
+ top -= scaleH * this.view.offsetY;
+ bottom = top - scaleH * this.view.height;
+
+ }
+
+ this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem, this.reversedDepth );
+
+ this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
+
+ }
+
+ toJSON( meta ) {
+
+ const data = super.toJSON( meta );
+
+ data.object.zoom = this.zoom;
+ data.object.left = this.left;
+ data.object.right = this.right;
+ data.object.top = this.top;
+ data.object.bottom = this.bottom;
+ data.object.near = this.near;
+ data.object.far = this.far;
+
+ if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
+
+ return data;
+
+ }
+
+}
+
/**
* Represents the shadow configuration of directional lights.
*
@@ -50231,12 +49837,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 );
@@ -60908,4 +60508,4 @@ if ( typeof window !== 'undefined' ) {
}
-export { ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, AgXToneMapping, AlphaFormat, AlwaysCompare, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrayCamera, ArrowHelper, AttachedBindMode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BackSide, BasicDepthPacking, BasicShadowMap, BatchedMesh, BezierInterpolant, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxGeometry, BoxHelper, BufferAttribute, BufferGeometry, BufferGeometryLoader, ByteType, Cache, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CineonToneMapping, CircleGeometry, ClampToEdgeWrapping, Clock, Color, ColorKeyframeTrack, ColorManagement, Compatibility, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ConeGeometry, ConstantAlphaFactor, ConstantColorFactor, Controls, CubeCamera, CubeDepthTexture, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeUVReflectionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CustomToneMapping, CylinderGeometry, Cylindrical, Data3DTexture, DataArrayTexture, DataTexture, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DepthTexture, DetachedBindMode, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DodecahedronGeometry, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, EqualCompare, EqualDepth, EqualStencilFunc, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExternalTexture, ExtrudeGeometry, FileLoader, Float16BufferAttribute, Float32BufferAttribute, FloatType, Fog, FogExp2, FramebufferTexture, FrontSide, Frustum, FrustumArray, GLBufferAttribute, GLSL1, GLSL3, GreaterCompare, GreaterDepth, GreaterEqualCompare, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HTMLTexture, HalfFloatType, HemisphereLight, HemisphereLightHelper, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateBezier, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InterpolationSamplingMode, InterpolationSamplingType, InvertStencilOp, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry, Layers, LessCompare, LessDepth, LessEqualCompare, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LineSegments, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping, LinearTransfer, Loader, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, MOUSE, Material, MaterialBlending, MaterialLoader, MathUtils, Matrix2, Matrix3, Matrix4, MaxEquation, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeutralToneMapping, NeverCompare, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoNormalPacking, NoToneMapping, NormalAnimationBlendMode, NormalBlending, NormalGAPacking, NormalRGPacking, NotEqualCompare, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, ObjectSpaceNormalMap, OctahedronGeometry, OneFactor, OneMinusConstantAlphaFactor, OneMinusConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, PCFShadowMap, PCFSoftShadowMap, Path, PerspectiveCamera, Plane, PlaneGeometry, PlaneHelper, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, R11_EAC_Format, RAD2DEG, RED_GREEN_RGTC2_Format, RED_RGTC1_Format, REVISION, RG11_EAC_Format, RGBADepthPacking, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBDepthPacking, RGBFormat, RGBIntegerFormat, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGDepthPacking, RGFormat, RGIntegerFormat, RawShaderMaterial, Ray, Raycaster, RectAreaLight, RedFormat, RedIntegerFormat, ReinhardToneMapping, RenderObjectRefreshType, RenderTarget, RenderTarget3D, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, ReversedDepthFuncs, RingGeometry, SIGNED_R11_EAC_Format, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SIGNED_RG11_EAC_Format, SRGBColorSpace, SRGBTransfer, Scene, ShaderMaterial, ShadowMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, Source, Sphere, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SubtractEquation, SubtractiveBlending, SunLight, TOUCH, TangentSpaceNormalMap, TetrahedronGeometry, Texture, TextureLoader, TextureSource, TextureUtils, Timer, TimestampQuery, TorusGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, UniformsUtils, UnsignedByteType, UnsignedInt101111Type, UnsignedInt248Type, UnsignedInt5999Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, VectorKeyframeTrack, VideoFrameTexture, VideoTexture, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLCoordinateSystem, WebGLRenderTarget, WebGPUCoordinateSystem, WebXRController, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, cloneUniforms, createCanvasElement, createElementNS, error, getByteLength, getConsoleFunction, getUnlitUniformColorSpace, isTypedArray, log, mergeUniforms, probeAsync, setConsoleFunction, warn, warnOnce, yieldToMain };
+export { ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, AgXToneMapping, AlphaFormat, AlwaysCompare, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrayCamera, ArrowHelper, AttachedBindMode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BackSide, BasicDepthPacking, BasicShadowMap, BatchedMesh, BezierInterpolant, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxGeometry, BoxHelper, BufferAttribute, BufferGeometry, BufferGeometryLoader, ByteType, Cache, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CineonToneMapping, CircleGeometry, ClampToEdgeWrapping, Clock, Color, ColorKeyframeTrack, ColorManagement, Compatibility, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ConeGeometry, ConstantAlphaFactor, ConstantColorFactor, Controls, CubeCamera, CubeDepthTexture, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeUVReflectionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CustomToneMapping, CylinderGeometry, Cylindrical, Data3DTexture, DataArrayTexture, DataTexture, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DepthTexture, DetachedBindMode, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DodecahedronGeometry, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, EqualCompare, EqualDepth, EqualStencilFunc, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExternalTexture, ExtrudeGeometry, FileLoader, Float16BufferAttribute, Float32BufferAttribute, FloatType, Fog, FogExp2, FramebufferTexture, FrontSide, Frustum, FrustumArray, GLBufferAttribute, GLSL1, GLSL3, GreaterCompare, GreaterDepth, GreaterEqualCompare, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HTMLTexture, HalfFloatType, HemisphereLight, HemisphereLightHelper, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateBezier, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InterpolationSamplingMode, InterpolationSamplingType, InvertStencilOp, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry, Layers, LessCompare, LessDepth, LessEqualCompare, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, LightShadow, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LineSegments, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping, LinearTransfer, Loader, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, MOUSE, Material, MaterialBlending, MaterialLoader, MathUtils, Matrix2, Matrix3, Matrix4, MaxEquation, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeutralToneMapping, NeverCompare, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoNormalPacking, NoToneMapping, NormalAnimationBlendMode, NormalBlending, NormalGAPacking, NormalRGPacking, NotEqualCompare, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, ObjectSpaceNormalMap, OctahedronGeometry, OneFactor, OneMinusConstantAlphaFactor, OneMinusConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, PCFShadowMap, PCFSoftShadowMap, Path, PerspectiveCamera, Plane, PlaneGeometry, PlaneHelper, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, R11_EAC_Format, RAD2DEG, RED_GREEN_RGTC2_Format, RED_RGTC1_Format, REVISION, RG11_EAC_Format, RGBADepthPacking, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBDepthPacking, RGBFormat, RGBIntegerFormat, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGDepthPacking, RGFormat, RGIntegerFormat, RawShaderMaterial, Ray, Raycaster, RectAreaLight, RedFormat, RedIntegerFormat, ReinhardToneMapping, RenderObjectRefreshType, RenderTarget, RenderTarget3D, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, ReversedDepthFuncs, RingGeometry, SIGNED_R11_EAC_Format, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SIGNED_RG11_EAC_Format, SRGBColorSpace, SRGBTransfer, Scene, ShaderMaterial, ShadowMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, Source, Sphere, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SubtractEquation, SubtractiveBlending, TOUCH, TangentSpaceNormalMap, TetrahedronGeometry, Texture, TextureLoader, TextureSource, TextureUtils, Timer, TimestampQuery, TorusGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, UniformsUtils, UnsignedByteType, UnsignedInt101111Type, UnsignedInt248Type, UnsignedInt5999Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, VectorKeyframeTrack, VideoFrameTexture, VideoTexture, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLCoordinateSystem, WebGLRenderTarget, WebGPUCoordinateSystem, WebXRController, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, cloneUniforms, createCanvasElement, createElementNS, error, getByteLength, getConsoleFunction, getUnlitUniformColorSpace, isTypedArray, log, mergeUniforms, probeAsync, setConsoleFunction, warn, warnOnce, yieldToMain };
diff --git a/build/three.module.js b/build/three.module.js
index 496b74f3557b7a..3a56b819c4e19f 100644
--- a/build/three.module.js
+++ b/build/three.module.js
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: MIT
*/
import { Matrix3, Vector2, Color, Vector3, mergeUniforms, CubeUVReflectionMapping, Mesh, BoxGeometry, ShaderMaterial, BackSide, cloneUniforms, Matrix4, ColorManagement, SRGBTransfer, PlaneGeometry, FrontSide, getUnlitUniformColorSpace, IntType, warn, HalfFloatType, UnsignedByteType, FloatType, RGBAFormat, Plane, CubeReflectionMapping, CubeRefractionMapping, BufferGeometry, OrthographicCamera, PerspectiveCamera, NoToneMapping, MeshBasicMaterial, NoBlending, WebGLRenderTarget, BufferAttribute, LinearSRGBColorSpace, LinearFilter, CubeTexture, LinearMipmapLinearFilter, CubeCamera, EquirectangularReflectionMapping, EquirectangularRefractionMapping, warnOnce, Uint32BufferAttribute, Uint16BufferAttribute, error, DataArrayTexture, Vector4, Float32BufferAttribute, RawShaderMaterial, CustomToneMapping, NeutralToneMapping, AgXToneMapping, ACESFilmicToneMapping, CineonToneMapping, ReinhardToneMapping, LinearToneMapping, Data3DTexture, GreaterEqualCompare, LessEqualCompare, DepthTexture, Texture, GLSL3, VSMShadowMap, PCFShadowMap, AddOperation, MixOperation, MultiplyOperation, LinearTransfer, UniformsUtils, DoubleSide, NormalBlending, TangentSpaceNormalMap, ObjectSpaceNormalMap, Layers, RGFormat, RG11_EAC_Format, RED_GREEN_RGTC2_Format, MeshDepthMaterial, MeshDistanceMaterial, PCFSoftShadowMap, DepthFormat, NearestFilter, CubeDepthTexture, UnsignedIntType, Frustum, LessEqualDepth, ReverseSubtractEquation, SubtractEquation, AddEquation, OneMinusConstantAlphaFactor, ConstantAlphaFactor, OneMinusConstantColorFactor, ConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, DstAlphaFactor, DstColorFactor, SrcAlphaSaturateFactor, SrcAlphaFactor, SrcColorFactor, OneFactor, ZeroFactor, NotEqualDepth, GreaterDepth, GreaterEqualDepth, EqualDepth, LessDepth, AlwaysDepth, NeverDepth, CullFaceNone, CullFaceBack, CullFaceFront, CustomBlending, MultiplyBlending, SubtractiveBlending, AdditiveBlending, ReversedDepthFuncs, MinEquation, MaxEquation, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, LinearMipmapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NotEqualCompare, GreaterCompare, EqualCompare, LessCompare, AlwaysCompare, NeverCompare, NoColorSpace, DepthStencilFormat, getByteLength, UnsignedInt248Type, UnsignedShortType, createElementNS, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedInt5999Type, UnsignedInt101111Type, ByteType, ShortType, AlphaFormat, RGBFormat, RedFormat, RedIntegerFormat, RGIntegerFormat, RGBAIntegerFormat, RGB_S3TC_DXT1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGB_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_PVRTC_2BPPV1_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, R11_EAC_Format, SIGNED_R11_EAC_Format, SIGNED_RG11_EAC_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_BPTC_Format, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, SIGNED_RED_GREEN_RGTC2_Format, ExternalTexture, EventDispatcher, ArrayCamera, WebXRController, RAD2DEG, DataTexture, createCanvasElement, SRGBColorSpace, REVISION, log, WebGLCoordinateSystem, probeAsync } from './three.core.js';
-export { AdditiveAnimationBlendMode, AlwaysStencilFunc, AmbientLight, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrowHelper, AttachedBindMode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BasicDepthPacking, BasicShadowMap, BatchedMesh, BezierInterpolant, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxHelper, BufferGeometryLoader, Cache, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CircleGeometry, Clock, ColorKeyframeTrack, Compatibility, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ConeGeometry, Controls, CubeTextureLoader, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceFrontBack, Curve, CurvePath, CylinderGeometry, Cylindrical, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DetachedBindMode, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DodecahedronGeometry, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, EqualStencilFunc, Euler, ExtrudeGeometry, FileLoader, Float16BufferAttribute, Fog, FogExp2, FramebufferTexture, FrustumArray, GLBufferAttribute, GLSL1, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HTMLTexture, HemisphereLight, HemisphereLightHelper, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateBezier, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InterpolationSamplingMode, InterpolationSamplingType, InvertStencilOp, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LineSegments, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, Loader, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, MOUSE, Material, MaterialBlending, MaterialLoader, MathUtils, Matrix2, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NeverStencilFunc, NoNormalPacking, NormalAnimationBlendMode, NormalGAPacking, NormalRGPacking, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, OctahedronGeometry, Path, PlaneHelper, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RGBADepthPacking, RGBDepthPacking, RGBIntegerFormat, RGDepthPacking, Ray, Raycaster, RectAreaLight, RenderObjectRefreshType, RenderTarget, RenderTarget3D, ReplaceStencilOp, RingGeometry, Scene, ShadowMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, Skeleton, SkeletonHelper, SkinnedMesh, Source, Sphere, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SunLight, TOUCH, TetrahedronGeometry, TextureLoader, TextureSource, TextureUtils, Timer, TimestampQuery, TorusGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry, UVMapping, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, VectorKeyframeTrack, VideoFrameTexture, VideoTexture, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGPUCoordinateSystem, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroSlopeEnding, ZeroStencilOp, getConsoleFunction, setConsoleFunction } from './three.core.js';
+export { AdditiveAnimationBlendMode, AlwaysStencilFunc, AmbientLight, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrowHelper, AttachedBindMode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BasicDepthPacking, BasicShadowMap, BatchedMesh, BezierInterpolant, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxHelper, BufferGeometryLoader, Cache, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CircleGeometry, Clock, ColorKeyframeTrack, Compatibility, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ConeGeometry, Controls, CubeTextureLoader, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceFrontBack, Curve, CurvePath, CylinderGeometry, Cylindrical, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DetachedBindMode, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DodecahedronGeometry, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, EqualStencilFunc, Euler, ExtrudeGeometry, FileLoader, Float16BufferAttribute, Fog, FogExp2, FramebufferTexture, FrustumArray, GLBufferAttribute, GLSL1, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HTMLTexture, HemisphereLight, HemisphereLightHelper, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateBezier, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InterpolationSamplingMode, InterpolationSamplingType, InvertStencilOp, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, LightShadow, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LineSegments, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, Loader, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, MOUSE, Material, MaterialBlending, MaterialLoader, MathUtils, Matrix2, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NeverStencilFunc, NoNormalPacking, NormalAnimationBlendMode, NormalGAPacking, NormalRGPacking, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, OctahedronGeometry, Path, PlaneHelper, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RGBADepthPacking, RGBDepthPacking, RGBIntegerFormat, RGDepthPacking, Ray, Raycaster, RectAreaLight, RenderObjectRefreshType, RenderTarget, RenderTarget3D, ReplaceStencilOp, RingGeometry, Scene, ShadowMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, Skeleton, SkeletonHelper, SkinnedMesh, Source, Sphere, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, TOUCH, TetrahedronGeometry, TextureLoader, TextureSource, TextureUtils, Timer, TimestampQuery, TorusGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry, UVMapping, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, VectorKeyframeTrack, VideoFrameTexture, VideoTexture, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGPUCoordinateSystem, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroSlopeEnding, ZeroStencilOp, getConsoleFunction, setConsoleFunction } from './three.core.js';
function WebGLAnimation() {
@@ -474,7 +474,7 @@ var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUG
var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
-var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_SUN_LIGHT_SHADOWS > 0\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tuniform sampler2DShadow sunShadowMap[ NUM_SUN_LIGHT_SHADOWS ];\n\t\t#else\n\t\t\tuniform sampler2D sunShadowMap[ NUM_SUN_LIGHT_SHADOWS ];\n\t\t#endif\n\t\tuniform mat4 sunShadowMatrix[ NUM_SUN_LIGHT_SHADOWS * 4 ];\n\t\tuniform vec4 sunShadowCascade[ NUM_SUN_LIGHT_SHADOWS * 4 ];\n\t\tvarying vec4 vSunShadowWorldPosition;\n\t\tvarying vec3 vSunShadowWorldNormal;\n\t\tstruct SunLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SunLightShadow sunLightShadows[ NUM_SUN_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tuniform sampler2DShadow directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\t#else\n\t\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\t#endif\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tuniform sampler2DShadow spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\t#else\n\t\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\t#endif\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tuniform samplerCubeShadow pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\t#elif defined( SHADOWMAP_TYPE_BASIC )\n\t\t\tuniform samplerCube pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\t#endif\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\tfloat interleavedGradientNoise( vec2 position ) {\n\t\t\treturn fract( 52.9829189 * fract( dot( position, vec2( 0.06711056, 0.00583715 ) ) ) );\n\t\t}\n\t\tvec2 vogelDiskSample( int sampleIndex, int samplesCount, float phi ) {\n\t\t\tconst float goldenAngle = 2.399963229728653;\n\t\t\tfloat r = sqrt( ( float( sampleIndex ) + 0.5 ) / float( samplesCount ) );\n\t\t\tfloat theta = float( sampleIndex ) * goldenAngle + phi;\n\t\t\treturn vec2( cos( theta ), sin( theta ) ) * r;\n\t\t}\n\t#endif\n\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\tfloat getShadow( sampler2DShadow shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\t\tfloat shadow = 1.0;\n\t\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\t\tshadowCoord.z += shadowBias;\n\t\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\t\tif ( frustumTest ) {\n\t\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\t\tfloat radius = shadowRadius * texelSize.x;\n\t\t\t\tfloat phi = interleavedGradientNoise( gl_FragCoord.xy ) * PI2;\n\t\t\t\tshadow = (\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 0, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 1, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 2, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 3, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 4, 5, phi ) * radius, shadowCoord.z ) )\n\t\t\t\t) * 0.2;\n\t\t\t}\n\t\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t\t}\n\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\t\tfloat shadow = 1.0;\n\t\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tshadowCoord.z -= shadowBias;\n\t\t\t#else\n\t\t\t\tshadowCoord.z += shadowBias;\n\t\t\t#endif\n\t\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\t\tif ( frustumTest ) {\n\t\t\t\tvec2 distribution = texture2D( shadowMap, shadowCoord.xy ).rg;\n\t\t\t\tfloat mean = distribution.x;\n\t\t\t\tfloat variance = distribution.y * distribution.y;\n\t\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\t\tfloat hard_shadow = step( mean, shadowCoord.z );\n\t\t\t\t#else\n\t\t\t\t\tfloat hard_shadow = step( shadowCoord.z, mean );\n\t\t\t\t#endif\n\t\t\t\t\n\t\t\t\tif ( hard_shadow == 1.0 ) {\n\t\t\t\t\tshadow = 1.0;\n\t\t\t\t} else {\n\t\t\t\t\tvariance = max( variance, 0.0000001 );\n\t\t\t\t\tfloat d = shadowCoord.z - mean;\n\t\t\t\t\tfloat p_max = variance / ( variance + d * d );\n\t\t\t\t\tp_max = clamp( ( p_max - 0.3 ) / 0.65, 0.0, 1.0 );\n\t\t\t\t\tshadow = max( hard_shadow, p_max );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t\t}\n\t#else\n\t\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\t\tfloat shadow = 1.0;\n\t\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tshadowCoord.z -= shadowBias;\n\t\t\t#else\n\t\t\t\tshadowCoord.z += shadowBias;\n\t\t\t#endif\n\t\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\t\tif ( frustumTest ) {\n\t\t\t\tfloat depth = texture2D( shadowMap, shadowCoord.xy ).r;\n\t\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\t\tshadow = step( depth, shadowCoord.z );\n\t\t\t\t#else\n\t\t\t\t\tshadow = step( shadowCoord.z, depth );\n\t\t\t\t#endif\n\t\t\t}\n\t\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t\t}\n\t#endif\n\t#if NUM_SUN_LIGHT_SHADOWS > 0\n\t\tfloat getSunShadow(\n\t\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\t\tsampler2DShadow shadowMap,\n\t\t\t#else\n\t\t\t\tsampler2D shadowMap,\n\t\t\t#endif\n\t\t\tSunLightShadow sunLightShadow,\n\t\t\tint shadowIndex\n\t\t) {\n\t\t\tvec4 shadowWorldPosition = vec4( vSunShadowWorldPosition.xyz + vSunShadowWorldNormal * sunLightShadow.shadowNormalBias, 1.0 );\n\t\t\tfloat viewDepth = vSunShadowWorldPosition.w;\n\t\t\tint cascadeOffset = shadowIndex * 4;\n\t\t\tfloat shadow = 1.0;\n\t\t\tfor ( int i = 3; i >= 0; i -- ) {\n\t\t\t\tvec4 cascade = sunShadowCascade[ cascadeOffset + i ];\n\t\t\t\tif ( viewDepth >= cascade.x && viewDepth < cascade.y ) {\n\t\t\t\t\tfloat cascadeShadow = getShadow( shadowMap, sunLightShadow.shadowMapSize, sunLightShadow.shadowIntensity, sunLightShadow.shadowBias, sunLightShadow.shadowRadius, sunShadowMatrix[ cascadeOffset + i ] * shadowWorldPosition );\n\t\t\t\t\tshadow = mix( cascadeShadow, shadow, smoothstep( cascade.z, cascade.y, viewDepth ) );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn shadow;\n\t\t}\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t#if defined( SHADOWMAP_TYPE_PCF )\n\tfloat getPointShadow( samplerCubeShadow shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\tvec3 absVec = abs( lightToPosition );\n\t\tfloat viewSpaceZ = max( max( absVec.x, absVec.y ), absVec.z );\n\t\tif ( viewSpaceZ - shadowCameraFar <= 0.0 && viewSpaceZ - shadowCameraNear >= 0.0 ) {\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tfloat dp = ( shadowCameraNear * ( shadowCameraFar - viewSpaceZ ) ) / ( viewSpaceZ * ( shadowCameraFar - shadowCameraNear ) );\n\t\t\t\tdp -= shadowBias;\n\t\t\t#else\n\t\t\t\tfloat dp = ( shadowCameraFar * ( viewSpaceZ - shadowCameraNear ) ) / ( viewSpaceZ * ( shadowCameraFar - shadowCameraNear ) );\n\t\t\t\tdp += shadowBias;\n\t\t\t#endif\n\t\t\tfloat texelSize = shadowRadius / shadowMapSize.x;\n\t\t\tvec3 absDir = abs( bd3D );\n\t\t\tvec3 tangent = absDir.x > absDir.z ? vec3( 0.0, 1.0, 0.0 ) : vec3( 1.0, 0.0, 0.0 );\n\t\t\ttangent = normalize( cross( bd3D, tangent ) );\n\t\t\tvec3 bitangent = cross( bd3D, tangent );\n\t\t\tfloat phi = interleavedGradientNoise( gl_FragCoord.xy ) * PI2;\n\t\t\tvec2 sample0 = vogelDiskSample( 0, 5, phi );\n\t\t\tvec2 sample1 = vogelDiskSample( 1, 5, phi );\n\t\t\tvec2 sample2 = vogelDiskSample( 2, 5, phi );\n\t\t\tvec2 sample3 = vogelDiskSample( 3, 5, phi );\n\t\t\tvec2 sample4 = vogelDiskSample( 4, 5, phi );\n\t\t\tshadow = (\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample0.x + bitangent * sample0.y ) * texelSize, dp ) ) +\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample1.x + bitangent * sample1.y ) * texelSize, dp ) ) +\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample2.x + bitangent * sample2.y ) * texelSize, dp ) ) +\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample3.x + bitangent * sample3.y ) * texelSize, dp ) ) +\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample4.x + bitangent * sample4.y ) * texelSize, dp ) )\n\t\t\t) * 0.2;\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n\t#elif defined( SHADOWMAP_TYPE_BASIC )\n\tfloat getPointShadow( samplerCube shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tvec3 absVec = abs( lightToPosition );\n\t\tfloat viewSpaceZ = max( max( absVec.x, absVec.y ), absVec.z );\n\t\tif ( viewSpaceZ - shadowCameraFar <= 0.0 && viewSpaceZ - shadowCameraNear >= 0.0 ) {\n\t\t\tfloat dp = ( shadowCameraFar * ( viewSpaceZ - shadowCameraNear ) ) / ( viewSpaceZ * ( shadowCameraFar - shadowCameraNear ) );\n\t\t\tdp += shadowBias;\n\t\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t\tfloat depth = textureCube( shadowMap, bd3D ).r;\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tdepth = 1.0 - depth;\n\t\t\t#endif\n\t\t\tshadow = step( dp, depth );\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n\t#endif\n\t#endif\n#endif";
+var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_SUN_LIGHT_SHADOWS > 0\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tuniform sampler2DShadow sunShadowMap[ NUM_SUN_LIGHT_SHADOWS ];\n\t\t#else\n\t\t\tuniform sampler2D sunShadowMap[ NUM_SUN_LIGHT_SHADOWS ];\n\t\t#endif\n\t\tuniform mat4 sunShadowMatrix[ NUM_SUN_LIGHT_SHADOWS * 2 ];\n\t\tuniform vec4 sunShadowCascade[ NUM_SUN_LIGHT_SHADOWS * 2 ];\n\t\tvarying vec4 vSunShadowWorldPosition;\n\t\tvarying vec3 vSunShadowWorldNormal;\n\t\tstruct SunLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SunLightShadow sunLightShadows[ NUM_SUN_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tuniform sampler2DShadow directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\t#else\n\t\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\t#endif\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tuniform sampler2DShadow spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\t#else\n\t\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\t#endif\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tuniform samplerCubeShadow pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\t#elif defined( SHADOWMAP_TYPE_BASIC )\n\t\t\tuniform samplerCube pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\t#endif\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\tfloat interleavedGradientNoise( vec2 position ) {\n\t\t\treturn fract( 52.9829189 * fract( dot( position, vec2( 0.06711056, 0.00583715 ) ) ) );\n\t\t}\n\t\tvec2 vogelDiskSample( int sampleIndex, int samplesCount, float phi ) {\n\t\t\tconst float goldenAngle = 2.399963229728653;\n\t\t\tfloat r = sqrt( ( float( sampleIndex ) + 0.5 ) / float( samplesCount ) );\n\t\t\tfloat theta = float( sampleIndex ) * goldenAngle + phi;\n\t\t\treturn vec2( cos( theta ), sin( theta ) ) * r;\n\t\t}\n\t#endif\n\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\tfloat getShadow( sampler2DShadow shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\t\tfloat shadow = 1.0;\n\t\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\t\tshadowCoord.z += shadowBias;\n\t\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\t\tif ( frustumTest ) {\n\t\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\t\tfloat radius = shadowRadius * texelSize.x;\n\t\t\t\tfloat phi = interleavedGradientNoise( gl_FragCoord.xy ) * PI2;\n\t\t\t\tshadow = (\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 0, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 1, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 2, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 3, 5, phi ) * radius, shadowCoord.z ) ) +\n\t\t\t\t\ttexture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( 4, 5, phi ) * radius, shadowCoord.z ) )\n\t\t\t\t) * 0.2;\n\t\t\t}\n\t\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t\t}\n\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\t\tfloat shadow = 1.0;\n\t\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tshadowCoord.z -= shadowBias;\n\t\t\t#else\n\t\t\t\tshadowCoord.z += shadowBias;\n\t\t\t#endif\n\t\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\t\tif ( frustumTest ) {\n\t\t\t\tvec2 distribution = texture2D( shadowMap, shadowCoord.xy ).rg;\n\t\t\t\tfloat mean = distribution.x;\n\t\t\t\tfloat variance = distribution.y * distribution.y;\n\t\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\t\tfloat hard_shadow = step( mean, shadowCoord.z );\n\t\t\t\t#else\n\t\t\t\t\tfloat hard_shadow = step( shadowCoord.z, mean );\n\t\t\t\t#endif\n\t\t\t\t\n\t\t\t\tif ( hard_shadow == 1.0 ) {\n\t\t\t\t\tshadow = 1.0;\n\t\t\t\t} else {\n\t\t\t\t\tvariance = max( variance, 0.0000001 );\n\t\t\t\t\tfloat d = shadowCoord.z - mean;\n\t\t\t\t\tfloat p_max = variance / ( variance + d * d );\n\t\t\t\t\tp_max = clamp( ( p_max - 0.3 ) / 0.65, 0.0, 1.0 );\n\t\t\t\t\tshadow = max( hard_shadow, p_max );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t\t}\n\t#else\n\t\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\t\tfloat shadow = 1.0;\n\t\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tshadowCoord.z -= shadowBias;\n\t\t\t#else\n\t\t\t\tshadowCoord.z += shadowBias;\n\t\t\t#endif\n\t\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\t\tif ( frustumTest ) {\n\t\t\t\tfloat depth = texture2D( shadowMap, shadowCoord.xy ).r;\n\t\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\t\tshadow = step( depth, shadowCoord.z );\n\t\t\t\t#else\n\t\t\t\t\tshadow = step( shadowCoord.z, depth );\n\t\t\t\t#endif\n\t\t\t}\n\t\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t\t}\n\t#endif\n\t#if NUM_SUN_LIGHT_SHADOWS > 0\n\t\tfloat getSunShadow(\n\t\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\t\tsampler2DShadow shadowMap,\n\t\t\t#else\n\t\t\t\tsampler2D shadowMap,\n\t\t\t#endif\n\t\t\tSunLightShadow sunLightShadow,\n\t\t\tint shadowIndex\n\t\t) {\n\t\t\tvec4 shadowWorldPosition = vec4( vSunShadowWorldPosition.xyz + vSunShadowWorldNormal * sunLightShadow.shadowNormalBias, 1.0 );\n\t\t\tfloat viewDepth = vSunShadowWorldPosition.w;\n\t\t\tint cascadeOffset = shadowIndex * 2;\n\t\t\tfloat shadow = 1.0;\n\t\t\tfor ( int i = 1; i >= 0; i -- ) {\n\t\t\t\tvec4 cascade = sunShadowCascade[ cascadeOffset + i ];\n\t\t\t\tif ( viewDepth >= cascade.x && viewDepth < cascade.y ) {\n\t\t\t\t\tfloat cascadeShadow = getShadow( shadowMap, sunLightShadow.shadowMapSize, sunLightShadow.shadowIntensity, sunLightShadow.shadowBias, sunLightShadow.shadowRadius, sunShadowMatrix[ cascadeOffset + i ] * shadowWorldPosition );\n\t\t\t\t\tshadow = mix( cascadeShadow, shadow, smoothstep( cascade.z, cascade.y, viewDepth ) );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn shadow;\n\t\t}\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t#if defined( SHADOWMAP_TYPE_PCF )\n\tfloat getPointShadow( samplerCubeShadow shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\tvec3 absVec = abs( lightToPosition );\n\t\tfloat viewSpaceZ = max( max( absVec.x, absVec.y ), absVec.z );\n\t\tif ( viewSpaceZ - shadowCameraFar <= 0.0 && viewSpaceZ - shadowCameraNear >= 0.0 ) {\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tfloat dp = ( shadowCameraNear * ( shadowCameraFar - viewSpaceZ ) ) / ( viewSpaceZ * ( shadowCameraFar - shadowCameraNear ) );\n\t\t\t\tdp -= shadowBias;\n\t\t\t#else\n\t\t\t\tfloat dp = ( shadowCameraFar * ( viewSpaceZ - shadowCameraNear ) ) / ( viewSpaceZ * ( shadowCameraFar - shadowCameraNear ) );\n\t\t\t\tdp += shadowBias;\n\t\t\t#endif\n\t\t\tfloat texelSize = shadowRadius / shadowMapSize.x;\n\t\t\tvec3 absDir = abs( bd3D );\n\t\t\tvec3 tangent = absDir.x > absDir.z ? vec3( 0.0, 1.0, 0.0 ) : vec3( 1.0, 0.0, 0.0 );\n\t\t\ttangent = normalize( cross( bd3D, tangent ) );\n\t\t\tvec3 bitangent = cross( bd3D, tangent );\n\t\t\tfloat phi = interleavedGradientNoise( gl_FragCoord.xy ) * PI2;\n\t\t\tvec2 sample0 = vogelDiskSample( 0, 5, phi );\n\t\t\tvec2 sample1 = vogelDiskSample( 1, 5, phi );\n\t\t\tvec2 sample2 = vogelDiskSample( 2, 5, phi );\n\t\t\tvec2 sample3 = vogelDiskSample( 3, 5, phi );\n\t\t\tvec2 sample4 = vogelDiskSample( 4, 5, phi );\n\t\t\tshadow = (\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample0.x + bitangent * sample0.y ) * texelSize, dp ) ) +\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample1.x + bitangent * sample1.y ) * texelSize, dp ) ) +\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample2.x + bitangent * sample2.y ) * texelSize, dp ) ) +\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample3.x + bitangent * sample3.y ) * texelSize, dp ) ) +\n\t\t\t\ttexture( shadowMap, vec4( bd3D + ( tangent * sample4.x + bitangent * sample4.y ) * texelSize, dp ) )\n\t\t\t) * 0.2;\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n\t#elif defined( SHADOWMAP_TYPE_BASIC )\n\tfloat getPointShadow( samplerCube shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tvec3 absVec = abs( lightToPosition );\n\t\tfloat viewSpaceZ = max( max( absVec.x, absVec.y ), absVec.z );\n\t\tif ( viewSpaceZ - shadowCameraFar <= 0.0 && viewSpaceZ - shadowCameraNear >= 0.0 ) {\n\t\t\tfloat dp = ( shadowCameraFar * ( viewSpaceZ - shadowCameraNear ) ) / ( viewSpaceZ * ( shadowCameraFar - shadowCameraNear ) );\n\t\t\tdp += shadowBias;\n\t\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t\tfloat depth = textureCube( shadowMap, bd3D ).r;\n\t\t\t#ifdef USE_REVERSED_DEPTH_BUFFER\n\t\t\t\tdepth = 1.0 - depth;\n\t\t\t#endif\n\t\t\tshadow = step( dp, depth );\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n\t#endif\n\t#endif\n#endif";
var shadowmap_pars_vertex = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_SUN_LIGHT_SHADOWS > 0\n\t\tvarying vec4 vSunShadowWorldPosition;\n\t\tvarying vec3 vSunShadowWorldNormal;\n\t#endif\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif";
@@ -8601,12 +8601,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 ];
}
@@ -8805,8 +8805,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;
@@ -19291,6 +19291,7 @@ class WebGLRenderer {
_gl.bufferData( _gl.PIXEL_PACK_BUFFER, buffer.byteLength, _gl.STREAM_READ );
_gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), 0 );
+ _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, null );
// reset the frame buffer to the currently set buffer before waiting
const currFramebuffer = _currentRenderTarget !== null ? properties.get( _currentRenderTarget ).__webglFramebuffer : null;
@@ -19306,6 +19307,7 @@ class WebGLRenderer {
// read the data and delete the buffer
_gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer );
_gl.getBufferSubData( _gl.PIXEL_PACK_BUFFER, 0, buffer );
+ _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, null );
_gl.deleteBuffer( glBuffer );
_gl.deleteSync( sync );
diff --git a/build/three.tsl.js b/build/three.tsl.js
index 2577a9b9695eae..7cab6721b991d1 100644
--- a/build/three.tsl.js
+++ b/build/three.tsl.js
@@ -7,6 +7,7 @@ import { TSL } from 'three/webgpu';
const BRDF_GGX = TSL.BRDF_GGX;
const BRDF_Lambert = TSL.BRDF_Lambert;
+const BRDF_Sheen = TSL.BRDF_Sheen;
const BasicPointShadowFilter = TSL.BasicPointShadowFilter;
const BasicShadowFilter = TSL.BasicShadowFilter;
const Break = TSL.Break;
@@ -14,10 +15,13 @@ const Const = TSL.Const;
const Continue = TSL.Continue;
const DFGLUT = TSL.DFGLUT;
const D_GGX = TSL.D_GGX;
+const D_GGX_Anisotropic = TSL.D_GGX_Anisotropic;
const Discard = TSL.Discard;
const EPSILON = TSL.EPSILON;
+const EnvironmentBRDF = TSL.EnvironmentBRDF;
const F_Schlick = TSL.F_Schlick;
const Fn = TSL.Fn;
+const HALF_PI = TSL.HALF_PI;
const INFINITY = TSL.INFINITY;
const If = TSL.If;
const Loop = TSL.Loop;
@@ -25,11 +29,18 @@ const NodeAccess = TSL.NodeAccess;
const NodeShaderStage = TSL.NodeShaderStage;
const NodeType = TSL.NodeType;
const NodeUpdateType = TSL.NodeUpdateType;
+const OnAfterObjectUpdate = TSL.OnAfterObjectUpdate;
+const OnAfterRenderPipeline = TSL.OnAfterRenderPipeline;
+const OnBeforeFrameUpdate = TSL.OnBeforeFrameUpdate;
+const OnBeforeMaterialUpdate = TSL.OnBeforeMaterialUpdate;
+const OnBeforeObjectUpdate = TSL.OnBeforeObjectUpdate;
+const OnBeforeRenderPipeline = TSL.OnBeforeRenderPipeline;
+const OnFrameUpdate = TSL.OnFrameUpdate;
+const OnMaterialUpdate = TSL.OnMaterialUpdate;
+const OnObjectUpdate = TSL.OnObjectUpdate;
const PCFShadowFilter = TSL.PCFShadowFilter;
const PI = TSL.PI;
const PI2 = TSL.PI2;
-const TWO_PI = TSL.TWO_PI;
-const HALF_PI = TSL.HALF_PI;
const PointShadowFilter = TSL.PointShadowFilter;
const Return = TSL.Return;
const Schlick_to_F0 = TSL.Schlick_to_F0;
@@ -37,8 +48,10 @@ const ShaderNode = TSL.ShaderNode;
const Stack = TSL.Stack;
const Switch = TSL.Switch;
const TBNViewMatrix = TSL.TBNViewMatrix;
+const TWO_PI = TSL.TWO_PI;
const VSMShadowFilter = TSL.VSMShadowFilter;
const V_GGX_SmithCorrelated = TSL.V_GGX_SmithCorrelated;
+const V_GGX_SmithCorrelated_Anisotropic = TSL.V_GGX_SmithCorrelated_Anisotropic;
const Var = TSL.Var;
const VarIntent = TSL.VarIntent;
const abs = TSL.abs;
@@ -81,6 +94,7 @@ const backgroundBlurriness = TSL.backgroundBlurriness;
const backgroundIntensity = TSL.backgroundIntensity;
const backgroundRotation = TSL.backgroundRotation;
const batch = TSL.batch;
+const batchColor = TSL.batchColor;
const batchIndirectIndex = TSL.batchIndirectIndex;
const bentNormalView = TSL.bentNormalView;
const billboarding = TSL.billboarding;
@@ -91,6 +105,7 @@ const bitXor = TSL.bitXor;
const bitangentGeometry = TSL.bitangentGeometry;
const bitangentLocal = TSL.bitangentLocal;
const bitangentView = TSL.bitangentView;
+const bitangentViewFrame = TSL.bitangentViewFrame;
const bitangentWorld = TSL.bitangentWorld;
const bitcast = TSL.bitcast;
const blendBurn = TSL.blendBurn;
@@ -101,10 +116,10 @@ const blendScreen = TSL.blendScreen;
const bool = TSL.bool;
const buffer = TSL.buffer;
const bufferAttribute = TSL.bufferAttribute;
-const bumpMap = TSL.bumpMap;
const builtin = TSL.builtin;
const builtinAOContext = TSL.builtinAOContext;
const builtinShadowContext = TSL.builtinShadowContext;
+const bumpMap = TSL.bumpMap;
const bvec2 = TSL.bvec2;
const bvec3 = TSL.bvec3;
const bvec4 = TSL.bvec4;
@@ -131,6 +146,8 @@ const clearcoat = TSL.clearcoat;
const clearcoatNormalView = TSL.clearcoatNormalView;
const clearcoatRoughness = TSL.clearcoatRoughness;
const clipSpace = TSL.clipSpace;
+const clipping = TSL.clipping;
+const clippingAlpha = TSL.clippingAlpha;
const code = TSL.code;
const color = TSL.color;
const colorSpaceToWorking = TSL.colorSpaceToWorking;
@@ -142,11 +159,11 @@ const context = TSL.context;
const convert = TSL.convert;
const convertColorSpace = TSL.convertColorSpace;
const convertToTexture = TSL.convertToTexture;
+const cos = TSL.cos;
+const cosh = TSL.cosh;
const countLeadingZeros = TSL.countLeadingZeros;
const countOneBits = TSL.countOneBits;
const countTrailingZeros = TSL.countTrailingZeros;
-const cos = TSL.cos;
-const cosh = TSL.cosh;
const cross = TSL.cross;
const cubeTexture = TSL.cubeTexture;
const cubeTextureBase = TSL.cubeTextureBase;
@@ -161,13 +178,13 @@ const defaultShaderStages = TSL.defaultShaderStages;
const defined = TSL.defined;
const degrees = TSL.degrees;
const deltaTime = TSL.deltaTime;
-const densityFog = TSL.densityFog;
const densityFogFactor = TSL.densityFogFactor;
const depth = TSL.depth;
const depthPass = TSL.depthPass;
const determinant = TSL.determinant;
const difference = TSL.difference;
const diffuseColor = TSL.diffuseColor;
+const diffuseContribution = TSL.diffuseContribution;
const directPointLight = TSL.directPointLight;
const directionToColor = TSL.directionToColor;
const directionToFaceDirection = TSL.directionToFaceDirection;
@@ -206,15 +223,11 @@ const getCurrentStack = TSL.getCurrentStack;
const getDistanceAttenuation = TSL.getDistanceAttenuation;
const getGeometryRoughness = TSL.getGeometryRoughness;
const getNormalFromDepth = TSL.getNormalFromDepth;
-const interleavedGradientNoise = TSL.interleavedGradientNoise;
-const vogelDiskSample = TSL.vogelDiskSample;
const getParallaxCorrectNormal = TSL.getParallaxCorrectNormal;
const getRoughness = TSL.getRoughness;
const getScreenPosition = TSL.getScreenPosition;
const getScreenPositionFromClip = TSL.getScreenPositionFromClip;
const getShIrradianceAt = TSL.getShIrradianceAt;
-const getShadowMaterial = TSL.getShadowMaterial;
-const getShadowRenderObjectFunction = TSL.getShadowRenderObjectFunction;
const getTextureIndex = TSL.getTextureIndex;
const getViewPosition = TSL.getViewPosition;
const globalId = TSL.globalId;
@@ -223,13 +236,16 @@ const glslFn = TSL.glslFn;
const grayscale = TSL.grayscale;
const greaterThan = TSL.greaterThan;
const greaterThanEqual = TSL.greaterThanEqual;
+const hardwareClipping = TSL.hardwareClipping;
const hash = TSL.hash;
const highpModelNormalViewMatrix = TSL.highpModelNormalViewMatrix;
const highpModelViewMatrix = TSL.highpModelViewMatrix;
const hue = TSL.hue;
const increment = TSL.increment;
const incrementBefore = TSL.incrementBefore;
+const inspect = TSL.inspect;
const instance = TSL.instance;
+const instanceColor = TSL.instanceColor;
const instanceIndex = TSL.instanceIndex;
const instancedArray = TSL.instancedArray;
const instancedBufferAttribute = TSL.instancedBufferAttribute;
@@ -237,6 +253,7 @@ const instancedDynamicBufferAttribute = TSL.instancedDynamicBufferAttribute;
const instancedMesh = TSL.instancedMesh;
const int = TSL.int;
const intBitsToFloat = TSL.intBitsToFloat;
+const interleavedGradientNoise = TSL.interleavedGradientNoise;
const inverse = TSL.inverse;
const inverseSqrt = TSL.inverseSqrt;
const inversesqrt = TSL.inversesqrt;
@@ -246,6 +263,7 @@ const ior = TSL.ior;
const iridescence = TSL.iridescence;
const iridescenceIOR = TSL.iridescenceIOR;
const iridescenceThickness = TSL.iridescenceThickness;
+const isolate = TSL.isolate;
const ivec2 = TSL.ivec2;
const ivec3 = TSL.ivec3;
const ivec4 = TSL.ivec4;
@@ -345,8 +363,8 @@ const mx_cell_noise_float = TSL.mx_cell_noise_float;
const mx_cell_noise_vec3 = TSL.mx_cell_noise_vec3;
const mx_contrast = TSL.mx_contrast;
const mx_divide = TSL.mx_divide;
-const mx_fractal_noise_float_2d = TSL.mx_fractal_noise_float_2d;
const mx_fractal_noise_float = TSL.mx_fractal_noise_float;
+const mx_fractal_noise_float_2d = TSL.mx_fractal_noise_float_2d;
const mx_fractal_noise_vec2 = TSL.mx_fractal_noise_vec2;
const mx_fractal_noise_vec3 = TSL.mx_fractal_noise_vec3;
const mx_fractal_noise_vec4 = TSL.mx_fractal_noise_vec4;
@@ -396,6 +414,7 @@ const nodeObject = TSL.nodeObject;
const nodeObjectIntent = TSL.nodeObjectIntent;
const nodeObjects = TSL.nodeObjects;
const nodeProxy = TSL.nodeProxy;
+const nodeProxyConstructor = TSL.nodeProxyConstructor;
const nodeProxyIntent = TSL.nodeProxyIntent;
const normalFlat = TSL.normalFlat;
const normalGeometry = TSL.normalGeometry;
@@ -416,13 +435,6 @@ const objectRadius = TSL.objectRadius;
const objectScale = TSL.objectScale;
const objectViewPosition = TSL.objectViewPosition;
const objectWorldMatrix = TSL.objectWorldMatrix;
-const OnAfterObjectUpdate = TSL.OnAfterObjectUpdate;
-const OnBeforeObjectUpdate = TSL.OnBeforeObjectUpdate;
-const OnBeforeMaterialUpdate = TSL.OnBeforeMaterialUpdate;
-const OnBeforeRenderPipeline = TSL.OnBeforeRenderPipeline;
-const OnAfterRenderPipeline = TSL.OnAfterRenderPipeline;
-const OnObjectUpdate = TSL.OnObjectUpdate;
-const OnMaterialUpdate = TSL.OnMaterialUpdate;
const oneMinus = TSL.oneMinus;
const or = TSL.or;
const orthographicDepthToViewZ = TSL.orthographicDepthToViewZ;
@@ -436,11 +448,11 @@ const overloadingFn = TSL.overloadingFn;
const overrideNode = TSL.overrideNode;
const overrideNodes = TSL.overrideNodes;
const packHalf2x16 = TSL.packHalf2x16;
+const packNormalToRGB = TSL.packNormalToRGB;
const packSnorm2x16 = TSL.packSnorm2x16;
-const packUnorm2x16 = TSL.packUnorm2x16;
const packSnorm4x8 = TSL.packSnorm4x8;
+const packUnorm2x16 = TSL.packUnorm2x16;
const packUnorm4x8 = TSL.packUnorm4x8;
-const packNormalToRGB = TSL.packNormalToRGB;
const parabola = TSL.parabola;
const parallaxDirection = TSL.parallaxDirection;
const parallaxUV = TSL.parallaxUV;
@@ -467,10 +479,13 @@ const pow3 = TSL.pow3;
const pow4 = TSL.pow4;
const premultiplyAlpha = TSL.premultiplyAlpha;
const property = TSL.property;
+const quadBroadcast = TSL.quadBroadcast;
+const quadSwapDiagonal = TSL.quadSwapDiagonal;
+const quadSwapX = TSL.quadSwapX;
+const quadSwapY = TSL.quadSwapY;
const radians = TSL.radians;
const rand = TSL.rand;
const range = TSL.range;
-const rangeFog = TSL.rangeFog;
const rangeFogFactor = TSL.rangeFogFactor;
const reciprocal = TSL.reciprocal;
const reference = TSL.reference;
@@ -483,13 +498,13 @@ const refract = TSL.refract;
const refractVector = TSL.refractVector;
const refractView = TSL.refractView;
const reinhardToneMapping = TSL.reinhardToneMapping;
-const retroreflectivity = TSL.retroreflectivity;
const remap = TSL.remap;
const remapClamp = TSL.remapClamp;
const renderGroup = TSL.renderGroup;
const renderOutput = TSL.renderOutput;
const rendererReference = TSL.rendererReference;
const replaceDefaultUV = TSL.replaceDefaultUV;
+const retroreflectivity = TSL.retroreflectivity;
const rotate = TSL.rotate;
const rotateUV = TSL.rotateUV;
const roughness = TSL.roughness;
@@ -502,7 +517,6 @@ const sampler = TSL.sampler;
const samplerComparison = TSL.samplerComparison;
const saturate = TSL.saturate;
const saturation = TSL.saturation;
-const screen = TSL.screen;
const screenCoordinate = TSL.screenCoordinate;
const screenDPR = TSL.screenDPR;
const screenSize = TSL.screenSize;
@@ -522,12 +536,13 @@ const shiftRight = TSL.shiftRight;
const shininess = TSL.shininess;
const sign = TSL.sign;
const sin = TSL.sin;
-const sinh = TSL.sinh;
const sinc = TSL.sinc;
+const sinh = TSL.sinh;
const skinning = TSL.skinning;
const smoothstep = TSL.smoothstep;
const smoothstepElement = TSL.smoothstepElement;
const specularColor = TSL.specularColor;
+const specularColorBlended = TSL.specularColorBlended;
const specularF90 = TSL.specularF90;
const spherizeUV = TSL.spherizeUV;
const split = TSL.split;
@@ -538,10 +553,12 @@ const step = TSL.step;
const stepElement = TSL.stepElement;
const storage = TSL.storage;
const storageBarrier = TSL.storageBarrier;
+const storageElement = TSL.storageElement;
const storageTexture = TSL.storageTexture;
const storageTexture3D = TSL.storageTexture3D;
const struct = TSL.struct;
const sub = TSL.sub;
+const subBuild = TSL.subBuild;
const subgroupAdd = TSL.subgroupAdd;
const subgroupAll = TSL.subgroupAll;
const subgroupAnd = TSL.subgroupAnd;
@@ -549,7 +566,6 @@ const subgroupAny = TSL.subgroupAny;
const subgroupBallot = TSL.subgroupBallot;
const subgroupBroadcast = TSL.subgroupBroadcast;
const subgroupBroadcastFirst = TSL.subgroupBroadcastFirst;
-const subBuild = TSL.subBuild;
const subgroupElect = TSL.subgroupElect;
const subgroupExclusiveAdd = TSL.subgroupExclusiveAdd;
const subgroupExclusiveMul = TSL.subgroupExclusiveMul;
@@ -567,19 +583,22 @@ const subgroupShuffleXor = TSL.subgroupShuffleXor;
const subgroupSize = TSL.subgroupSize;
const subgroupXor = TSL.subgroupXor;
const tan = TSL.tan;
-const tanh = TSL.tanh;
const tangentGeometry = TSL.tangentGeometry;
const tangentLocal = TSL.tangentLocal;
const tangentView = TSL.tangentView;
+const tangentViewFrame = TSL.tangentViewFrame;
const tangentWorld = TSL.tangentWorld;
+const tanh = TSL.tanh;
const texture = TSL.texture;
const texture3D = TSL.texture3D;
+const texture3DLevel = TSL.texture3DLevel;
+const texture3DLoad = TSL.texture3DLoad;
const textureBarrier = TSL.textureBarrier;
const textureBicubic = TSL.textureBicubic;
const textureBicubicLevel = TSL.textureBicubicLevel;
+const textureLevel = TSL.textureLevel;
const textureLoad = TSL.textureLoad;
const textureSize = TSL.textureSize;
-const textureLevel = TSL.textureLevel;
const textureStore = TSL.textureStore;
const thickness = TSL.thickness;
const time = TSL.time;
@@ -605,15 +624,16 @@ const uintBitsToFloat = TSL.uintBitsToFloat;
const uniform = TSL.uniform;
const uniformArray = TSL.uniformArray;
const uniformCubeTexture = TSL.uniformCubeTexture;
-const uniformGroup = TSL.uniformGroup;
const uniformFlow = TSL.uniformFlow;
+const uniformGroup = TSL.uniformGroup;
const uniformTexture = TSL.uniformTexture;
const unpackHalf2x16 = TSL.unpackHalf2x16;
+const unpackNormal = TSL.unpackNormal;
+const unpackRGBToNormal = TSL.unpackRGBToNormal;
const unpackSnorm2x16 = TSL.unpackSnorm2x16;
-const unpackUnorm2x16 = TSL.unpackUnorm2x16;
const unpackSnorm4x8 = TSL.unpackSnorm4x8;
+const unpackUnorm2x16 = TSL.unpackUnorm2x16;
const unpackUnorm4x8 = TSL.unpackUnorm4x8;
-const unpackRGBToNormal = TSL.unpackRGBToNormal;
const unpremultiplyAlpha = TSL.unpremultiplyAlpha;
const userData = TSL.userData;
const uv = TSL.uv;
@@ -647,6 +667,7 @@ const viewportSharedTexture = TSL.viewportSharedTexture;
const viewportSize = TSL.viewportSize;
const viewportTexture = TSL.viewportTexture;
const viewportUV = TSL.viewportUV;
+const vogelDiskSample = TSL.vogelDiskSample;
const wgsl = TSL.wgsl;
const wgslFn = TSL.wgslFn;
const workgroupArray = TSL.workgroupArray;
@@ -655,18 +676,4 @@ const workgroupId = TSL.workgroupId;
const workingToColorSpace = TSL.workingToColorSpace;
const xor = TSL.xor;
-/*
-// Use this code to generate the export statements dynamically
-
-let code = '';
-
-for ( const key of Object.keys( THREE.TSL ) ) {
-
- code += `export const ${ key } = TSL.${ key };\n`;
-
-}
-
-log( code );
-//*/
-
-export { BRDF_GGX, BRDF_Lambert, BasicPointShadowFilter, BasicShadowFilter, Break, Const, Continue, DFGLUT, D_GGX, Discard, EPSILON, F_Schlick, Fn, HALF_PI, INFINITY, If, Loop, NodeAccess, NodeShaderStage, NodeType, NodeUpdateType, OnAfterObjectUpdate, OnAfterRenderPipeline, OnBeforeMaterialUpdate, OnBeforeObjectUpdate, OnBeforeRenderPipeline, OnMaterialUpdate, OnObjectUpdate, PCFShadowFilter, PI, PI2, PointShadowFilter, Return, Schlick_to_F0, ShaderNode, Stack, Switch, TBNViewMatrix, TWO_PI, VSMShadowFilter, V_GGX_SmithCorrelated, Var, VarIntent, abs, acesFilmicToneMapping, acos, acosh, add, addMethodChaining, addNodeElement, agxToneMapping, all, alphaT, ambientOcclusion, and, anisotropy, anisotropyB, anisotropyT, any, array, asin, asinh, assign, atan, atanh, atomicAdd, atomicAnd, atomicFunc, atomicLoad, atomicMax, atomicMin, atomicOr, atomicStore, atomicSub, atomicXor, attenuationColor, attenuationDistance, attribute, attributeArray, backgroundBlurriness, backgroundIntensity, backgroundRotation, batch, batchIndirectIndex, bentNormalView, billboarding, bitAnd, bitNot, bitOr, bitXor, bitangentGeometry, bitangentLocal, bitangentView, bitangentWorld, bitcast, blendBurn, blendColor, blendDodge, blendOverlay, blendScreen, bool, buffer, bufferAttribute, builtin, builtinAOContext, builtinShadowContext, bumpMap, bvec2, bvec3, bvec4, bypass, cache, call, cameraFar, cameraIndex, cameraNear, cameraNormalMatrix, cameraPosition, cameraProjectionMatrix, cameraProjectionMatrixInverse, cameraViewMatrix, cameraViewport, cameraWorldMatrix, cbrt, cdl, ceil, checker, cineonToneMapping, clamp, clearcoat, clearcoatNormalView, clearcoatRoughness, clipSpace, code, color, colorSpaceToWorking, colorToDirection, compute, computeKernel, computeSkinning, context, convert, convertColorSpace, convertToTexture, cos, cosh, countLeadingZeros, countOneBits, countTrailingZeros, cross, cubeTexture, cubeTextureBase, dFdx, dFdy, dashSize, debug, decrement, decrementBefore, defaultBuildStages, defaultShaderStages, defined, degrees, deltaTime, densityFog, densityFogFactor, depth, depthPass, determinant, difference, diffuseColor, directPointLight, directionToColor, directionToFaceDirection, dispersion, distance, div, dot, drawIndex, dynamicBufferAttribute, element, emissive, equal, equirectDirection, equirectUV, exp, exp2, exponentialHeightFogFactor, expression, faceDirection, faceForward, faceforward, float, floatBitsToInt, floatBitsToUint, floor, fog, fract, frameGroup, frameId, frontFacing, fwidth, gain, gapSize, getConstNodeType, getCurrentStack, getDistanceAttenuation, getGeometryRoughness, getNormalFromDepth, getParallaxCorrectNormal, getRoughness, getScreenPosition, getScreenPositionFromClip, getShIrradianceAt, getShadowMaterial, getShadowRenderObjectFunction, getTextureIndex, getViewPosition, globalId, glsl, glslFn, grayscale, greaterThan, greaterThanEqual, hash, highpModelNormalViewMatrix, highpModelViewMatrix, hue, increment, incrementBefore, instance, instanceIndex, instancedArray, instancedBufferAttribute, instancedDynamicBufferAttribute, instancedMesh, int, intBitsToFloat, interleavedGradientNoise, inverse, inverseSqrt, inversesqrt, invocationLocalIndex, invocationSubgroupIndex, ior, iridescence, iridescenceIOR, iridescenceThickness, ivec2, ivec3, ivec4, js, label, length, lengthSq, lessThan, lessThanEqual, lightPosition, lightProjectionUV, lightShadowMatrix, lightTargetDirection, lightTargetPosition, lightViewPosition, lightingContext, lights, linearDepth, linearToneMapping, localId, log, log2, logarithmicDepthToViewZ, luminance, mat2, mat3, mat4, matcapUV, materialAO, materialAlphaTest, materialAnisotropy, materialAnisotropyVector, materialAttenuationColor, materialAttenuationDistance, materialClearcoat, materialClearcoatNormal, materialClearcoatRoughness, materialColor, materialDispersion, materialEmissive, materialEnvIntensity, materialEnvRotation, materialIOR, materialIridescence, materialIridescenceIOR, materialIridescenceThickness, materialLightMap, materialLineDashOffset, materialLineDashSize, materialLineGapSize, materialLineScale, materialLineWidth, materialMetalness, materialNormal, materialOpacity, materialPointSize, materialReference, materialReflectivity, materialRefractionRatio, materialRetroreflectivity, materialRotation, materialRoughness, materialSheen, materialSheenRoughness, materialShininess, materialSpecular, materialSpecularColor, materialSpecularIntensity, materialSpecularStrength, materialThickness, materialTransmission, max, maxMipLevel, mediumpModelViewMatrix, metalness, min, mix, mixElement, mod, modelDirection, modelNormalMatrix, modelPosition, modelRadius, modelScale, modelViewMatrix, modelViewPosition, modelViewProjection, modelWorldMatrix, modelWorldMatrixInverse, morphReference, mrt, mul, mx_aastep, mx_add, mx_atan2, mx_cell_noise_float, mx_cell_noise_vec3, mx_contrast, mx_divide, mx_fractal_noise_float, mx_fractal_noise_float_2d, mx_fractal_noise_vec2, mx_fractal_noise_vec3, mx_fractal_noise_vec4, mx_frame, mx_heighttonormal, mx_hsvtorgb, mx_ifequal, mx_ifgreater, mx_ifgreatereq, mx_invert, mx_modulo, mx_multiply, mx_noise_float, mx_noise_vec3, mx_noise_vec4, mx_place2d, mx_power, mx_ramp4, mx_ramplr, mx_ramptb, mx_rgbtohsv, mx_rotate2d, mx_rotate3d, mx_safepower, mx_separate, mx_smoothstep, mx_splitlr, mx_splittb, mx_srgb_texture_to_lin_rec709, mx_subtract, mx_timer, mx_transform_uv, mx_unifiednoise2d, mx_unifiednoise3d, mx_worley_noise_float, mx_worley_noise_float_2d, mx_worley_noise_float_3d, mx_worley_noise_vec2, mx_worley_noise_vec3, mx_worley_noise_vec3_style, negate, negateOnBackSide, neutralToneMapping, nodeArray, nodeImmutable, nodeObject, nodeObjectIntent, nodeObjects, nodeProxy, nodeProxyIntent, normalFlat, normalGeometry, normalLocal, normalMap, normalView, normalViewGeometry, normalWorld, normalWorldGeometry, normalize, not, notEqual, numWorkgroups, objectDirection, objectGroup, objectPosition, objectRadius, objectScale, objectViewPosition, objectWorldMatrix, oneMinus, or, orthographicDepthToViewZ, oscSawtooth, oscSine, oscSquare, oscTriangle, output, outputStruct, overloadingFn, overrideNode, overrideNodes, packHalf2x16, packNormalToRGB, packSnorm2x16, packSnorm4x8, packUnorm2x16, packUnorm4x8, parabola, parallaxDirection, parallaxUV, parameter, pass, passTexture, pcurve, perspectiveDepthToViewZ, pmremTexture, pointShadow, pointUV, pointWidth, positionGeometry, positionLocal, positionPrevious, positionView, positionViewDirection, positionWorld, positionWorldDirection, posterize, pow, pow2, pow3, pow4, premultiplyAlpha, property, radians, rand, range, rangeFog, rangeFogFactor, reciprocal, reference, referenceBuffer, reflect, reflectVector, reflectView, reflector, refract, refractVector, refractView, reinhardToneMapping, remap, remapClamp, renderGroup, renderOutput, rendererReference, replaceDefaultUV, retroreflectivity, rotate, rotateUV, roughness, round, rtt, sRGBTransferEOTF, sRGBTransferOETF, sample, sampler, samplerComparison, saturate, saturation, screen, screenCoordinate, screenDPR, screenSize, screenUV, select, setCurrentStack, setName, shaderStages, shadow, shadowPositionWorld, shapeCircle, sharedUniformGroup, sheen, sheenRoughness, shiftLeft, shiftRight, shininess, sign, sin, sinc, sinh, skinning, smoothstep, smoothstepElement, specularColor, specularF90, spherizeUV, split, spritesheetUV, sqrt, stack, step, stepElement, storage, storageBarrier, storageTexture, storageTexture3D, struct, sub, subBuild, subgroupAdd, subgroupAll, subgroupAnd, subgroupAny, subgroupBallot, subgroupBroadcast, subgroupBroadcastFirst, subgroupElect, subgroupExclusiveAdd, subgroupExclusiveMul, subgroupInclusiveAdd, subgroupInclusiveMul, subgroupIndex, subgroupMax, subgroupMin, subgroupMul, subgroupOr, subgroupShuffle, subgroupShuffleDown, subgroupShuffleUp, subgroupShuffleXor, subgroupSize, subgroupXor, tan, tangentGeometry, tangentLocal, tangentView, tangentWorld, tanh, texture, texture3D, textureBarrier, textureBicubic, textureBicubicLevel, textureLevel, textureLoad, textureSize, textureStore, thickness, time, toneMapping, toneMappingExposure, toonOutlinePass, transformDirection, transformNormal, transformNormalByInverseViewMatrix, transformNormalByViewMatrix, transformNormalToView, transformedClearcoatNormalView, transformedNormalView, transformedNormalWorld, transmission, transpose, triNoise3D, triplanarTexture, triplanarTextures, trunc, uint, uintBitsToFloat, uniform, uniformArray, uniformCubeTexture, uniformFlow, uniformGroup, uniformTexture, unpackHalf2x16, unpackRGBToNormal, unpackSnorm2x16, unpackSnorm4x8, unpackUnorm2x16, unpackUnorm4x8, unpremultiplyAlpha, userData, uv, uvec2, uvec3, uvec4, varying, varyingProperty, vec2, vec3, vec4, vectorComponents, velocity, vertexColor, vertexIndex, vertexStage, vibrance, viewZToLogarithmicDepth, viewZToOrthographicDepth, viewZToPerspectiveDepth, viewZToReversedOrthographicDepth, viewZToReversedPerspectiveDepth, viewport, viewportCoordinate, viewportDepthTexture, viewportLinearDepth, viewportMipTexture, viewportOpaqueMipTexture, viewportSafeUV, viewportSharedTexture, viewportSize, viewportTexture, viewportUV, vogelDiskSample, wgsl, wgslFn, workgroupArray, workgroupBarrier, workgroupId, workingToColorSpace, xor };
+export { BRDF_GGX, BRDF_Lambert, BRDF_Sheen, BasicPointShadowFilter, BasicShadowFilter, Break, Const, Continue, DFGLUT, D_GGX, D_GGX_Anisotropic, Discard, EPSILON, EnvironmentBRDF, F_Schlick, Fn, HALF_PI, INFINITY, If, Loop, NodeAccess, NodeShaderStage, NodeType, NodeUpdateType, OnAfterObjectUpdate, OnAfterRenderPipeline, OnBeforeFrameUpdate, OnBeforeMaterialUpdate, OnBeforeObjectUpdate, OnBeforeRenderPipeline, OnFrameUpdate, OnMaterialUpdate, OnObjectUpdate, PCFShadowFilter, PI, PI2, PointShadowFilter, Return, Schlick_to_F0, ShaderNode, Stack, Switch, TBNViewMatrix, TWO_PI, VSMShadowFilter, V_GGX_SmithCorrelated, V_GGX_SmithCorrelated_Anisotropic, Var, VarIntent, abs, acesFilmicToneMapping, acos, acosh, add, addMethodChaining, addNodeElement, agxToneMapping, all, alphaT, ambientOcclusion, and, anisotropy, anisotropyB, anisotropyT, any, array, asin, asinh, assign, atan, atanh, atomicAdd, atomicAnd, atomicFunc, atomicLoad, atomicMax, atomicMin, atomicOr, atomicStore, atomicSub, atomicXor, attenuationColor, attenuationDistance, attribute, attributeArray, backgroundBlurriness, backgroundIntensity, backgroundRotation, batch, batchColor, batchIndirectIndex, bentNormalView, billboarding, bitAnd, bitNot, bitOr, bitXor, bitangentGeometry, bitangentLocal, bitangentView, bitangentViewFrame, bitangentWorld, bitcast, blendBurn, blendColor, blendDodge, blendOverlay, blendScreen, bool, buffer, bufferAttribute, builtin, builtinAOContext, builtinShadowContext, bumpMap, bvec2, bvec3, bvec4, bypass, cache, call, cameraFar, cameraIndex, cameraNear, cameraNormalMatrix, cameraPosition, cameraProjectionMatrix, cameraProjectionMatrixInverse, cameraViewMatrix, cameraViewport, cameraWorldMatrix, cbrt, cdl, ceil, checker, cineonToneMapping, clamp, clearcoat, clearcoatNormalView, clearcoatRoughness, clipSpace, clipping, clippingAlpha, code, color, colorSpaceToWorking, colorToDirection, compute, computeKernel, computeSkinning, context, convert, convertColorSpace, convertToTexture, cos, cosh, countLeadingZeros, countOneBits, countTrailingZeros, cross, cubeTexture, cubeTextureBase, dFdx, dFdy, dashSize, debug, decrement, decrementBefore, defaultBuildStages, defaultShaderStages, defined, degrees, deltaTime, densityFogFactor, depth, depthPass, determinant, difference, diffuseColor, diffuseContribution, directPointLight, directionToColor, directionToFaceDirection, dispersion, distance, div, dot, drawIndex, dynamicBufferAttribute, element, emissive, equal, equirectDirection, equirectUV, exp, exp2, exponentialHeightFogFactor, expression, faceDirection, faceForward, faceforward, float, floatBitsToInt, floatBitsToUint, floor, fog, fract, frameGroup, frameId, frontFacing, fwidth, gain, gapSize, getConstNodeType, getCurrentStack, getDistanceAttenuation, getGeometryRoughness, getNormalFromDepth, getParallaxCorrectNormal, getRoughness, getScreenPosition, getScreenPositionFromClip, getShIrradianceAt, getTextureIndex, getViewPosition, globalId, glsl, glslFn, grayscale, greaterThan, greaterThanEqual, hardwareClipping, hash, highpModelNormalViewMatrix, highpModelViewMatrix, hue, increment, incrementBefore, inspect, instance, instanceColor, instanceIndex, instancedArray, instancedBufferAttribute, instancedDynamicBufferAttribute, instancedMesh, int, intBitsToFloat, interleavedGradientNoise, inverse, inverseSqrt, inversesqrt, invocationLocalIndex, invocationSubgroupIndex, ior, iridescence, iridescenceIOR, iridescenceThickness, isolate, ivec2, ivec3, ivec4, js, label, length, lengthSq, lessThan, lessThanEqual, lightPosition, lightProjectionUV, lightShadowMatrix, lightTargetDirection, lightTargetPosition, lightViewPosition, lightingContext, lights, linearDepth, linearToneMapping, localId, log, log2, logarithmicDepthToViewZ, luminance, mat2, mat3, mat4, matcapUV, materialAO, materialAlphaTest, materialAnisotropy, materialAnisotropyVector, materialAttenuationColor, materialAttenuationDistance, materialClearcoat, materialClearcoatNormal, materialClearcoatRoughness, materialColor, materialDispersion, materialEmissive, materialEnvIntensity, materialEnvRotation, materialIOR, materialIridescence, materialIridescenceIOR, materialIridescenceThickness, materialLightMap, materialLineDashOffset, materialLineDashSize, materialLineGapSize, materialLineScale, materialLineWidth, materialMetalness, materialNormal, materialOpacity, materialPointSize, materialReference, materialReflectivity, materialRefractionRatio, materialRetroreflectivity, materialRotation, materialRoughness, materialSheen, materialSheenRoughness, materialShininess, materialSpecular, materialSpecularColor, materialSpecularIntensity, materialSpecularStrength, materialThickness, materialTransmission, max, maxMipLevel, mediumpModelViewMatrix, metalness, min, mix, mixElement, mod, modelDirection, modelNormalMatrix, modelPosition, modelRadius, modelScale, modelViewMatrix, modelViewPosition, modelViewProjection, modelWorldMatrix, modelWorldMatrixInverse, morphReference, mrt, mul, mx_aastep, mx_add, mx_atan2, mx_cell_noise_float, mx_cell_noise_vec3, mx_contrast, mx_divide, mx_fractal_noise_float, mx_fractal_noise_float_2d, mx_fractal_noise_vec2, mx_fractal_noise_vec3, mx_fractal_noise_vec4, mx_frame, mx_heighttonormal, mx_hsvtorgb, mx_ifequal, mx_ifgreater, mx_ifgreatereq, mx_invert, mx_modulo, mx_multiply, mx_noise_float, mx_noise_vec3, mx_noise_vec4, mx_place2d, mx_power, mx_ramp4, mx_ramplr, mx_ramptb, mx_rgbtohsv, mx_rotate2d, mx_rotate3d, mx_safepower, mx_separate, mx_smoothstep, mx_splitlr, mx_splittb, mx_srgb_texture_to_lin_rec709, mx_subtract, mx_timer, mx_transform_uv, mx_unifiednoise2d, mx_unifiednoise3d, mx_worley_noise_float, mx_worley_noise_float_2d, mx_worley_noise_float_3d, mx_worley_noise_vec2, mx_worley_noise_vec3, mx_worley_noise_vec3_style, negate, negateOnBackSide, neutralToneMapping, nodeArray, nodeImmutable, nodeObject, nodeObjectIntent, nodeObjects, nodeProxy, nodeProxyConstructor, nodeProxyIntent, normalFlat, normalGeometry, normalLocal, normalMap, normalView, normalViewGeometry, normalWorld, normalWorldGeometry, normalize, not, notEqual, numWorkgroups, objectDirection, objectGroup, objectPosition, objectRadius, objectScale, objectViewPosition, objectWorldMatrix, oneMinus, or, orthographicDepthToViewZ, oscSawtooth, oscSine, oscSquare, oscTriangle, output, outputStruct, overloadingFn, overrideNode, overrideNodes, packHalf2x16, packNormalToRGB, packSnorm2x16, packSnorm4x8, packUnorm2x16, packUnorm4x8, parabola, parallaxDirection, parallaxUV, parameter, pass, passTexture, pcurve, perspectiveDepthToViewZ, pmremTexture, pointShadow, pointUV, pointWidth, positionGeometry, positionLocal, positionPrevious, positionView, positionViewDirection, positionWorld, positionWorldDirection, posterize, pow, pow2, pow3, pow4, premultiplyAlpha, property, quadBroadcast, quadSwapDiagonal, quadSwapX, quadSwapY, radians, rand, range, rangeFogFactor, reciprocal, reference, referenceBuffer, reflect, reflectVector, reflectView, reflector, refract, refractVector, refractView, reinhardToneMapping, remap, remapClamp, renderGroup, renderOutput, rendererReference, replaceDefaultUV, retroreflectivity, rotate, rotateUV, roughness, round, rtt, sRGBTransferEOTF, sRGBTransferOETF, sample, sampler, samplerComparison, saturate, saturation, screenCoordinate, screenDPR, screenSize, screenUV, select, setCurrentStack, setName, shaderStages, shadow, shadowPositionWorld, shapeCircle, sharedUniformGroup, sheen, sheenRoughness, shiftLeft, shiftRight, shininess, sign, sin, sinc, sinh, skinning, smoothstep, smoothstepElement, specularColor, specularColorBlended, specularF90, spherizeUV, split, spritesheetUV, sqrt, stack, step, stepElement, storage, storageBarrier, storageElement, storageTexture, storageTexture3D, struct, sub, subBuild, subgroupAdd, subgroupAll, subgroupAnd, subgroupAny, subgroupBallot, subgroupBroadcast, subgroupBroadcastFirst, subgroupElect, subgroupExclusiveAdd, subgroupExclusiveMul, subgroupInclusiveAdd, subgroupInclusiveMul, subgroupIndex, subgroupMax, subgroupMin, subgroupMul, subgroupOr, subgroupShuffle, subgroupShuffleDown, subgroupShuffleUp, subgroupShuffleXor, subgroupSize, subgroupXor, tan, tangentGeometry, tangentLocal, tangentView, tangentViewFrame, tangentWorld, tanh, texture, texture3D, texture3DLevel, texture3DLoad, textureBarrier, textureBicubic, textureBicubicLevel, textureLevel, textureLoad, textureSize, textureStore, thickness, time, toneMapping, toneMappingExposure, toonOutlinePass, transformDirection, transformNormal, transformNormalByInverseViewMatrix, transformNormalByViewMatrix, transformNormalToView, transformedClearcoatNormalView, transformedNormalView, transformedNormalWorld, transmission, transpose, triNoise3D, triplanarTexture, triplanarTextures, trunc, uint, uintBitsToFloat, uniform, uniformArray, uniformCubeTexture, uniformFlow, uniformGroup, uniformTexture, unpackHalf2x16, unpackNormal, unpackRGBToNormal, unpackSnorm2x16, unpackSnorm4x8, unpackUnorm2x16, unpackUnorm4x8, unpremultiplyAlpha, userData, uv, uvec2, uvec3, uvec4, varying, varyingProperty, vec2, vec3, vec4, vectorComponents, velocity, vertexColor, vertexIndex, vertexStage, vibrance, viewZToLogarithmicDepth, viewZToOrthographicDepth, viewZToPerspectiveDepth, viewZToReversedOrthographicDepth, viewZToReversedPerspectiveDepth, viewport, viewportCoordinate, viewportDepthTexture, viewportLinearDepth, viewportMipTexture, viewportOpaqueMipTexture, viewportSafeUV, viewportSharedTexture, viewportSize, viewportTexture, viewportUV, vogelDiskSample, wgsl, wgslFn, workgroupArray, workgroupBarrier, workgroupId, workingToColorSpace, xor };
diff --git a/build/three.webgpu.js b/build/three.webgpu.js
index 8070602a8f7807..7223dccdb9126d 100644
--- a/build/three.webgpu.js
+++ b/build/three.webgpu.js
@@ -3,8 +3,8 @@
* Copyright 2010-2026 Three.js Authors
* SPDX-License-Identifier: MIT
*/
-import { DynamicDrawUsage, RenderObjectRefreshType, Color, Vector2, Vector3, Vector4, Matrix2, Matrix3, Matrix4, UnsignedIntType, IntType, error, RedFormat, RedIntegerFormat, DepthFormat, DepthStencilFormat, AlphaFormat, RGFormat, RGIntegerFormat, RGBFormat, RGBIntegerFormat, EventDispatcher, MathUtils, warn, WebGLCoordinateSystem, WebGPUCoordinateSystem, ColorManagement, SRGBTransfer, NoToneMapping, StaticDrawUsage, InterleavedBufferAttribute, InterleavedBuffer, NoColorSpace, log as log$1, warnOnce, Texture, Compatibility, LessCompare, LessEqualCompare, GreaterCompare, GreaterEqualCompare, NearestFilter, Sphere, BackSide, DoubleSide, CubeTexture, CubeReflectionMapping, CubeRefractionMapping, TangentSpaceNormalMap, NoNormalPacking, NormalRGPacking, NormalGAPacking, ObjectSpaceNormalMap, RED_GREEN_RGTC2_Format, RG11_EAC_Format, InstancedBufferAttribute, InstancedInterleavedBuffer, DataTexture, RGBAFormat, FloatType, DataArrayTexture, FramebufferTexture, LinearMipmapLinearFilter, DepthTexture, Material, LineBasicMaterial, LineDashedMaterial, NoBlending, MeshNormalMaterial, SRGBColorSpace, RenderTarget, BoxGeometry, Mesh, Scene, LinearFilter, CubeCamera, EquirectangularReflectionMapping, EquirectangularRefractionMapping, AddOperation, MixOperation, MultiplyOperation, MeshBasicMaterial, MeshLambertMaterial, MeshPhongMaterial, HalfFloatType, ClampToEdgeWrapping, BufferGeometry, OrthographicCamera, PerspectiveCamera, LinearSRGBColorSpace, CubeUVReflectionMapping, BufferAttribute, MeshStandardMaterial, MeshPhysicalMaterial, MeshToonMaterial, MeshMatcapMaterial, SpriteMaterial, PointsMaterial, ShadowMaterial, Uint32BufferAttribute, Uint16BufferAttribute, ByteType, UnsignedByteType, ShortType, UnsignedShortType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedInt248Type, UnsignedInt5999Type, UnsignedInt101111Type, NormalBlending, SrcAlphaFactor, OneMinusSrcAlphaFactor, AddEquation, MaterialBlending, Object3D, LinearMipMapLinearFilter, Plane, Float32BufferAttribute, UVMapping, VSMShadowMap, PCFShadowMap, BasicShadowMap, CubeDepthTexture, SphereGeometry, LinearMipmapNearestFilter, NearestMipmapLinearFilter, Float16BufferAttribute, yieldToMain, REVISION, ArrayCamera, PlaneGeometry, FrontSide, CustomBlending, ZeroFactor, CylinderGeometry, Quaternion, WebXRController, RAD2DEG, PCFSoftShadowMap, FrustumArray, Frustum, RGBAIntegerFormat, TimestampQuery, createCanvasElement, MaxEquation, MinEquation, ReverseSubtractEquation, SubtractEquation, OneMinusConstantAlphaFactor, ConstantAlphaFactor, OneMinusConstantColorFactor, ConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcColorFactor, DstAlphaFactor, DstColorFactor, SrcAlphaSaturateFactor, SrcColorFactor, OneFactor, CullFaceNone, CullFaceBack, CullFaceFront, MultiplyBlending, SubtractiveBlending, AdditiveBlending, NotEqualDepth, GreaterDepth, GreaterEqualDepth, EqualDepth, LessEqualDepth, LessDepth, AlwaysDepth, NeverDepth, ReversedDepthFuncs, RGB_S3TC_DXT1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGB_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_PVRTC_2BPPV1_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, R11_EAC_Format, SIGNED_R11_EAC_Format, SIGNED_RG11_EAC_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_BPTC_Format, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, SIGNED_RED_GREEN_RGTC2_Format, MirroredRepeatWrapping, RepeatWrapping, NearestMipmapNearestFilter, NotEqualCompare, EqualCompare, AlwaysCompare, NeverCompare, LinearTransfer, getByteLength, isTypedArray, NotEqualStencilFunc, GreaterStencilFunc, GreaterEqualStencilFunc, EqualStencilFunc, LessEqualStencilFunc, LessStencilFunc, AlwaysStencilFunc, NeverStencilFunc, DecrementWrapStencilOp, IncrementWrapStencilOp, DecrementStencilOp, IncrementStencilOp, InvertStencilOp, ReplaceStencilOp, ZeroStencilOp, KeepStencilOp, SpotLight, PointLight, DirectionalLight, RectAreaLight, AmbientLight, HemisphereLight, LightProbe, LinearToneMapping, ReinhardToneMapping, CineonToneMapping, ACESFilmicToneMapping, AgXToneMapping, NeutralToneMapping, Group, Loader, FileLoader, MaterialLoader, ObjectLoader } from './three.core.js';
-export { AdditiveAnimationBlendMode, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrowHelper, AttachedBindMode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BasicDepthPacking, BatchedMesh, BezierInterpolant, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxHelper, BufferGeometryLoader, Cache, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CircleGeometry, Clock, ColorKeyframeTrack, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ConeGeometry, Controls, CubeTextureLoader, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceFrontBack, Curve, CurvePath, CustomToneMapping, Cylindrical, Data3DTexture, DataTextureLoader, DataUtils, DefaultLoadingManager, DetachedBindMode, DirectionalLightHelper, DiscreteInterpolant, DodecahedronGeometry, DynamicCopyUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, Euler, ExternalTexture, ExtrudeGeometry, Fog, FogExp2, GLBufferAttribute, GLSL1, GLSL3, GridHelper, HTMLTexture, HemisphereLightHelper, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, InstancedBufferGeometry, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, Interpolant, InterpolateBezier, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InterpolationSamplingMode, InterpolationSamplingType, KeyframeTrack, LOD, LatheGeometry, Layers, Light, Line, Line3, LineCurve, LineCurve3, LineLoop, LineSegments, LinearInterpolant, LinearMipMapNearestFilter, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, MOUSE, MeshDepthMaterial, MeshDistanceMaterial, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NormalAnimationBlendMode, NumberKeyframeTrack, OctahedronGeometry, Path, PlaneHelper, PointLightHelper, Points, PolarGridHelper, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RGBADepthPacking, RGBDepthPacking, RGDepthPacking, RawShaderMaterial, Ray, Raycaster, RenderTarget3D, RingGeometry, ShaderMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, Skeleton, SkeletonHelper, SkinnedMesh, Source, Spherical, SphericalHarmonics3, SplineCurve, SpotLightHelper, Sprite, StaticCopyUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SunLight, TOUCH, TetrahedronGeometry, TextureLoader, TextureSource, TextureUtils, Timer, TorusGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, VectorKeyframeTrack, VideoFrameTexture, VideoTexture, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLRenderTarget, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroSlopeEnding, getConsoleFunction, setConsoleFunction } from './three.core.js';
+import { DynamicDrawUsage, RenderObjectRefreshType, Color, Vector2, Vector3, Vector4, Matrix2, Matrix3, Matrix4, error, UnsignedIntType, IntType, RedFormat, RedIntegerFormat, DepthFormat, DepthStencilFormat, AlphaFormat, RGFormat, RGIntegerFormat, RGBFormat, RGBIntegerFormat, EventDispatcher, MathUtils, warn, WebGLCoordinateSystem, WebGPUCoordinateSystem, ColorManagement, SRGBTransfer, NoToneMapping, StaticDrawUsage, InterleavedBufferAttribute, InterleavedBuffer, NoColorSpace, log as log$1, warnOnce, Texture, Compatibility, LessCompare, LessEqualCompare, GreaterCompare, GreaterEqualCompare, NearestFilter, Sphere, BackSide, DoubleSide, CubeTexture, CubeReflectionMapping, CubeRefractionMapping, TangentSpaceNormalMap, NoNormalPacking, NormalRGPacking, NormalGAPacking, ObjectSpaceNormalMap, RED_GREEN_RGTC2_Format, RG11_EAC_Format, InstancedBufferAttribute, InstancedInterleavedBuffer, DataTexture, RGBAFormat, FloatType, DataArrayTexture, FramebufferTexture, LinearMipmapLinearFilter, DepthTexture, Material, LineBasicMaterial, LineDashedMaterial, NoBlending, MeshNormalMaterial, SRGBColorSpace, RenderTarget, BoxGeometry, Mesh, Scene, LinearFilter, CubeCamera, EquirectangularReflectionMapping, EquirectangularRefractionMapping, AddOperation, MixOperation, MultiplyOperation, MeshBasicMaterial, MeshLambertMaterial, MeshPhongMaterial, HalfFloatType, ClampToEdgeWrapping, BufferGeometry, OrthographicCamera, PerspectiveCamera, LinearSRGBColorSpace, CubeUVReflectionMapping, BufferAttribute, MeshStandardMaterial, MeshPhysicalMaterial, MeshToonMaterial, MeshMatcapMaterial, SpriteMaterial, PointsMaterial, ShadowMaterial, Uint32BufferAttribute, Uint16BufferAttribute, ByteType, UnsignedByteType, ShortType, UnsignedShortType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedInt248Type, UnsignedInt5999Type, UnsignedInt101111Type, NormalBlending, SrcAlphaFactor, OneMinusSrcAlphaFactor, AddEquation, MaterialBlending, Object3D, LinearMipMapLinearFilter, Plane, Float32BufferAttribute, UVMapping, VSMShadowMap, PCFShadowMap, BasicShadowMap, CubeDepthTexture, SphereGeometry, LinearMipmapNearestFilter, NearestMipmapLinearFilter, Float16BufferAttribute, yieldToMain, REVISION, ArrayCamera, PlaneGeometry, FrontSide, CustomBlending, ZeroFactor, CylinderGeometry, Quaternion, WebXRController, RAD2DEG, PCFSoftShadowMap, FrustumArray, Frustum, RGBAIntegerFormat, TimestampQuery, createCanvasElement, MaxEquation, MinEquation, ReverseSubtractEquation, SubtractEquation, OneMinusConstantAlphaFactor, ConstantAlphaFactor, OneMinusConstantColorFactor, ConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcColorFactor, DstAlphaFactor, DstColorFactor, SrcAlphaSaturateFactor, SrcColorFactor, OneFactor, CullFaceNone, CullFaceBack, CullFaceFront, MultiplyBlending, SubtractiveBlending, AdditiveBlending, NotEqualDepth, GreaterDepth, GreaterEqualDepth, EqualDepth, LessEqualDepth, LessDepth, AlwaysDepth, NeverDepth, ReversedDepthFuncs, RGB_S3TC_DXT1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGB_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_PVRTC_2BPPV1_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, R11_EAC_Format, SIGNED_R11_EAC_Format, SIGNED_RG11_EAC_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_BPTC_Format, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, SIGNED_RED_GREEN_RGTC2_Format, MirroredRepeatWrapping, RepeatWrapping, NearestMipmapNearestFilter, NotEqualCompare, EqualCompare, AlwaysCompare, NeverCompare, LinearTransfer, getByteLength, isTypedArray, NotEqualStencilFunc, GreaterStencilFunc, GreaterEqualStencilFunc, EqualStencilFunc, LessEqualStencilFunc, LessStencilFunc, AlwaysStencilFunc, NeverStencilFunc, DecrementWrapStencilOp, IncrementWrapStencilOp, DecrementStencilOp, IncrementStencilOp, InvertStencilOp, ReplaceStencilOp, ZeroStencilOp, KeepStencilOp, SpotLight, PointLight, DirectionalLight, RectAreaLight, AmbientLight, HemisphereLight, LightProbe, LinearToneMapping, ReinhardToneMapping, CineonToneMapping, ACESFilmicToneMapping, AgXToneMapping, NeutralToneMapping, Group, Loader, FileLoader, MaterialLoader, ObjectLoader } from './three.core.js';
+export { AdditiveAnimationBlendMode, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrowHelper, AttachedBindMode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BasicDepthPacking, BatchedMesh, BezierInterpolant, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxHelper, BufferGeometryLoader, Cache, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CircleGeometry, Clock, ColorKeyframeTrack, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ConeGeometry, Controls, CubeTextureLoader, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceFrontBack, Curve, CurvePath, CustomToneMapping, Cylindrical, Data3DTexture, DataTextureLoader, DataUtils, DefaultLoadingManager, DetachedBindMode, DirectionalLightHelper, DiscreteInterpolant, DodecahedronGeometry, DynamicCopyUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, Euler, ExternalTexture, ExtrudeGeometry, Fog, FogExp2, GLBufferAttribute, GLSL1, GLSL3, GridHelper, HTMLTexture, HemisphereLightHelper, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, InstancedBufferGeometry, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, Interpolant, InterpolateBezier, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InterpolationSamplingMode, InterpolationSamplingType, KeyframeTrack, LOD, LatheGeometry, Layers, Light, LightShadow, Line, Line3, LineCurve, LineCurve3, LineLoop, LineSegments, LinearInterpolant, LinearMipMapNearestFilter, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, MOUSE, MeshDepthMaterial, MeshDistanceMaterial, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NormalAnimationBlendMode, NumberKeyframeTrack, OctahedronGeometry, Path, PlaneHelper, PointLightHelper, Points, PolarGridHelper, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RGBADepthPacking, RGBDepthPacking, RGDepthPacking, RawShaderMaterial, Ray, Raycaster, RenderTarget3D, RingGeometry, ShaderMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, Skeleton, SkeletonHelper, SkinnedMesh, Source, Spherical, SphericalHarmonics3, SplineCurve, SpotLightHelper, Sprite, StaticCopyUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, TOUCH, TetrahedronGeometry, TextureLoader, TextureSource, TextureUtils, Timer, TorusGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, VectorKeyframeTrack, VideoFrameTexture, VideoTexture, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLRenderTarget, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroSlopeEnding, getConsoleFunction, setConsoleFunction } from './three.core.js';
const refreshUniforms = [
'alphaMap',
@@ -7239,7 +7239,7 @@ const shiftRight = /*@__PURE__*/ nodeProxyIntent( OperatorNode, '>>' ).setParame
* @param {Node} a - The node to increment.
* @returns {OperatorNode}
*/
-const incrementBefore = Fn( ( [ a ] ) => {
+const incrementBefore = /*@__PURE__*/ Fn( ( [ a ] ) => {
a.addAssign( 1 );
return a;
@@ -7254,7 +7254,7 @@ const incrementBefore = Fn( ( [ a ] ) => {
* @param {Node} a - The node to decrement.
* @returns {OperatorNode}
*/
-const decrementBefore = Fn( ( [ a ] ) => {
+const decrementBefore = /*@__PURE__*/ Fn( ( [ a ] ) => {
a.subAssign( 1 );
return a;
@@ -12284,7 +12284,7 @@ class InspectorNode extends Node {
* @param {Function|null} [callback=null] - Optional callback to modify the node during setup.
* @returns {Node} The inspector node.
*/
-function inspector( node, name = '', callback = null ) {
+function inspect( node, name = '', callback = null ) {
node = nodeObject( node );
@@ -12292,7 +12292,7 @@ function inspector( node, name = '', callback = null ) {
}
-addMethodChaining( 'toInspector', inspector );
+addMethodChaining( 'toInspector', inspect );
function addNodeElement( name/*, nodeElement*/ ) {
@@ -14260,7 +14260,7 @@ class BuiltinNode extends Node {
* @param {string} name - The name of the built-in shader variable.
* @returns {BuiltinNode}
*/
-const builtin = nodeProxy( BuiltinNode ).setParameterLength( 1 );
+const builtin = /*@__PURE__*/ nodeProxy( BuiltinNode ).setParameterLength( 1 );
let _screenSizeVec, _viewportVec;
@@ -16960,7 +16960,7 @@ const normalMap = /*@__PURE__*/ nodeProxy( NormalMapNode ).setParameterLength( 1
// Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen
// https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf
-const dHdxy_fwd = Fn( ( { textureNode, bumpScale } ) => {
+const dHdxy_fwd = /*@__PURE__*/ Fn( ( { textureNode, bumpScale } ) => {
// It's used to preserve the same TextureNode instance
const sampleTexture = ( callback ) => textureNode.isolate().context( { getUV: ( texNode ) => callback( texNode.uvNode || uv$1() ), forceUVContext: true } );
@@ -16976,7 +16976,7 @@ const dHdxy_fwd = Fn( ( { textureNode, bumpScale } ) => {
// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
-const perturbNormalArb = Fn( ( inputs ) => {
+const perturbNormalArb = /*@__PURE__*/ Fn( ( inputs ) => {
const { surf_pos, surf_norm, dHdxy } = inputs;
@@ -31156,9 +31156,18 @@ class RenderObjects {
* A dictionary that manages render contexts in chain maps
* for each pass ID.
*
+ * @private
* @type {Object}
*/
- this.chainMaps = {};
+ this._chainMaps = {};
+
+ /**
+ * Stores all render objects created by this component.
+ *
+ * @private
+ * @type {Set}
+ */
+ this._renderObjects = new Set();
}
@@ -31251,7 +31260,7 @@ class RenderObjects {
*/
getChainMap( passId = 'default' ) {
- return this.chainMaps[ passId ] || ( this.chainMaps[ passId ] = new ChainMap() );
+ return this._chainMaps[ passId ] || ( this._chainMaps[ passId ] = new ChainMap() );
}
@@ -31260,7 +31269,15 @@ class RenderObjects {
*/
dispose() {
- this.chainMaps = {};
+ for ( const renderObject of this._renderObjects ) {
+
+ renderObject.dispose();
+
+ }
+
+ this._renderObjects.clear();
+
+ this._chainMaps = {};
}
@@ -31294,8 +31311,12 @@ class RenderObjects {
chainMap.delete( renderObject.getChainArray() );
+ this._renderObjects.delete( renderObject );
+
};
+ this._renderObjects.add( renderObject );
+
return renderObject;
}
@@ -37322,11 +37343,25 @@ class BitcountNode extends MathNode {
}
-}
+ static get COUNT_TRAILING_ZEROS() {
+
+ return 'countTrailingZeros';
+
+ }
+
+ static get COUNT_LEADING_ZEROS() {
+
+ return 'countLeadingZeros';
+
+ }
+
+ static get COUNT_ONE_BITS() {
+
+ return 'countOneBits';
+
+ }
-BitcountNode.COUNT_TRAILING_ZEROS = 'countTrailingZeros';
-BitcountNode.COUNT_LEADING_ZEROS = 'countLeadingZeros';
-BitcountNode.COUNT_ONE_BITS = 'countOneBits';
+}
/**
* Finds the number of consecutive 0 bits from the least significant bit of the input value,
@@ -39409,7 +39444,7 @@ const getNormalFromDepth = /*@__PURE__*/ Fn( ( [ uv, depthTexture, projectionMat
* @param {Node} position - The input position, usually screen coordinates.
* @return {Node} The noise value.
*/
-const interleavedGradientNoise = Fn( ( [ position ] ) => {
+const interleavedGradientNoise = /*@__PURE__*/ Fn( ( [ position ] ) => {
return fract( float( 52.9829189 ).mul( fract( dot( position, vec2( 0.06711056, 0.00583715 ) ) ) ) );
@@ -39435,7 +39470,7 @@ const interleavedGradientNoise = Fn( ( [ position ] ) => {
* @param {Node} phi - Rotation angle in radians (typically from IGN * 2π).
* @return {Node} A 2D point on the unit disk.
*/
-const vogelDiskSample = Fn( ( [ sampleIndex, samplesCount, phi ] ) => {
+const vogelDiskSample = /*@__PURE__*/ Fn( ( [ sampleIndex, samplesCount, phi ] ) => {
const goldenAngle = float( 2.399963229728653 ); // 2π * (2 - φ) where φ is golden ratio
const r = sqrt( float( sampleIndex ).add( 0.5 ).div( float( samplesCount ) ) );
@@ -40203,7 +40238,7 @@ class StorageTexture3DNode extends StorageTextureNode {
*/
const storageTexture3D = /*@__PURE__*/ nodeProxy( StorageTexture3DNode ).setParameterLength( 1, 3 );
-const normal = Fn( ( { texture, uv } ) => {
+const normal = /*@__PURE__*/ Fn( ( { texture, uv } ) => {
const epsilon = 0.0001;
@@ -40955,7 +40990,7 @@ const cdl = /*@__PURE__*/ Fn( ( [
* @param {Node} stepsNode - Controls the intensity of the posterization effect. A lower number results in a more blocky appearance.
* @returns {Node} The posterized color.
*/
-const posterize = Fn( ( [ source, steps ] ) => {
+const posterize = /*@__PURE__*/ Fn( ( [ source, steps ] ) => {
return source.mul( steps ).floor().div( steps );
@@ -42059,21 +42094,29 @@ class PassNode extends TempNode {
}
-}
+ /**
+ * @static
+ * @type {'color'}
+ * @default 'color'
+ */
+ static get COLOR() {
-/**
- * @static
- * @type {'color'}
- * @default 'color'
- */
-PassNode.COLOR = 'color';
+ return 'color';
-/**
- * @static
- * @type {'depth'}
- * @default 'depth'
- */
-PassNode.DEPTH = 'depth';
+ }
+
+ /**
+ * @static
+ * @type {'depth'}
+ * @default 'depth'
+ */
+ static get DEPTH() {
+
+ return 'depth';
+
+ }
+
+}
/**
* TSL function for creating a pass node.
@@ -42914,7 +42957,7 @@ function getViewZNode( builder ) {
* @param {Node} near - Defines the near value.
* @param {Node} far - Defines the far value.
*/
-const rangeFogFactor = Fn( ( [ near, far ], builder ) => {
+const rangeFogFactor = /*@__PURE__*/ Fn( ( [ near, far ], builder ) => {
const viewZ = getViewZNode( builder );
@@ -42931,7 +42974,7 @@ const rangeFogFactor = Fn( ( [ near, far ], builder ) => {
* @function
* @param {Node} density - Defines the fog density.
*/
-const densityFogFactor = Fn( ( [ density ], builder ) => {
+const densityFogFactor = /*@__PURE__*/ Fn( ( [ density ], builder ) => {
const viewZ = getViewZNode( builder );
@@ -42947,7 +42990,7 @@ const densityFogFactor = Fn( ( [ density ], builder ) => {
* @param {Node} density - Defines the fog density.
* @param {Node} height - The height threshold in world space. Everything below this y-coordinate is affected by fog.
*/
-const exponentialHeightFogFactor = Fn( ( [ density, height ], builder ) => {
+const exponentialHeightFogFactor = /*@__PURE__*/ Fn( ( [ density, height ], builder ) => {
const viewZ = getViewZNode( builder );
@@ -42967,7 +43010,7 @@ const exponentialHeightFogFactor = Fn( ( [ density, height ], builder ) => {
* @param {Node} color - Defines the color of the fog.
* @param {Node} factor - Defines how the fog is factored in the scene.
*/
-const fog = Fn( ( [ color, factor ] ) => {
+const fog = /*@__PURE__*/ Fn( ( [ color, factor ] ) => {
return vec4( factor.toFloat().mix( output.rgb, color.toVec3() ), output.a );
@@ -43450,7 +43493,7 @@ class BarrierNode extends Node {
* @param {string} scope - The scope defines the behavior of the node..
* @returns {BarrierNode}
*/
-const barrier = nodeProxy( BarrierNode );
+const barrier = /*@__PURE__*/ nodeProxy( BarrierNode );
/**
* TSL function for creating a workgroup barrier. All compute shader
@@ -43842,17 +43885,61 @@ class AtomicFunctionNode extends Node {
}
-}
+ static get ATOMIC_LOAD() {
+
+ return 'atomicLoad';
+
+ }
+
+ static get ATOMIC_STORE() {
-AtomicFunctionNode.ATOMIC_LOAD = 'atomicLoad';
-AtomicFunctionNode.ATOMIC_STORE = 'atomicStore';
-AtomicFunctionNode.ATOMIC_ADD = 'atomicAdd';
-AtomicFunctionNode.ATOMIC_SUB = 'atomicSub';
-AtomicFunctionNode.ATOMIC_MAX = 'atomicMax';
-AtomicFunctionNode.ATOMIC_MIN = 'atomicMin';
-AtomicFunctionNode.ATOMIC_AND = 'atomicAnd';
-AtomicFunctionNode.ATOMIC_OR = 'atomicOr';
-AtomicFunctionNode.ATOMIC_XOR = 'atomicXor';
+ return 'atomicStore';
+
+ }
+
+ static get ATOMIC_ADD() {
+
+ return 'atomicAdd';
+
+ }
+
+ static get ATOMIC_SUB() {
+
+ return 'atomicSub';
+
+ }
+
+ static get ATOMIC_MAX() {
+
+ return 'atomicMax';
+
+ }
+
+ static get ATOMIC_MIN() {
+
+ return 'atomicMin';
+
+ }
+
+ static get ATOMIC_AND() {
+
+ return 'atomicAnd';
+
+ }
+
+ static get ATOMIC_OR() {
+
+ return 'atomicOr';
+
+ }
+
+ static get ATOMIC_XOR() {
+
+ return 'atomicXor';
+
+ }
+
+}
/**
* TSL function for creating an atomic function node.
@@ -43864,7 +43951,7 @@ AtomicFunctionNode.ATOMIC_XOR = 'atomicXor';
* @param {Node} valueNode - The value that mutates the atomic variable.
* @returns {AtomicFunctionNode}
*/
-const atomicNode = nodeProxy( AtomicFunctionNode );
+const atomicNode = /*@__PURE__*/ nodeProxy( AtomicFunctionNode );
/**
* TSL function for appending an atomic function call into the programmatic flow of a compute shader.
@@ -44140,40 +44227,160 @@ class SubgroupFunctionNode extends TempNode {
}
-}
+ // 0 inputs
+ static get SUBGROUP_ELECT() {
-// 0 inputs
-SubgroupFunctionNode.SUBGROUP_ELECT = 'subgroupElect';
+ return 'subgroupElect';
-// 1 input
-SubgroupFunctionNode.SUBGROUP_BALLOT = 'subgroupBallot';
-SubgroupFunctionNode.SUBGROUP_ADD = 'subgroupAdd';
-SubgroupFunctionNode.SUBGROUP_INCLUSIVE_ADD = 'subgroupInclusiveAdd';
-SubgroupFunctionNode.SUBGROUP_EXCLUSIVE_AND = 'subgroupExclusiveAdd';
-SubgroupFunctionNode.SUBGROUP_MUL = 'subgroupMul';
-SubgroupFunctionNode.SUBGROUP_INCLUSIVE_MUL = 'subgroupInclusiveMul';
-SubgroupFunctionNode.SUBGROUP_EXCLUSIVE_MUL = 'subgroupExclusiveMul';
-SubgroupFunctionNode.SUBGROUP_AND = 'subgroupAnd';
-SubgroupFunctionNode.SUBGROUP_OR = 'subgroupOr';
-SubgroupFunctionNode.SUBGROUP_XOR = 'subgroupXor';
-SubgroupFunctionNode.SUBGROUP_MIN = 'subgroupMin';
-SubgroupFunctionNode.SUBGROUP_MAX = 'subgroupMax';
-SubgroupFunctionNode.SUBGROUP_ALL = 'subgroupAll';
-SubgroupFunctionNode.SUBGROUP_ANY = 'subgroupAny';
-SubgroupFunctionNode.SUBGROUP_BROADCAST_FIRST = 'subgroupBroadcastFirst';
-SubgroupFunctionNode.QUAD_SWAP_X = 'quadSwapX';
-SubgroupFunctionNode.QUAD_SWAP_Y = 'quadSwapY';
-SubgroupFunctionNode.QUAD_SWAP_DIAGONAL = 'quadSwapDiagonal';
+ }
-// 2 inputs
-SubgroupFunctionNode.SUBGROUP_BROADCAST = 'subgroupBroadcast';
-SubgroupFunctionNode.SUBGROUP_SHUFFLE = 'subgroupShuffle';
-SubgroupFunctionNode.SUBGROUP_SHUFFLE_XOR = 'subgroupShuffleXor';
-SubgroupFunctionNode.SUBGROUP_SHUFFLE_UP = 'subgroupShuffleUp';
-SubgroupFunctionNode.SUBGROUP_SHUFFLE_DOWN = 'subgroupShuffleDown';
-SubgroupFunctionNode.QUAD_BROADCAST = 'quadBroadcast';
+ // 1 input
+ static get SUBGROUP_BALLOT() {
+
+ return 'subgroupBallot';
+
+ }
+
+ static get SUBGROUP_ADD() {
+
+ return 'subgroupAdd';
+
+ }
+
+ static get SUBGROUP_INCLUSIVE_ADD() {
+
+ return 'subgroupInclusiveAdd';
+
+ }
+
+ static get SUBGROUP_EXCLUSIVE_AND() {
+
+ return 'subgroupExclusiveAdd';
+ }
+
+ static get SUBGROUP_MUL() {
+
+ return 'subgroupMul';
+
+ }
+
+ static get SUBGROUP_INCLUSIVE_MUL() {
+
+ return 'subgroupInclusiveMul';
+
+ }
+
+ static get SUBGROUP_EXCLUSIVE_MUL() {
+
+ return 'subgroupExclusiveMul';
+
+ }
+
+ static get SUBGROUP_AND() {
+
+ return 'subgroupAnd';
+
+ }
+
+ static get SUBGROUP_OR() {
+
+ return 'subgroupOr';
+
+ }
+
+ static get SUBGROUP_XOR() {
+
+ return 'subgroupXor';
+
+ }
+
+ static get SUBGROUP_MIN() {
+
+ return 'subgroupMin';
+
+ }
+
+ static get SUBGROUP_MAX() {
+
+ return 'subgroupMax';
+
+ }
+
+ static get SUBGROUP_ALL() {
+
+ return 'subgroupAll';
+
+ }
+
+ static get SUBGROUP_ANY() {
+
+ return 'subgroupAny';
+
+ }
+
+ static get SUBGROUP_BROADCAST_FIRST() {
+
+ return 'subgroupBroadcastFirst';
+
+ }
+
+ static get QUAD_SWAP_X() {
+
+ return 'quadSwapX';
+
+ }
+
+ static get QUAD_SWAP_Y() {
+ return 'quadSwapY';
+
+ }
+
+ static get QUAD_SWAP_DIAGONAL() {
+
+ return 'quadSwapDiagonal';
+
+ }
+
+ // 2 inputs
+ static get SUBGROUP_BROADCAST() {
+
+ return 'subgroupBroadcast';
+
+ }
+
+ static get SUBGROUP_SHUFFLE() {
+
+ return 'subgroupShuffle';
+
+ }
+
+ static get SUBGROUP_SHUFFLE_XOR() {
+
+ return 'subgroupShuffleXor';
+
+ }
+
+ static get SUBGROUP_SHUFFLE_UP() {
+
+ return 'subgroupShuffleUp';
+
+ }
+
+ static get SUBGROUP_SHUFFLE_DOWN() {
+
+ return 'subgroupShuffleDown';
+
+ }
+
+ static get QUAD_BROADCAST() {
+
+ return 'quadBroadcast';
+
+ }
+
+}
/**
* Returns true if this invocation has the lowest subgroup_invocation_id
@@ -47193,7 +47400,7 @@ const checker = /*@__PURE__*/ Fn( ( [ coord = uv$1() ] ) => {
* @param {Node} coord - The uv to generate the circle.
* @return {Node} The circle shape.
*/
-const shapeCircle = Fn( ( [ coord = uv$1() ], { renderer, material } ) => {
+const shapeCircle = /*@__PURE__*/ Fn( ( [ coord = uv$1() ], { renderer, material } ) => {
const len2 = lengthSq( coord.mul( 2 ).sub( 1 ) );
@@ -49329,6 +49536,7 @@ var TSL = /*#__PURE__*/Object.freeze({
__proto__: null,
BRDF_GGX: BRDF_GGX,
BRDF_Lambert: BRDF_Lambert,
+ BRDF_Sheen: BRDF_Sheen,
BasicPointShadowFilter: BasicPointShadowFilter,
BasicShadowFilter: BasicShadowFilter,
Break: Break,
@@ -49336,8 +49544,10 @@ var TSL = /*#__PURE__*/Object.freeze({
Continue: Continue,
DFGLUT: DFGLUT,
D_GGX: D_GGX,
+ D_GGX_Anisotropic: D_GGX_Anisotropic,
Discard: Discard,
EPSILON: EPSILON,
+ EnvironmentBRDF: EnvironmentBRDF,
F_Schlick: F_Schlick,
Fn: Fn,
HALF_PI: HALF_PI,
@@ -49370,6 +49580,7 @@ var TSL = /*#__PURE__*/Object.freeze({
TWO_PI: TWO_PI,
VSMShadowFilter: VSMShadowFilter,
V_GGX_SmithCorrelated: V_GGX_SmithCorrelated,
+ V_GGX_SmithCorrelated_Anisotropic: V_GGX_SmithCorrelated_Anisotropic,
Var: Var,
VarIntent: VarIntent,
abs: abs,
@@ -49423,6 +49634,7 @@ var TSL = /*#__PURE__*/Object.freeze({
bitangentGeometry: bitangentGeometry,
bitangentLocal: bitangentLocal,
bitangentView: bitangentView,
+ bitangentViewFrame: bitangentViewFrame,
bitangentWorld: bitangentWorld,
bitcast: bitcast,
blendBurn: blendBurn,
@@ -49463,6 +49675,8 @@ var TSL = /*#__PURE__*/Object.freeze({
clearcoatNormalView: clearcoatNormalView,
clearcoatRoughness: clearcoatRoughness,
clipSpace: clipSpace,
+ clipping: clipping,
+ clippingAlpha: clippingAlpha,
code: code,
color: color,
colorSpaceToWorking: colorSpaceToWorking,
@@ -49551,13 +49765,14 @@ var TSL = /*#__PURE__*/Object.freeze({
grayscale: grayscale,
greaterThan: greaterThan,
greaterThanEqual: greaterThanEqual,
+ hardwareClipping: hardwareClipping,
hash: hash,
highpModelNormalViewMatrix: highpModelNormalViewMatrix,
highpModelViewMatrix: highpModelViewMatrix,
hue: hue,
increment: increment,
incrementBefore: incrementBefore,
- inspector: inspector,
+ inspect: inspect,
instance: instance,
instanceColor: instanceColor,
instanceIndex: instanceIndex,
@@ -49867,6 +50082,7 @@ var TSL = /*#__PURE__*/Object.freeze({
stepElement: stepElement,
storage: storage,
storageBarrier: storageBarrier,
+ storageElement: storageElement,
storageTexture: storageTexture,
storageTexture3D: storageTexture3D,
struct: struct,
@@ -49899,6 +50115,7 @@ var TSL = /*#__PURE__*/Object.freeze({
tangentGeometry: tangentGeometry,
tangentLocal: tangentLocal,
tangentView: tangentView,
+ tangentViewFrame: tangentViewFrame,
tangentWorld: tangentWorld,
tanh: tanh,
texture: texture,
@@ -57382,6 +57599,8 @@ class NodeManager extends DataMap {
const _plane = /*@__PURE__*/ new Plane();
+let _clippingContextId = 0;
+
/**
* Represents the state that is used to perform clipping via clipping planes.
* There is a default clipping context for each render context. When the
@@ -57399,6 +57618,14 @@ class ClippingContext {
*/
constructor( parentContext = null ) {
+ /**
+ * The id of the clipping context.
+ *
+ * @type {number}
+ * @readonly
+ */
+ this.id = _clippingContextId ++;
+
/**
* The clipping context's version.
*
@@ -57599,7 +57826,7 @@ class ClippingContext {
if ( update ) {
this.version ++;
- this.cacheKey = `${ this.intersectionPlanes.length }:${ this.unionPlanes.length }`;
+ this.cacheKey = `${ this.id }:${ this.intersectionPlanes.length }:${ this.unionPlanes.length }`;
}
@@ -63111,7 +63338,6 @@ class Renderer {
if ( this._initialized === true ) {
this.info.dispose();
- this.backend.dispose();
this._animation.dispose();
this._objects.dispose();
@@ -63135,6 +63361,8 @@ class Renderer {
} );
+ this.backend.dispose();
+
}
this.setRenderTarget( null );
@@ -69673,28 +69901,27 @@ class WebGLState {
? this.enable( gl.SAMPLE_ALPHA_TO_COVERAGE )
: this.disable( gl.SAMPLE_ALPHA_TO_COVERAGE );
- if ( hardwareClippingPlanes > 0 ) {
-
- if ( this.currentClippingPlanes !== hardwareClippingPlanes ) {
- const CLIP_DISTANCE0_WEBGL = 0x3000;
+ if ( this.currentClippingPlanes !== hardwareClippingPlanes ) {
- for ( let i = 0; i < 8; i ++ ) {
+ const CLIP_DISTANCE0_WEBGL = 0x3000;
- if ( i < hardwareClippingPlanes ) {
+ for ( let i = 0; i < 8; i ++ ) {
- this.enable( CLIP_DISTANCE0_WEBGL + i );
+ if ( i < hardwareClippingPlanes ) {
- } else {
+ this.enable( CLIP_DISTANCE0_WEBGL + i );
- this.disable( CLIP_DISTANCE0_WEBGL + i );
+ } else {
- }
+ this.disable( CLIP_DISTANCE0_WEBGL + i );
}
}
+ this.currentClippingPlanes = hardwareClippingPlanes;
+
}
}
@@ -71812,6 +72039,7 @@ class WebGLTextureUtils {
backend.state.bindFramebuffer( gl.READ_FRAMEBUFFER, null );
+ gl.deleteBuffer( buffer );
gl.deleteFramebuffer( fb );
return dstBuffer;
@@ -73554,6 +73782,7 @@ class WebGLBackend extends Backend {
const clearStencil = renderer.getClearStencil();
if ( depth ) this.state.setDepthMask( true );
+ if ( stencil ) this.state.setStencilMask( 0xffffffff );
if ( descriptor.textures === null ) {
@@ -73996,9 +74225,9 @@ class WebGLBackend extends Backend {
}
- const pixelRatio = this.renderer.getPixelRatio();
-
const renderTarget = this._currentContext.renderTarget;
+
+ const pixelRatio = renderTarget !== null ? 1 : this.renderer.getPixelRatio();
const isRenderCameraDepthArray = this._isRenderCameraDepthArray( this._currentContext );
const prevActiveCubeFace = this._currentContext.activeCubeFace;
@@ -87939,7 +88168,7 @@ class WebGPUBackend extends Backend {
}
- const pixelRatio = this.renderer.getPixelRatio();
+ const pixelRatio = context.renderTarget !== null ? 1 : this.renderer.getPixelRatio();
const indexPos = cameraIndex ? bindings.indexOf( cameraIndex ) : -1;
for ( let i = 0, len = cameras.length; i < len; i ++ ) {
diff --git a/build/three.webgpu.nodes.js b/build/three.webgpu.nodes.js
index bf792dc6b1c86e..4ec0dc6477924d 100644
--- a/build/three.webgpu.nodes.js
+++ b/build/three.webgpu.nodes.js
@@ -3,8 +3,8 @@
* Copyright 2010-2026 Three.js Authors
* SPDX-License-Identifier: MIT
*/
-import { DynamicDrawUsage, RenderObjectRefreshType, Color, Vector2, Vector3, Vector4, Matrix2, Matrix3, Matrix4, UnsignedIntType, IntType, error, RedFormat, RedIntegerFormat, DepthFormat, DepthStencilFormat, AlphaFormat, RGFormat, RGIntegerFormat, RGBFormat, RGBIntegerFormat, EventDispatcher, MathUtils, warn, WebGLCoordinateSystem, WebGPUCoordinateSystem, ColorManagement, SRGBTransfer, NoToneMapping, StaticDrawUsage, InterleavedBufferAttribute, InterleavedBuffer, NoColorSpace, log as log$1, warnOnce, Texture, Compatibility, LessCompare, LessEqualCompare, GreaterCompare, GreaterEqualCompare, NearestFilter, Sphere, BackSide, DoubleSide, CubeTexture, CubeReflectionMapping, CubeRefractionMapping, TangentSpaceNormalMap, NoNormalPacking, NormalRGPacking, NormalGAPacking, ObjectSpaceNormalMap, RED_GREEN_RGTC2_Format, RG11_EAC_Format, InstancedBufferAttribute, InstancedInterleavedBuffer, DataTexture, RGBAFormat, FloatType, DataArrayTexture, FramebufferTexture, LinearMipmapLinearFilter, DepthTexture, Material, LineBasicMaterial, LineDashedMaterial, NoBlending, MeshNormalMaterial, SRGBColorSpace, RenderTarget, BoxGeometry, Mesh, Scene, LinearFilter, CubeCamera, EquirectangularReflectionMapping, EquirectangularRefractionMapping, AddOperation, MixOperation, MultiplyOperation, MeshBasicMaterial, MeshLambertMaterial, MeshPhongMaterial, HalfFloatType, ClampToEdgeWrapping, BufferGeometry, OrthographicCamera, PerspectiveCamera, LinearSRGBColorSpace, CubeUVReflectionMapping, BufferAttribute, MeshStandardMaterial, MeshPhysicalMaterial, MeshToonMaterial, MeshMatcapMaterial, SpriteMaterial, PointsMaterial, ShadowMaterial, Uint32BufferAttribute, Uint16BufferAttribute, ByteType, UnsignedByteType, ShortType, UnsignedShortType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedInt248Type, UnsignedInt5999Type, UnsignedInt101111Type, NormalBlending, SrcAlphaFactor, OneMinusSrcAlphaFactor, AddEquation, MaterialBlending, Object3D, LinearMipMapLinearFilter, Plane, Float32BufferAttribute, UVMapping, VSMShadowMap, PCFShadowMap, BasicShadowMap, CubeDepthTexture, SphereGeometry, LinearMipmapNearestFilter, NearestMipmapLinearFilter, Float16BufferAttribute, yieldToMain, REVISION, ArrayCamera, PlaneGeometry, FrontSide, CustomBlending, ZeroFactor, CylinderGeometry, Quaternion, WebXRController, RAD2DEG, PCFSoftShadowMap, FrustumArray, Frustum, RGBAIntegerFormat, TimestampQuery, createCanvasElement, MaxEquation, MinEquation, ReverseSubtractEquation, SubtractEquation, OneMinusConstantAlphaFactor, ConstantAlphaFactor, OneMinusConstantColorFactor, ConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcColorFactor, DstAlphaFactor, DstColorFactor, SrcAlphaSaturateFactor, SrcColorFactor, OneFactor, CullFaceNone, CullFaceBack, CullFaceFront, MultiplyBlending, SubtractiveBlending, AdditiveBlending, NotEqualDepth, GreaterDepth, GreaterEqualDepth, EqualDepth, LessEqualDepth, LessDepth, AlwaysDepth, NeverDepth, ReversedDepthFuncs, RGB_S3TC_DXT1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGB_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_PVRTC_2BPPV1_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, R11_EAC_Format, SIGNED_R11_EAC_Format, SIGNED_RG11_EAC_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_BPTC_Format, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, SIGNED_RED_GREEN_RGTC2_Format, MirroredRepeatWrapping, RepeatWrapping, NearestMipmapNearestFilter, NotEqualCompare, EqualCompare, AlwaysCompare, NeverCompare, LinearTransfer, getByteLength, isTypedArray, NotEqualStencilFunc, GreaterStencilFunc, GreaterEqualStencilFunc, EqualStencilFunc, LessEqualStencilFunc, LessStencilFunc, AlwaysStencilFunc, NeverStencilFunc, DecrementWrapStencilOp, IncrementWrapStencilOp, DecrementStencilOp, IncrementStencilOp, InvertStencilOp, ReplaceStencilOp, ZeroStencilOp, KeepStencilOp, SpotLight, PointLight, DirectionalLight, RectAreaLight, AmbientLight, HemisphereLight, LightProbe, LinearToneMapping, ReinhardToneMapping, CineonToneMapping, ACESFilmicToneMapping, AgXToneMapping, NeutralToneMapping, Group, Loader, FileLoader, MaterialLoader, ObjectLoader } from './three.core.js';
-export { AdditiveAnimationBlendMode, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrowHelper, AttachedBindMode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BasicDepthPacking, BatchedMesh, BezierInterpolant, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxHelper, BufferGeometryLoader, Cache, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CircleGeometry, Clock, ColorKeyframeTrack, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ConeGeometry, Controls, CubeTextureLoader, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceFrontBack, Curve, CurvePath, CustomToneMapping, Cylindrical, Data3DTexture, DataTextureLoader, DataUtils, DefaultLoadingManager, DetachedBindMode, DirectionalLightHelper, DiscreteInterpolant, DodecahedronGeometry, DynamicCopyUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, Euler, ExternalTexture, ExtrudeGeometry, Fog, FogExp2, GLBufferAttribute, GLSL1, GLSL3, GridHelper, HTMLTexture, HemisphereLightHelper, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, InstancedBufferGeometry, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, Interpolant, InterpolateBezier, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InterpolationSamplingMode, InterpolationSamplingType, KeyframeTrack, LOD, LatheGeometry, Layers, Light, Line, Line3, LineCurve, LineCurve3, LineLoop, LineSegments, LinearInterpolant, LinearMipMapNearestFilter, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, MOUSE, MeshDepthMaterial, MeshDistanceMaterial, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NormalAnimationBlendMode, NumberKeyframeTrack, OctahedronGeometry, Path, PlaneHelper, PointLightHelper, Points, PolarGridHelper, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RGBADepthPacking, RGBDepthPacking, RGDepthPacking, RawShaderMaterial, Ray, Raycaster, RenderTarget3D, RingGeometry, ShaderMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, Skeleton, SkeletonHelper, SkinnedMesh, Source, Spherical, SphericalHarmonics3, SplineCurve, SpotLightHelper, Sprite, StaticCopyUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SunLight, TOUCH, TetrahedronGeometry, TextureLoader, TextureSource, TextureUtils, Timer, TorusGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, VectorKeyframeTrack, VideoFrameTexture, VideoTexture, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLRenderTarget, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroSlopeEnding, getConsoleFunction, setConsoleFunction } from './three.core.js';
+import { DynamicDrawUsage, RenderObjectRefreshType, Color, Vector2, Vector3, Vector4, Matrix2, Matrix3, Matrix4, error, UnsignedIntType, IntType, RedFormat, RedIntegerFormat, DepthFormat, DepthStencilFormat, AlphaFormat, RGFormat, RGIntegerFormat, RGBFormat, RGBIntegerFormat, EventDispatcher, MathUtils, warn, WebGLCoordinateSystem, WebGPUCoordinateSystem, ColorManagement, SRGBTransfer, NoToneMapping, StaticDrawUsage, InterleavedBufferAttribute, InterleavedBuffer, NoColorSpace, log as log$1, warnOnce, Texture, Compatibility, LessCompare, LessEqualCompare, GreaterCompare, GreaterEqualCompare, NearestFilter, Sphere, BackSide, DoubleSide, CubeTexture, CubeReflectionMapping, CubeRefractionMapping, TangentSpaceNormalMap, NoNormalPacking, NormalRGPacking, NormalGAPacking, ObjectSpaceNormalMap, RED_GREEN_RGTC2_Format, RG11_EAC_Format, InstancedBufferAttribute, InstancedInterleavedBuffer, DataTexture, RGBAFormat, FloatType, DataArrayTexture, FramebufferTexture, LinearMipmapLinearFilter, DepthTexture, Material, LineBasicMaterial, LineDashedMaterial, NoBlending, MeshNormalMaterial, SRGBColorSpace, RenderTarget, BoxGeometry, Mesh, Scene, LinearFilter, CubeCamera, EquirectangularReflectionMapping, EquirectangularRefractionMapping, AddOperation, MixOperation, MultiplyOperation, MeshBasicMaterial, MeshLambertMaterial, MeshPhongMaterial, HalfFloatType, ClampToEdgeWrapping, BufferGeometry, OrthographicCamera, PerspectiveCamera, LinearSRGBColorSpace, CubeUVReflectionMapping, BufferAttribute, MeshStandardMaterial, MeshPhysicalMaterial, MeshToonMaterial, MeshMatcapMaterial, SpriteMaterial, PointsMaterial, ShadowMaterial, Uint32BufferAttribute, Uint16BufferAttribute, ByteType, UnsignedByteType, ShortType, UnsignedShortType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedInt248Type, UnsignedInt5999Type, UnsignedInt101111Type, NormalBlending, SrcAlphaFactor, OneMinusSrcAlphaFactor, AddEquation, MaterialBlending, Object3D, LinearMipMapLinearFilter, Plane, Float32BufferAttribute, UVMapping, VSMShadowMap, PCFShadowMap, BasicShadowMap, CubeDepthTexture, SphereGeometry, LinearMipmapNearestFilter, NearestMipmapLinearFilter, Float16BufferAttribute, yieldToMain, REVISION, ArrayCamera, PlaneGeometry, FrontSide, CustomBlending, ZeroFactor, CylinderGeometry, Quaternion, WebXRController, RAD2DEG, PCFSoftShadowMap, FrustumArray, Frustum, RGBAIntegerFormat, TimestampQuery, createCanvasElement, MaxEquation, MinEquation, ReverseSubtractEquation, SubtractEquation, OneMinusConstantAlphaFactor, ConstantAlphaFactor, OneMinusConstantColorFactor, ConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcColorFactor, DstAlphaFactor, DstColorFactor, SrcAlphaSaturateFactor, SrcColorFactor, OneFactor, CullFaceNone, CullFaceBack, CullFaceFront, MultiplyBlending, SubtractiveBlending, AdditiveBlending, NotEqualDepth, GreaterDepth, GreaterEqualDepth, EqualDepth, LessEqualDepth, LessDepth, AlwaysDepth, NeverDepth, ReversedDepthFuncs, RGB_S3TC_DXT1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGB_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_PVRTC_2BPPV1_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, R11_EAC_Format, SIGNED_R11_EAC_Format, SIGNED_RG11_EAC_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_BPTC_Format, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, SIGNED_RED_GREEN_RGTC2_Format, MirroredRepeatWrapping, RepeatWrapping, NearestMipmapNearestFilter, NotEqualCompare, EqualCompare, AlwaysCompare, NeverCompare, LinearTransfer, getByteLength, isTypedArray, NotEqualStencilFunc, GreaterStencilFunc, GreaterEqualStencilFunc, EqualStencilFunc, LessEqualStencilFunc, LessStencilFunc, AlwaysStencilFunc, NeverStencilFunc, DecrementWrapStencilOp, IncrementWrapStencilOp, DecrementStencilOp, IncrementStencilOp, InvertStencilOp, ReplaceStencilOp, ZeroStencilOp, KeepStencilOp, SpotLight, PointLight, DirectionalLight, RectAreaLight, AmbientLight, HemisphereLight, LightProbe, LinearToneMapping, ReinhardToneMapping, CineonToneMapping, ACESFilmicToneMapping, AgXToneMapping, NeutralToneMapping, Group, Loader, FileLoader, MaterialLoader, ObjectLoader } from './three.core.js';
+export { AdditiveAnimationBlendMode, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrowHelper, AttachedBindMode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BasicDepthPacking, BatchedMesh, BezierInterpolant, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxHelper, BufferGeometryLoader, Cache, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CircleGeometry, Clock, ColorKeyframeTrack, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ConeGeometry, Controls, CubeTextureLoader, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceFrontBack, Curve, CurvePath, CustomToneMapping, Cylindrical, Data3DTexture, DataTextureLoader, DataUtils, DefaultLoadingManager, DetachedBindMode, DirectionalLightHelper, DiscreteInterpolant, DodecahedronGeometry, DynamicCopyUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, Euler, ExternalTexture, ExtrudeGeometry, Fog, FogExp2, GLBufferAttribute, GLSL1, GLSL3, GridHelper, HTMLTexture, HemisphereLightHelper, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, InstancedBufferGeometry, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, Interpolant, InterpolateBezier, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InterpolationSamplingMode, InterpolationSamplingType, KeyframeTrack, LOD, LatheGeometry, Layers, Light, LightShadow, Line, Line3, LineCurve, LineCurve3, LineLoop, LineSegments, LinearInterpolant, LinearMipMapNearestFilter, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, MOUSE, MeshDepthMaterial, MeshDistanceMaterial, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NormalAnimationBlendMode, NumberKeyframeTrack, OctahedronGeometry, Path, PlaneHelper, PointLightHelper, Points, PolarGridHelper, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RGBADepthPacking, RGBDepthPacking, RGDepthPacking, RawShaderMaterial, Ray, Raycaster, RenderTarget3D, RingGeometry, ShaderMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, Skeleton, SkeletonHelper, SkinnedMesh, Source, Spherical, SphericalHarmonics3, SplineCurve, SpotLightHelper, Sprite, StaticCopyUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, TOUCH, TetrahedronGeometry, TextureLoader, TextureSource, TextureUtils, Timer, TorusGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, VectorKeyframeTrack, VideoFrameTexture, VideoTexture, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLRenderTarget, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroSlopeEnding, getConsoleFunction, setConsoleFunction } from './three.core.js';
const refreshUniforms = [
'alphaMap',
@@ -7239,7 +7239,7 @@ const shiftRight = /*@__PURE__*/ nodeProxyIntent( OperatorNode, '>>' ).setParame
* @param {Node} a - The node to increment.
* @returns {OperatorNode}
*/
-const incrementBefore = Fn( ( [ a ] ) => {
+const incrementBefore = /*@__PURE__*/ Fn( ( [ a ] ) => {
a.addAssign( 1 );
return a;
@@ -7254,7 +7254,7 @@ const incrementBefore = Fn( ( [ a ] ) => {
* @param {Node} a - The node to decrement.
* @returns {OperatorNode}
*/
-const decrementBefore = Fn( ( [ a ] ) => {
+const decrementBefore = /*@__PURE__*/ Fn( ( [ a ] ) => {
a.subAssign( 1 );
return a;
@@ -12284,7 +12284,7 @@ class InspectorNode extends Node {
* @param {Function|null} [callback=null] - Optional callback to modify the node during setup.
* @returns {Node} The inspector node.
*/
-function inspector( node, name = '', callback = null ) {
+function inspect( node, name = '', callback = null ) {
node = nodeObject( node );
@@ -12292,7 +12292,7 @@ function inspector( node, name = '', callback = null ) {
}
-addMethodChaining( 'toInspector', inspector );
+addMethodChaining( 'toInspector', inspect );
function addNodeElement( name/*, nodeElement*/ ) {
@@ -14260,7 +14260,7 @@ class BuiltinNode extends Node {
* @param {string} name - The name of the built-in shader variable.
* @returns {BuiltinNode}
*/
-const builtin = nodeProxy( BuiltinNode ).setParameterLength( 1 );
+const builtin = /*@__PURE__*/ nodeProxy( BuiltinNode ).setParameterLength( 1 );
let _screenSizeVec, _viewportVec;
@@ -16960,7 +16960,7 @@ const normalMap = /*@__PURE__*/ nodeProxy( NormalMapNode ).setParameterLength( 1
// Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen
// https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf
-const dHdxy_fwd = Fn( ( { textureNode, bumpScale } ) => {
+const dHdxy_fwd = /*@__PURE__*/ Fn( ( { textureNode, bumpScale } ) => {
// It's used to preserve the same TextureNode instance
const sampleTexture = ( callback ) => textureNode.isolate().context( { getUV: ( texNode ) => callback( texNode.uvNode || uv$1() ), forceUVContext: true } );
@@ -16976,7 +16976,7 @@ const dHdxy_fwd = Fn( ( { textureNode, bumpScale } ) => {
// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
-const perturbNormalArb = Fn( ( inputs ) => {
+const perturbNormalArb = /*@__PURE__*/ Fn( ( inputs ) => {
const { surf_pos, surf_norm, dHdxy } = inputs;
@@ -31156,9 +31156,18 @@ class RenderObjects {
* A dictionary that manages render contexts in chain maps
* for each pass ID.
*
+ * @private
* @type {Object}
*/
- this.chainMaps = {};
+ this._chainMaps = {};
+
+ /**
+ * Stores all render objects created by this component.
+ *
+ * @private
+ * @type {Set}
+ */
+ this._renderObjects = new Set();
}
@@ -31251,7 +31260,7 @@ class RenderObjects {
*/
getChainMap( passId = 'default' ) {
- return this.chainMaps[ passId ] || ( this.chainMaps[ passId ] = new ChainMap() );
+ return this._chainMaps[ passId ] || ( this._chainMaps[ passId ] = new ChainMap() );
}
@@ -31260,7 +31269,15 @@ class RenderObjects {
*/
dispose() {
- this.chainMaps = {};
+ for ( const renderObject of this._renderObjects ) {
+
+ renderObject.dispose();
+
+ }
+
+ this._renderObjects.clear();
+
+ this._chainMaps = {};
}
@@ -31294,8 +31311,12 @@ class RenderObjects {
chainMap.delete( renderObject.getChainArray() );
+ this._renderObjects.delete( renderObject );
+
};
+ this._renderObjects.add( renderObject );
+
return renderObject;
}
@@ -37322,11 +37343,25 @@ class BitcountNode extends MathNode {
}
-}
+ static get COUNT_TRAILING_ZEROS() {
+
+ return 'countTrailingZeros';
+
+ }
+
+ static get COUNT_LEADING_ZEROS() {
+
+ return 'countLeadingZeros';
+
+ }
+
+ static get COUNT_ONE_BITS() {
+
+ return 'countOneBits';
+
+ }
-BitcountNode.COUNT_TRAILING_ZEROS = 'countTrailingZeros';
-BitcountNode.COUNT_LEADING_ZEROS = 'countLeadingZeros';
-BitcountNode.COUNT_ONE_BITS = 'countOneBits';
+}
/**
* Finds the number of consecutive 0 bits from the least significant bit of the input value,
@@ -39409,7 +39444,7 @@ const getNormalFromDepth = /*@__PURE__*/ Fn( ( [ uv, depthTexture, projectionMat
* @param {Node} position - The input position, usually screen coordinates.
* @return {Node} The noise value.
*/
-const interleavedGradientNoise = Fn( ( [ position ] ) => {
+const interleavedGradientNoise = /*@__PURE__*/ Fn( ( [ position ] ) => {
return fract( float( 52.9829189 ).mul( fract( dot( position, vec2( 0.06711056, 0.00583715 ) ) ) ) );
@@ -39435,7 +39470,7 @@ const interleavedGradientNoise = Fn( ( [ position ] ) => {
* @param {Node} phi - Rotation angle in radians (typically from IGN * 2π).
* @return {Node} A 2D point on the unit disk.
*/
-const vogelDiskSample = Fn( ( [ sampleIndex, samplesCount, phi ] ) => {
+const vogelDiskSample = /*@__PURE__*/ Fn( ( [ sampleIndex, samplesCount, phi ] ) => {
const goldenAngle = float( 2.399963229728653 ); // 2π * (2 - φ) where φ is golden ratio
const r = sqrt( float( sampleIndex ).add( 0.5 ).div( float( samplesCount ) ) );
@@ -40203,7 +40238,7 @@ class StorageTexture3DNode extends StorageTextureNode {
*/
const storageTexture3D = /*@__PURE__*/ nodeProxy( StorageTexture3DNode ).setParameterLength( 1, 3 );
-const normal = Fn( ( { texture, uv } ) => {
+const normal = /*@__PURE__*/ Fn( ( { texture, uv } ) => {
const epsilon = 0.0001;
@@ -40955,7 +40990,7 @@ const cdl = /*@__PURE__*/ Fn( ( [
* @param {Node} stepsNode - Controls the intensity of the posterization effect. A lower number results in a more blocky appearance.
* @returns {Node} The posterized color.
*/
-const posterize = Fn( ( [ source, steps ] ) => {
+const posterize = /*@__PURE__*/ Fn( ( [ source, steps ] ) => {
return source.mul( steps ).floor().div( steps );
@@ -42059,21 +42094,29 @@ class PassNode extends TempNode {
}
-}
+ /**
+ * @static
+ * @type {'color'}
+ * @default 'color'
+ */
+ static get COLOR() {
-/**
- * @static
- * @type {'color'}
- * @default 'color'
- */
-PassNode.COLOR = 'color';
+ return 'color';
-/**
- * @static
- * @type {'depth'}
- * @default 'depth'
- */
-PassNode.DEPTH = 'depth';
+ }
+
+ /**
+ * @static
+ * @type {'depth'}
+ * @default 'depth'
+ */
+ static get DEPTH() {
+
+ return 'depth';
+
+ }
+
+}
/**
* TSL function for creating a pass node.
@@ -42914,7 +42957,7 @@ function getViewZNode( builder ) {
* @param {Node} near - Defines the near value.
* @param {Node} far - Defines the far value.
*/
-const rangeFogFactor = Fn( ( [ near, far ], builder ) => {
+const rangeFogFactor = /*@__PURE__*/ Fn( ( [ near, far ], builder ) => {
const viewZ = getViewZNode( builder );
@@ -42931,7 +42974,7 @@ const rangeFogFactor = Fn( ( [ near, far ], builder ) => {
* @function
* @param {Node} density - Defines the fog density.
*/
-const densityFogFactor = Fn( ( [ density ], builder ) => {
+const densityFogFactor = /*@__PURE__*/ Fn( ( [ density ], builder ) => {
const viewZ = getViewZNode( builder );
@@ -42947,7 +42990,7 @@ const densityFogFactor = Fn( ( [ density ], builder ) => {
* @param {Node} density - Defines the fog density.
* @param {Node} height - The height threshold in world space. Everything below this y-coordinate is affected by fog.
*/
-const exponentialHeightFogFactor = Fn( ( [ density, height ], builder ) => {
+const exponentialHeightFogFactor = /*@__PURE__*/ Fn( ( [ density, height ], builder ) => {
const viewZ = getViewZNode( builder );
@@ -42967,7 +43010,7 @@ const exponentialHeightFogFactor = Fn( ( [ density, height ], builder ) => {
* @param {Node} color - Defines the color of the fog.
* @param {Node} factor - Defines how the fog is factored in the scene.
*/
-const fog = Fn( ( [ color, factor ] ) => {
+const fog = /*@__PURE__*/ Fn( ( [ color, factor ] ) => {
return vec4( factor.toFloat().mix( output.rgb, color.toVec3() ), output.a );
@@ -43450,7 +43493,7 @@ class BarrierNode extends Node {
* @param {string} scope - The scope defines the behavior of the node..
* @returns {BarrierNode}
*/
-const barrier = nodeProxy( BarrierNode );
+const barrier = /*@__PURE__*/ nodeProxy( BarrierNode );
/**
* TSL function for creating a workgroup barrier. All compute shader
@@ -43842,17 +43885,61 @@ class AtomicFunctionNode extends Node {
}
-}
+ static get ATOMIC_LOAD() {
+
+ return 'atomicLoad';
+
+ }
+
+ static get ATOMIC_STORE() {
-AtomicFunctionNode.ATOMIC_LOAD = 'atomicLoad';
-AtomicFunctionNode.ATOMIC_STORE = 'atomicStore';
-AtomicFunctionNode.ATOMIC_ADD = 'atomicAdd';
-AtomicFunctionNode.ATOMIC_SUB = 'atomicSub';
-AtomicFunctionNode.ATOMIC_MAX = 'atomicMax';
-AtomicFunctionNode.ATOMIC_MIN = 'atomicMin';
-AtomicFunctionNode.ATOMIC_AND = 'atomicAnd';
-AtomicFunctionNode.ATOMIC_OR = 'atomicOr';
-AtomicFunctionNode.ATOMIC_XOR = 'atomicXor';
+ return 'atomicStore';
+
+ }
+
+ static get ATOMIC_ADD() {
+
+ return 'atomicAdd';
+
+ }
+
+ static get ATOMIC_SUB() {
+
+ return 'atomicSub';
+
+ }
+
+ static get ATOMIC_MAX() {
+
+ return 'atomicMax';
+
+ }
+
+ static get ATOMIC_MIN() {
+
+ return 'atomicMin';
+
+ }
+
+ static get ATOMIC_AND() {
+
+ return 'atomicAnd';
+
+ }
+
+ static get ATOMIC_OR() {
+
+ return 'atomicOr';
+
+ }
+
+ static get ATOMIC_XOR() {
+
+ return 'atomicXor';
+
+ }
+
+}
/**
* TSL function for creating an atomic function node.
@@ -43864,7 +43951,7 @@ AtomicFunctionNode.ATOMIC_XOR = 'atomicXor';
* @param {Node} valueNode - The value that mutates the atomic variable.
* @returns {AtomicFunctionNode}
*/
-const atomicNode = nodeProxy( AtomicFunctionNode );
+const atomicNode = /*@__PURE__*/ nodeProxy( AtomicFunctionNode );
/**
* TSL function for appending an atomic function call into the programmatic flow of a compute shader.
@@ -44140,40 +44227,160 @@ class SubgroupFunctionNode extends TempNode {
}
-}
+ // 0 inputs
+ static get SUBGROUP_ELECT() {
-// 0 inputs
-SubgroupFunctionNode.SUBGROUP_ELECT = 'subgroupElect';
+ return 'subgroupElect';
-// 1 input
-SubgroupFunctionNode.SUBGROUP_BALLOT = 'subgroupBallot';
-SubgroupFunctionNode.SUBGROUP_ADD = 'subgroupAdd';
-SubgroupFunctionNode.SUBGROUP_INCLUSIVE_ADD = 'subgroupInclusiveAdd';
-SubgroupFunctionNode.SUBGROUP_EXCLUSIVE_AND = 'subgroupExclusiveAdd';
-SubgroupFunctionNode.SUBGROUP_MUL = 'subgroupMul';
-SubgroupFunctionNode.SUBGROUP_INCLUSIVE_MUL = 'subgroupInclusiveMul';
-SubgroupFunctionNode.SUBGROUP_EXCLUSIVE_MUL = 'subgroupExclusiveMul';
-SubgroupFunctionNode.SUBGROUP_AND = 'subgroupAnd';
-SubgroupFunctionNode.SUBGROUP_OR = 'subgroupOr';
-SubgroupFunctionNode.SUBGROUP_XOR = 'subgroupXor';
-SubgroupFunctionNode.SUBGROUP_MIN = 'subgroupMin';
-SubgroupFunctionNode.SUBGROUP_MAX = 'subgroupMax';
-SubgroupFunctionNode.SUBGROUP_ALL = 'subgroupAll';
-SubgroupFunctionNode.SUBGROUP_ANY = 'subgroupAny';
-SubgroupFunctionNode.SUBGROUP_BROADCAST_FIRST = 'subgroupBroadcastFirst';
-SubgroupFunctionNode.QUAD_SWAP_X = 'quadSwapX';
-SubgroupFunctionNode.QUAD_SWAP_Y = 'quadSwapY';
-SubgroupFunctionNode.QUAD_SWAP_DIAGONAL = 'quadSwapDiagonal';
+ }
-// 2 inputs
-SubgroupFunctionNode.SUBGROUP_BROADCAST = 'subgroupBroadcast';
-SubgroupFunctionNode.SUBGROUP_SHUFFLE = 'subgroupShuffle';
-SubgroupFunctionNode.SUBGROUP_SHUFFLE_XOR = 'subgroupShuffleXor';
-SubgroupFunctionNode.SUBGROUP_SHUFFLE_UP = 'subgroupShuffleUp';
-SubgroupFunctionNode.SUBGROUP_SHUFFLE_DOWN = 'subgroupShuffleDown';
-SubgroupFunctionNode.QUAD_BROADCAST = 'quadBroadcast';
+ // 1 input
+ static get SUBGROUP_BALLOT() {
+
+ return 'subgroupBallot';
+
+ }
+
+ static get SUBGROUP_ADD() {
+
+ return 'subgroupAdd';
+
+ }
+
+ static get SUBGROUP_INCLUSIVE_ADD() {
+
+ return 'subgroupInclusiveAdd';
+
+ }
+
+ static get SUBGROUP_EXCLUSIVE_AND() {
+
+ return 'subgroupExclusiveAdd';
+ }
+
+ static get SUBGROUP_MUL() {
+
+ return 'subgroupMul';
+
+ }
+
+ static get SUBGROUP_INCLUSIVE_MUL() {
+
+ return 'subgroupInclusiveMul';
+
+ }
+
+ static get SUBGROUP_EXCLUSIVE_MUL() {
+
+ return 'subgroupExclusiveMul';
+
+ }
+
+ static get SUBGROUP_AND() {
+
+ return 'subgroupAnd';
+
+ }
+
+ static get SUBGROUP_OR() {
+
+ return 'subgroupOr';
+
+ }
+
+ static get SUBGROUP_XOR() {
+
+ return 'subgroupXor';
+
+ }
+
+ static get SUBGROUP_MIN() {
+
+ return 'subgroupMin';
+
+ }
+
+ static get SUBGROUP_MAX() {
+
+ return 'subgroupMax';
+
+ }
+
+ static get SUBGROUP_ALL() {
+
+ return 'subgroupAll';
+
+ }
+
+ static get SUBGROUP_ANY() {
+
+ return 'subgroupAny';
+
+ }
+
+ static get SUBGROUP_BROADCAST_FIRST() {
+
+ return 'subgroupBroadcastFirst';
+
+ }
+
+ static get QUAD_SWAP_X() {
+
+ return 'quadSwapX';
+
+ }
+
+ static get QUAD_SWAP_Y() {
+ return 'quadSwapY';
+
+ }
+
+ static get QUAD_SWAP_DIAGONAL() {
+
+ return 'quadSwapDiagonal';
+
+ }
+
+ // 2 inputs
+ static get SUBGROUP_BROADCAST() {
+
+ return 'subgroupBroadcast';
+
+ }
+
+ static get SUBGROUP_SHUFFLE() {
+
+ return 'subgroupShuffle';
+
+ }
+
+ static get SUBGROUP_SHUFFLE_XOR() {
+
+ return 'subgroupShuffleXor';
+
+ }
+
+ static get SUBGROUP_SHUFFLE_UP() {
+
+ return 'subgroupShuffleUp';
+
+ }
+
+ static get SUBGROUP_SHUFFLE_DOWN() {
+
+ return 'subgroupShuffleDown';
+
+ }
+
+ static get QUAD_BROADCAST() {
+
+ return 'quadBroadcast';
+
+ }
+
+}
/**
* Returns true if this invocation has the lowest subgroup_invocation_id
@@ -47193,7 +47400,7 @@ const checker = /*@__PURE__*/ Fn( ( [ coord = uv$1() ] ) => {
* @param {Node} coord - The uv to generate the circle.
* @return {Node} The circle shape.
*/
-const shapeCircle = Fn( ( [ coord = uv$1() ], { renderer, material } ) => {
+const shapeCircle = /*@__PURE__*/ Fn( ( [ coord = uv$1() ], { renderer, material } ) => {
const len2 = lengthSq( coord.mul( 2 ).sub( 1 ) );
@@ -49329,6 +49536,7 @@ var TSL = /*#__PURE__*/Object.freeze({
__proto__: null,
BRDF_GGX: BRDF_GGX,
BRDF_Lambert: BRDF_Lambert,
+ BRDF_Sheen: BRDF_Sheen,
BasicPointShadowFilter: BasicPointShadowFilter,
BasicShadowFilter: BasicShadowFilter,
Break: Break,
@@ -49336,8 +49544,10 @@ var TSL = /*#__PURE__*/Object.freeze({
Continue: Continue,
DFGLUT: DFGLUT,
D_GGX: D_GGX,
+ D_GGX_Anisotropic: D_GGX_Anisotropic,
Discard: Discard,
EPSILON: EPSILON,
+ EnvironmentBRDF: EnvironmentBRDF,
F_Schlick: F_Schlick,
Fn: Fn,
HALF_PI: HALF_PI,
@@ -49370,6 +49580,7 @@ var TSL = /*#__PURE__*/Object.freeze({
TWO_PI: TWO_PI,
VSMShadowFilter: VSMShadowFilter,
V_GGX_SmithCorrelated: V_GGX_SmithCorrelated,
+ V_GGX_SmithCorrelated_Anisotropic: V_GGX_SmithCorrelated_Anisotropic,
Var: Var,
VarIntent: VarIntent,
abs: abs,
@@ -49423,6 +49634,7 @@ var TSL = /*#__PURE__*/Object.freeze({
bitangentGeometry: bitangentGeometry,
bitangentLocal: bitangentLocal,
bitangentView: bitangentView,
+ bitangentViewFrame: bitangentViewFrame,
bitangentWorld: bitangentWorld,
bitcast: bitcast,
blendBurn: blendBurn,
@@ -49463,6 +49675,8 @@ var TSL = /*#__PURE__*/Object.freeze({
clearcoatNormalView: clearcoatNormalView,
clearcoatRoughness: clearcoatRoughness,
clipSpace: clipSpace,
+ clipping: clipping,
+ clippingAlpha: clippingAlpha,
code: code,
color: color,
colorSpaceToWorking: colorSpaceToWorking,
@@ -49551,13 +49765,14 @@ var TSL = /*#__PURE__*/Object.freeze({
grayscale: grayscale,
greaterThan: greaterThan,
greaterThanEqual: greaterThanEqual,
+ hardwareClipping: hardwareClipping,
hash: hash,
highpModelNormalViewMatrix: highpModelNormalViewMatrix,
highpModelViewMatrix: highpModelViewMatrix,
hue: hue,
increment: increment,
incrementBefore: incrementBefore,
- inspector: inspector,
+ inspect: inspect,
instance: instance,
instanceColor: instanceColor,
instanceIndex: instanceIndex,
@@ -49867,6 +50082,7 @@ var TSL = /*#__PURE__*/Object.freeze({
stepElement: stepElement,
storage: storage,
storageBarrier: storageBarrier,
+ storageElement: storageElement,
storageTexture: storageTexture,
storageTexture3D: storageTexture3D,
struct: struct,
@@ -49899,6 +50115,7 @@ var TSL = /*#__PURE__*/Object.freeze({
tangentGeometry: tangentGeometry,
tangentLocal: tangentLocal,
tangentView: tangentView,
+ tangentViewFrame: tangentViewFrame,
tangentWorld: tangentWorld,
tanh: tanh,
texture: texture,
@@ -57382,6 +57599,8 @@ class NodeManager extends DataMap {
const _plane = /*@__PURE__*/ new Plane();
+let _clippingContextId = 0;
+
/**
* Represents the state that is used to perform clipping via clipping planes.
* There is a default clipping context for each render context. When the
@@ -57399,6 +57618,14 @@ class ClippingContext {
*/
constructor( parentContext = null ) {
+ /**
+ * The id of the clipping context.
+ *
+ * @type {number}
+ * @readonly
+ */
+ this.id = _clippingContextId ++;
+
/**
* The clipping context's version.
*
@@ -57599,7 +57826,7 @@ class ClippingContext {
if ( update ) {
this.version ++;
- this.cacheKey = `${ this.intersectionPlanes.length }:${ this.unionPlanes.length }`;
+ this.cacheKey = `${ this.id }:${ this.intersectionPlanes.length }:${ this.unionPlanes.length }`;
}
@@ -63111,7 +63338,6 @@ class Renderer {
if ( this._initialized === true ) {
this.info.dispose();
- this.backend.dispose();
this._animation.dispose();
this._objects.dispose();
@@ -63135,6 +63361,8 @@ class Renderer {
} );
+ this.backend.dispose();
+
}
this.setRenderTarget( null );
@@ -69673,28 +69901,27 @@ class WebGLState {
? this.enable( gl.SAMPLE_ALPHA_TO_COVERAGE )
: this.disable( gl.SAMPLE_ALPHA_TO_COVERAGE );
- if ( hardwareClippingPlanes > 0 ) {
-
- if ( this.currentClippingPlanes !== hardwareClippingPlanes ) {
- const CLIP_DISTANCE0_WEBGL = 0x3000;
+ if ( this.currentClippingPlanes !== hardwareClippingPlanes ) {
- for ( let i = 0; i < 8; i ++ ) {
+ const CLIP_DISTANCE0_WEBGL = 0x3000;
- if ( i < hardwareClippingPlanes ) {
+ for ( let i = 0; i < 8; i ++ ) {
- this.enable( CLIP_DISTANCE0_WEBGL + i );
+ if ( i < hardwareClippingPlanes ) {
- } else {
+ this.enable( CLIP_DISTANCE0_WEBGL + i );
- this.disable( CLIP_DISTANCE0_WEBGL + i );
+ } else {
- }
+ this.disable( CLIP_DISTANCE0_WEBGL + i );
}
}
+ this.currentClippingPlanes = hardwareClippingPlanes;
+
}
}
@@ -71812,6 +72039,7 @@ class WebGLTextureUtils {
backend.state.bindFramebuffer( gl.READ_FRAMEBUFFER, null );
+ gl.deleteBuffer( buffer );
gl.deleteFramebuffer( fb );
return dstBuffer;
@@ -73554,6 +73782,7 @@ class WebGLBackend extends Backend {
const clearStencil = renderer.getClearStencil();
if ( depth ) this.state.setDepthMask( true );
+ if ( stencil ) this.state.setStencilMask( 0xffffffff );
if ( descriptor.textures === null ) {
@@ -73996,9 +74225,9 @@ class WebGLBackend extends Backend {
}
- const pixelRatio = this.renderer.getPixelRatio();
-
const renderTarget = this._currentContext.renderTarget;
+
+ const pixelRatio = renderTarget !== null ? 1 : this.renderer.getPixelRatio();
const isRenderCameraDepthArray = this._isRenderCameraDepthArray( this._currentContext );
const prevActiveCubeFace = this._currentContext.activeCubeFace;
@@ -87939,7 +88168,7 @@ class WebGPUBackend extends Backend {
}
- const pixelRatio = this.renderer.getPixelRatio();
+ const pixelRatio = context.renderTarget !== null ? 1 : this.renderer.getPixelRatio();
const indexPos = cameraIndex ? bindings.indexOf( cameraIndex ) : -1;
for ( let i = 0, len = cameras.length; i < len; i ++ ) {
diff --git a/src/nodes/accessors/BuiltinNode.js b/src/nodes/accessors/BuiltinNode.js
index 0dc6b682b966aa..ba14c6a58f7873 100644
--- a/src/nodes/accessors/BuiltinNode.js
+++ b/src/nodes/accessors/BuiltinNode.js
@@ -60,4 +60,4 @@ export default BuiltinNode;
* @param {string} name - The name of the built-in shader variable.
* @returns {BuiltinNode}
*/
-export const builtin = nodeProxy( BuiltinNode ).setParameterLength( 1 );
+export const builtin = /*@__PURE__*/ nodeProxy( BuiltinNode ).setParameterLength( 1 );
diff --git a/src/nodes/accessors/Texture3DNode.js b/src/nodes/accessors/Texture3DNode.js
index c0fcd0b263265f..556b83fc56928f 100644
--- a/src/nodes/accessors/Texture3DNode.js
+++ b/src/nodes/accessors/Texture3DNode.js
@@ -1,7 +1,7 @@
import TextureNode from './TextureNode.js';
import { nodeProxy, vec3, Fn, If } from '../tsl/TSLBase.js';
-const normal = Fn( ( { texture, uv } ) => {
+const normal = /*@__PURE__*/ Fn( ( { texture, uv } ) => {
const epsilon = 0.0001;
diff --git a/src/nodes/display/BumpMapNode.js b/src/nodes/display/BumpMapNode.js
index 3848591f6a2cda..a868ad20bbf3aa 100644
--- a/src/nodes/display/BumpMapNode.js
+++ b/src/nodes/display/BumpMapNode.js
@@ -8,7 +8,7 @@ import { Fn, nodeProxy, float, vec2 } from '../tsl/TSLBase.js';
// Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen
// https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf
-const dHdxy_fwd = Fn( ( { textureNode, bumpScale } ) => {
+const dHdxy_fwd = /*@__PURE__*/ Fn( ( { textureNode, bumpScale } ) => {
// It's used to preserve the same TextureNode instance
const sampleTexture = ( callback ) => textureNode.isolate().context( { getUV: ( texNode ) => callback( texNode.uvNode || uv() ), forceUVContext: true } );
@@ -24,7 +24,7 @@ const dHdxy_fwd = Fn( ( { textureNode, bumpScale } ) => {
// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
-const perturbNormalArb = Fn( ( inputs ) => {
+const perturbNormalArb = /*@__PURE__*/ Fn( ( inputs ) => {
const { surf_pos, surf_norm, dHdxy } = inputs;
diff --git a/src/nodes/display/ColorAdjustment.js b/src/nodes/display/ColorAdjustment.js
index 090a949a7e6242..061d25aeae9cab 100644
--- a/src/nodes/display/ColorAdjustment.js
+++ b/src/nodes/display/ColorAdjustment.js
@@ -151,7 +151,7 @@ export const cdl = /*@__PURE__*/ Fn( ( [
* @param {Node} stepsNode - Controls the intensity of the posterization effect. A lower number results in a more blocky appearance.
* @returns {Node} The posterized color.
*/
-export const posterize = Fn( ( [ source, steps ] ) => {
+export const posterize = /*@__PURE__*/ Fn( ( [ source, steps ] ) => {
return source.mul( steps ).floor().div( steps );
diff --git a/src/nodes/display/PassNode.js b/src/nodes/display/PassNode.js
index 69268c142dfcb4..01fb6dc495869a 100644
--- a/src/nodes/display/PassNode.js
+++ b/src/nodes/display/PassNode.js
@@ -1044,21 +1044,29 @@ class PassNode extends TempNode {
}
-}
+ /**
+ * @static
+ * @type {'color'}
+ * @default 'color'
+ */
+ static get COLOR() {
-/**
- * @static
- * @type {'color'}
- * @default 'color'
- */
-PassNode.COLOR = 'color';
+ return 'color';
-/**
- * @static
- * @type {'depth'}
- * @default 'depth'
- */
-PassNode.DEPTH = 'depth';
+ }
+
+ /**
+ * @static
+ * @type {'depth'}
+ * @default 'depth'
+ */
+ static get DEPTH() {
+
+ return 'depth';
+
+ }
+
+}
export default PassNode;
diff --git a/src/nodes/fog/Fog.js b/src/nodes/fog/Fog.js
index 644b2646b5304c..2b202d04c681ae 100644
--- a/src/nodes/fog/Fog.js
+++ b/src/nodes/fog/Fog.js
@@ -37,7 +37,7 @@ function getViewZNode( builder ) {
* @param {Node} near - Defines the near value.
* @param {Node} far - Defines the far value.
*/
-export const rangeFogFactor = Fn( ( [ near, far ], builder ) => {
+export const rangeFogFactor = /*@__PURE__*/ Fn( ( [ near, far ], builder ) => {
const viewZ = getViewZNode( builder );
@@ -54,7 +54,7 @@ export const rangeFogFactor = Fn( ( [ near, far ], builder ) => {
* @function
* @param {Node} density - Defines the fog density.
*/
-export const densityFogFactor = Fn( ( [ density ], builder ) => {
+export const densityFogFactor = /*@__PURE__*/ Fn( ( [ density ], builder ) => {
const viewZ = getViewZNode( builder );
@@ -70,7 +70,7 @@ export const densityFogFactor = Fn( ( [ density ], builder ) => {
* @param {Node} density - Defines the fog density.
* @param {Node} height - The height threshold in world space. Everything below this y-coordinate is affected by fog.
*/
-export const exponentialHeightFogFactor = Fn( ( [ density, height ], builder ) => {
+export const exponentialHeightFogFactor = /*@__PURE__*/ Fn( ( [ density, height ], builder ) => {
const viewZ = getViewZNode( builder );
@@ -90,7 +90,7 @@ export const exponentialHeightFogFactor = Fn( ( [ density, height ], builder ) =
* @param {Node} color - Defines the color of the fog.
* @param {Node} factor - Defines how the fog is factored in the scene.
*/
-export const fog = Fn( ( [ color, factor ] ) => {
+export const fog = /*@__PURE__*/ Fn( ( [ color, factor ] ) => {
return vec4( factor.toFloat().mix( output.rgb, color.toVec3() ), output.a );
diff --git a/src/nodes/gpgpu/AtomicFunctionNode.js b/src/nodes/gpgpu/AtomicFunctionNode.js
index 26464b996c2add..bb17b2b0ab641d 100644
--- a/src/nodes/gpgpu/AtomicFunctionNode.js
+++ b/src/nodes/gpgpu/AtomicFunctionNode.js
@@ -133,17 +133,61 @@ class AtomicFunctionNode extends Node {
}
-}
+ static get ATOMIC_LOAD() {
+
+ return 'atomicLoad';
+
+ }
+
+ static get ATOMIC_STORE() {
+
+ return 'atomicStore';
+
+ }
+
+ static get ATOMIC_ADD() {
+
+ return 'atomicAdd';
-AtomicFunctionNode.ATOMIC_LOAD = 'atomicLoad';
-AtomicFunctionNode.ATOMIC_STORE = 'atomicStore';
-AtomicFunctionNode.ATOMIC_ADD = 'atomicAdd';
-AtomicFunctionNode.ATOMIC_SUB = 'atomicSub';
-AtomicFunctionNode.ATOMIC_MAX = 'atomicMax';
-AtomicFunctionNode.ATOMIC_MIN = 'atomicMin';
-AtomicFunctionNode.ATOMIC_AND = 'atomicAnd';
-AtomicFunctionNode.ATOMIC_OR = 'atomicOr';
-AtomicFunctionNode.ATOMIC_XOR = 'atomicXor';
+ }
+
+ static get ATOMIC_SUB() {
+
+ return 'atomicSub';
+
+ }
+
+ static get ATOMIC_MAX() {
+
+ return 'atomicMax';
+
+ }
+
+ static get ATOMIC_MIN() {
+
+ return 'atomicMin';
+
+ }
+
+ static get ATOMIC_AND() {
+
+ return 'atomicAnd';
+
+ }
+
+ static get ATOMIC_OR() {
+
+ return 'atomicOr';
+
+ }
+
+ static get ATOMIC_XOR() {
+
+ return 'atomicXor';
+
+ }
+
+}
export default AtomicFunctionNode;
@@ -157,7 +201,7 @@ export default AtomicFunctionNode;
* @param {Node} valueNode - The value that mutates the atomic variable.
* @returns {AtomicFunctionNode}
*/
-const atomicNode = nodeProxy( AtomicFunctionNode );
+const atomicNode = /*@__PURE__*/ nodeProxy( AtomicFunctionNode );
/**
* TSL function for appending an atomic function call into the programmatic flow of a compute shader.
diff --git a/src/nodes/gpgpu/BarrierNode.js b/src/nodes/gpgpu/BarrierNode.js
index 33341e413aed4c..028dbbd2205c4e 100644
--- a/src/nodes/gpgpu/BarrierNode.js
+++ b/src/nodes/gpgpu/BarrierNode.js
@@ -61,7 +61,7 @@ export default BarrierNode;
* @param {string} scope - The scope defines the behavior of the node..
* @returns {BarrierNode}
*/
-const barrier = nodeProxy( BarrierNode );
+const barrier = /*@__PURE__*/ nodeProxy( BarrierNode );
/**
* TSL function for creating a workgroup barrier. All compute shader
diff --git a/src/nodes/gpgpu/SubgroupFunctionNode.js b/src/nodes/gpgpu/SubgroupFunctionNode.js
index dad8f164182093..2420045a1ceb8a 100644
--- a/src/nodes/gpgpu/SubgroupFunctionNode.js
+++ b/src/nodes/gpgpu/SubgroupFunctionNode.js
@@ -162,42 +162,162 @@ class SubgroupFunctionNode extends TempNode {
}
-}
+ // 0 inputs
+ static get SUBGROUP_ELECT() {
-// 0 inputs
-SubgroupFunctionNode.SUBGROUP_ELECT = 'subgroupElect';
-
-// 1 input
-SubgroupFunctionNode.SUBGROUP_BALLOT = 'subgroupBallot';
-SubgroupFunctionNode.SUBGROUP_ADD = 'subgroupAdd';
-SubgroupFunctionNode.SUBGROUP_INCLUSIVE_ADD = 'subgroupInclusiveAdd';
-SubgroupFunctionNode.SUBGROUP_EXCLUSIVE_AND = 'subgroupExclusiveAdd';
-SubgroupFunctionNode.SUBGROUP_MUL = 'subgroupMul';
-SubgroupFunctionNode.SUBGROUP_INCLUSIVE_MUL = 'subgroupInclusiveMul';
-SubgroupFunctionNode.SUBGROUP_EXCLUSIVE_MUL = 'subgroupExclusiveMul';
-SubgroupFunctionNode.SUBGROUP_AND = 'subgroupAnd';
-SubgroupFunctionNode.SUBGROUP_OR = 'subgroupOr';
-SubgroupFunctionNode.SUBGROUP_XOR = 'subgroupXor';
-SubgroupFunctionNode.SUBGROUP_MIN = 'subgroupMin';
-SubgroupFunctionNode.SUBGROUP_MAX = 'subgroupMax';
-SubgroupFunctionNode.SUBGROUP_ALL = 'subgroupAll';
-SubgroupFunctionNode.SUBGROUP_ANY = 'subgroupAny';
-SubgroupFunctionNode.SUBGROUP_BROADCAST_FIRST = 'subgroupBroadcastFirst';
-SubgroupFunctionNode.QUAD_SWAP_X = 'quadSwapX';
-SubgroupFunctionNode.QUAD_SWAP_Y = 'quadSwapY';
-SubgroupFunctionNode.QUAD_SWAP_DIAGONAL = 'quadSwapDiagonal';
-
-// 2 inputs
-SubgroupFunctionNode.SUBGROUP_BROADCAST = 'subgroupBroadcast';
-SubgroupFunctionNode.SUBGROUP_SHUFFLE = 'subgroupShuffle';
-SubgroupFunctionNode.SUBGROUP_SHUFFLE_XOR = 'subgroupShuffleXor';
-SubgroupFunctionNode.SUBGROUP_SHUFFLE_UP = 'subgroupShuffleUp';
-SubgroupFunctionNode.SUBGROUP_SHUFFLE_DOWN = 'subgroupShuffleDown';
-SubgroupFunctionNode.QUAD_BROADCAST = 'quadBroadcast';
+ return 'subgroupElect';
-export default SubgroupFunctionNode;
+ }
+
+ // 1 input
+ static get SUBGROUP_BALLOT() {
+
+ return 'subgroupBallot';
+
+ }
+
+ static get SUBGROUP_ADD() {
+
+ return 'subgroupAdd';
+
+ }
+
+ static get SUBGROUP_INCLUSIVE_ADD() {
+
+ return 'subgroupInclusiveAdd';
+
+ }
+
+ static get SUBGROUP_EXCLUSIVE_AND() {
+
+ return 'subgroupExclusiveAdd';
+
+ }
+
+ static get SUBGROUP_MUL() {
+
+ return 'subgroupMul';
+
+ }
+
+ static get SUBGROUP_INCLUSIVE_MUL() {
+
+ return 'subgroupInclusiveMul';
+
+ }
+
+ static get SUBGROUP_EXCLUSIVE_MUL() {
+
+ return 'subgroupExclusiveMul';
+
+ }
+
+ static get SUBGROUP_AND() {
+
+ return 'subgroupAnd';
+
+ }
+
+ static get SUBGROUP_OR() {
+
+ return 'subgroupOr';
+
+ }
+
+ static get SUBGROUP_XOR() {
+
+ return 'subgroupXor';
+
+ }
+
+ static get SUBGROUP_MIN() {
+
+ return 'subgroupMin';
+
+ }
+
+ static get SUBGROUP_MAX() {
+
+ return 'subgroupMax';
+
+ }
+ static get SUBGROUP_ALL() {
+ return 'subgroupAll';
+
+ }
+
+ static get SUBGROUP_ANY() {
+
+ return 'subgroupAny';
+
+ }
+
+ static get SUBGROUP_BROADCAST_FIRST() {
+
+ return 'subgroupBroadcastFirst';
+
+ }
+
+ static get QUAD_SWAP_X() {
+
+ return 'quadSwapX';
+
+ }
+
+ static get QUAD_SWAP_Y() {
+
+ return 'quadSwapY';
+
+ }
+
+ static get QUAD_SWAP_DIAGONAL() {
+
+ return 'quadSwapDiagonal';
+
+ }
+
+ // 2 inputs
+ static get SUBGROUP_BROADCAST() {
+
+ return 'subgroupBroadcast';
+
+ }
+
+ static get SUBGROUP_SHUFFLE() {
+
+ return 'subgroupShuffle';
+
+ }
+
+ static get SUBGROUP_SHUFFLE_XOR() {
+
+ return 'subgroupShuffleXor';
+
+ }
+
+ static get SUBGROUP_SHUFFLE_UP() {
+
+ return 'subgroupShuffleUp';
+
+ }
+
+ static get SUBGROUP_SHUFFLE_DOWN() {
+
+ return 'subgroupShuffleDown';
+
+ }
+
+ static get QUAD_BROADCAST() {
+
+ return 'quadBroadcast';
+
+ }
+
+}
+
+export default SubgroupFunctionNode;
/**
* Returns true if this invocation has the lowest subgroup_invocation_id
diff --git a/src/nodes/math/BitcountNode.js b/src/nodes/math/BitcountNode.js
index e11f63b2810cf0..a6189b37b17792 100644
--- a/src/nodes/math/BitcountNode.js
+++ b/src/nodes/math/BitcountNode.js
@@ -388,14 +388,28 @@ class BitcountNode extends MathNode {
}
+ static get COUNT_TRAILING_ZEROS() {
+
+ return 'countTrailingZeros';
+
+ }
+
+ static get COUNT_LEADING_ZEROS() {
+
+ return 'countLeadingZeros';
+
+ }
+
+ static get COUNT_ONE_BITS() {
+
+ return 'countOneBits';
+
+ }
+
}
export default BitcountNode;
-BitcountNode.COUNT_TRAILING_ZEROS = 'countTrailingZeros';
-BitcountNode.COUNT_LEADING_ZEROS = 'countLeadingZeros';
-BitcountNode.COUNT_ONE_BITS = 'countOneBits';
-
/**
* Finds the number of consecutive 0 bits from the least significant bit of the input value,
* which is also the index of the least significant bit of the input value.
diff --git a/src/nodes/math/OperatorNode.js b/src/nodes/math/OperatorNode.js
index bf53b92c7f9f5b..28862db5d85f9f 100644
--- a/src/nodes/math/OperatorNode.js
+++ b/src/nodes/math/OperatorNode.js
@@ -670,7 +670,7 @@ export const shiftRight = /*@__PURE__*/ nodeProxyIntent( OperatorNode, '>>' ).se
* @param {Node} a - The node to increment.
* @returns {OperatorNode}
*/
-export const incrementBefore = Fn( ( [ a ] ) => {
+export const incrementBefore = /*@__PURE__*/ Fn( ( [ a ] ) => {
a.addAssign( 1 );
return a;
@@ -685,7 +685,7 @@ export const incrementBefore = Fn( ( [ a ] ) => {
* @param {Node} a - The node to decrement.
* @returns {OperatorNode}
*/
-export const decrementBefore = Fn( ( [ a ] ) => {
+export const decrementBefore = /*@__PURE__*/ Fn( ( [ a ] ) => {
a.subAssign( 1 );
return a;
diff --git a/src/nodes/shapes/Shapes.js b/src/nodes/shapes/Shapes.js
index 777187a8f8e016..e946bd2f7b5c57 100644
--- a/src/nodes/shapes/Shapes.js
+++ b/src/nodes/shapes/Shapes.js
@@ -10,7 +10,7 @@ import { uv } from '../accessors/UV.js';
* @param {Node} coord - The uv to generate the circle.
* @return {Node} The circle shape.
*/
-export const shapeCircle = Fn( ( [ coord = uv() ], { renderer, material } ) => {
+export const shapeCircle = /*@__PURE__*/ Fn( ( [ coord = uv() ], { renderer, material } ) => {
const len2 = lengthSq( coord.mul( 2 ).sub( 1 ) );
diff --git a/src/nodes/utils/PostProcessingUtils.js b/src/nodes/utils/PostProcessingUtils.js
index 823c8d27ea15ed..09c471ba2effc1 100644
--- a/src/nodes/utils/PostProcessingUtils.js
+++ b/src/nodes/utils/PostProcessingUtils.js
@@ -131,7 +131,7 @@ export const getNormalFromDepth = /*@__PURE__*/ Fn( ( [ uv, depthTexture, projec
* @param {Node} position - The input position, usually screen coordinates.
* @return {Node} The noise value.
*/
-export const interleavedGradientNoise = Fn( ( [ position ] ) => {
+export const interleavedGradientNoise = /*@__PURE__*/ Fn( ( [ position ] ) => {
return fract( float( 52.9829189 ).mul( fract( dot( position, vec2( 0.06711056, 0.00583715 ) ) ) ) );
@@ -157,7 +157,7 @@ export const interleavedGradientNoise = Fn( ( [ position ] ) => {
* @param {Node} phi - Rotation angle in radians (typically from IGN * 2π).
* @return {Node} A 2D point on the unit disk.
*/
-export const vogelDiskSample = Fn( ( [ sampleIndex, samplesCount, phi ] ) => {
+export const vogelDiskSample = /*@__PURE__*/ Fn( ( [ sampleIndex, samplesCount, phi ] ) => {
const goldenAngle = float( 2.399963229728653 ); // 2π * (2 - φ) where φ is golden ratio
const r = sqrt( float( sampleIndex ).add( 0.5 ).div( float( samplesCount ) ) );
diff --git a/src/renderers/common/RenderObjects.js b/src/renderers/common/RenderObjects.js
index 676cc2bd416942..93c235c70c866a 100644
--- a/src/renderers/common/RenderObjects.js
+++ b/src/renderers/common/RenderObjects.js
@@ -68,9 +68,18 @@ class RenderObjects {
* A dictionary that manages render contexts in chain maps
* for each pass ID.
*
+ * @private
* @type {Object}
*/
- this.chainMaps = {};
+ this._chainMaps = {};
+
+ /**
+ * Stores all render objects created by this component.
+ *
+ * @private
+ * @type {Set}
+ */
+ this._renderObjects = new Set();
}
@@ -163,7 +172,7 @@ class RenderObjects {
*/
getChainMap( passId = 'default' ) {
- return this.chainMaps[ passId ] || ( this.chainMaps[ passId ] = new ChainMap() );
+ return this._chainMaps[ passId ] || ( this._chainMaps[ passId ] = new ChainMap() );
}
@@ -172,7 +181,15 @@ class RenderObjects {
*/
dispose() {
- this.chainMaps = {};
+ for ( const renderObject of this._renderObjects ) {
+
+ renderObject.dispose();
+
+ }
+
+ this._renderObjects.clear();
+
+ this._chainMaps = {};
}
@@ -206,8 +223,12 @@ class RenderObjects {
chainMap.delete( renderObject.getChainArray() );
+ this._renderObjects.delete( renderObject );
+
};
+ this._renderObjects.add( renderObject );
+
return renderObject;
}
diff --git a/src/renderers/common/Renderer.js b/src/renderers/common/Renderer.js
index 59adb81850d2a2..cc7c87df201dfd 100644
--- a/src/renderers/common/Renderer.js
+++ b/src/renderers/common/Renderer.js
@@ -2701,7 +2701,6 @@ class Renderer {
if ( this._initialized === true ) {
this.info.dispose();
- this.backend.dispose();
this._animation.dispose();
this._objects.dispose();
@@ -2725,6 +2724,8 @@ class Renderer {
} );
+ this.backend.dispose();
+
}
this.setRenderTarget( null );
diff --git a/src/renderers/webgl-fallback/WebGLBackend.js b/src/renderers/webgl-fallback/WebGLBackend.js
index 00649a36bbe28a..c55ef3fe370c7f 100644
--- a/src/renderers/webgl-fallback/WebGLBackend.js
+++ b/src/renderers/webgl-fallback/WebGLBackend.js
@@ -1264,9 +1264,9 @@ class WebGLBackend extends Backend {
}
- const pixelRatio = this.renderer.getPixelRatio();
-
const renderTarget = this._currentContext.renderTarget;
+
+ const pixelRatio = renderTarget !== null ? 1 : this.renderer.getPixelRatio();
const isRenderCameraDepthArray = this._isRenderCameraDepthArray( this._currentContext );
const prevActiveCubeFace = this._currentContext.activeCubeFace;
diff --git a/src/renderers/webgpu/WebGPUBackend.js b/src/renderers/webgpu/WebGPUBackend.js
index 446157f6661ac9..e24bd4d469ea01 100644
--- a/src/renderers/webgpu/WebGPUBackend.js
+++ b/src/renderers/webgpu/WebGPUBackend.js
@@ -2257,7 +2257,7 @@ class WebGPUBackend extends Backend {
}
- const pixelRatio = this.renderer.getPixelRatio();
+ const pixelRatio = context.renderTarget !== null ? 1 : this.renderer.getPixelRatio();
const indexPos = cameraIndex ? bindings.indexOf( cameraIndex ) : - 1;
for ( let i = 0, len = cameras.length; i < len; i ++ ) {
diff --git a/test/unit/addons/tsl/GPUTest.tests.js b/test/unit/addons/tsl/GPUTest.tests.js
new file mode 100644
index 00000000000000..085ede72266529
--- /dev/null
+++ b/test/unit/addons/tsl/GPUTest.tests.js
@@ -0,0 +1,52 @@
+import { hash, vec3, float } from 'three/tsl';
+import { sRGBTransferEOTF, sRGBTransferOETF } from 'three/tsl';
+import { gpuTest, gpuFuzzTest } from './gpu-test-utils.js';
+
+export default QUnit.module( 'TSL', () => {
+
+ QUnit.module( 'GPU-native unit tests (prototype)', () => {
+
+ gpuTest( 'sRGB <-> linear round trip', ( { assert } ) => {
+
+ const srgb = vec3( 0.5, 0.2, 0.8 );
+ const roundTrip = sRGBTransferOETF( sRGBTransferEOTF( srgb ) );
+
+ assert.closeAbs( roundTrip, srgb, 1e-4 );
+
+ } );
+
+ gpuTest( 'basic scalar and vector sanity checks', ( { assert } ) => {
+
+ assert.eq( float( 1.0 ).add( 1.0 ), float( 2.0 ) );
+ assert.closeRel( vec3( 100.0, 1.0, 0.01 ), vec3( 100.1, 1.001, 0.0101 ), 0.01 );
+
+ } );
+
+ gpuTest( 'relational assertions', ( { assert } ) => {
+
+ assert.greaterThan( float( 5.0 ), float( 3.0 ) );
+ assert.greaterThanOrEqual( float( 3.0 ), float( 3.0 ) );
+ assert.lessThan( float( 3.0 ), float( 5.0 ) );
+ assert.lessThanOrEqual( float( 3.0 ), float( 3.0 ) );
+ assert.greaterThan( vec3( 5.0, 6.0, 7.0 ), vec3( 3.0, 3.0, 3.0 ) );
+
+ } );
+
+ gpuFuzzTest( 'sRGB <-> linear round trip (fuzz, 256 random colors)', 256, ( { instanceIndex, assert } ) => {
+
+ // Deterministically pseudo-random per invocation -- every instance
+ // generates and checks its own case, entirely on the GPU.
+ const srgb = vec3(
+ hash( instanceIndex.add( 1 ) ),
+ hash( instanceIndex.add( 1000 ) ),
+ hash( instanceIndex.add( 2000 ) )
+ );
+ const roundTrip = sRGBTransferOETF( sRGBTransferEOTF( srgb ) );
+
+ assert.closeAbs( roundTrip, srgb, 1e-3 );
+
+ } );
+
+ } );
+
+} );
diff --git a/test/unit/addons/tsl/gpu-test-utils.js b/test/unit/addons/tsl/gpu-test-utils.js
new file mode 100644
index 00000000000000..2309bbc1088a7f
--- /dev/null
+++ b/test/unit/addons/tsl/gpu-test-utils.js
@@ -0,0 +1,885 @@
+//
+// GPU-native TSL unit test harness (prototype).
+//
+// The general approach -- exercising real shader code on the GPU and reading
+// results back to the CPU to assert on them, rather than mocking the GPU away
+// -- is based on the GPU testing method used in threeify:
+// https://github.com/bhouston/threeify (see packages/core/src/shaders/tests/
+// and packages/core/src/shaders/**/*.test.glsl). threeify renders a fullscreen
+// quad and packs one pass/fail byte per pixel via `gl.readPixels()`, since
+// WebGL2 has no compute shaders. This harness follows the same "one row per
+// test" idea, but via TSL compute + storage-buffer readback (available here),
+// which lets each row capture full raw values (not just a pass/fail bit) and
+// resolve types automatically -- see below.
+//
+// Design: every assertion gets its own row, addressed by `instanceIndex`, in
+// a pair of `vec4` storage buffers (`actual`/`expected`) -- one compute
+// invocation per assertion. The CPU reads both buffers back and does the
+// comparison + tolerance handling + diagnostic formatting itself, so failures
+// report actual vs. expected values (and, for vectors, a per-component diff)
+// instead of a bare test id.
+//
+// DX goal: tests should read like ordinary vitest/chai-style assertions --
+// assert.closeAbs( roundTrip, srgb, 1e-4 )
+// with no manual test ids and no manually-declared value types. Types are
+// resolved automatically by asking the *actual TSL node builder* what type
+// an expression evaluates to (`node.getNodeType(builder)`), which is only
+// available from inside a node's own `setup(builder)` -- so each assertion
+// compiles down to a tiny custom Node (AssertWriteNode) whose setup() asks
+// the builder for the real type.
+//
+// Matrix support (mat3/mat4): a single `vec4` row can't hold 9 or 16 floats.
+// A matrix value is represented as `columns` column-vectors (mat3: 3 x vec3,
+// mat4: 4 x vec4 -- see `MATRIX_LAYOUT`/NodeBuilder.getElementType), each
+// zero-padded to a vec4 exactly like a plain vector value. `AssertWriteNode`
+// resolves this layout once real type info exists (`setup(builder)`) and
+// then, for each column, calls a `writeColumn(c, actualVec4, expectedVec4)`
+// callback supplied by the caller -- `gpuTest` and `gpuFuzzTest` each
+// implement that callback differently, because they use two different
+// addressing strategies (see each function's own comment below). Crucially,
+// resource cost (buffer count / dispatch size) only grows where the caller
+// chooses to pay for it -- a plain gpuTest scalar/vector assertion and a
+// gpuFuzzTest site with the default options cost exactly what they did
+// before matrices existed.
+//
+// Two entry points:
+// - gpuTest( name, buildFn ) -- N declarative assertions, one
+// compute invocation per
+// assertion (row = instanceIndex).
+// - gpuFuzzTest( name, count, buildFn ) -- assertions dispatched over
+// `count` instances, each free
+// to generate its own inputs
+// from `instanceIndex`
+// (property/fuzz-style testing
+// at GPU scale).
+// Both run on WebGPU and WebGPURenderer's WebGL2 fallback backend, since both
+// only ever write via the bare `instanceIndex` node -- the one write pattern
+// transform-feedback-based backends (WebGL2 fallback) support. Confirmed
+// empirically: any write target other than the bare `instanceIndex` node
+// (e.g. an arithmetic offset, or a JS-constant index) collapses onto slot 0
+// there instead of landing at the requested offset. Also confirmed
+// empirically: WebGL2's transform-feedback fallback only guarantees a small,
+// fixed number of simultaneously-bound output buffers (the spec-minimum
+// `MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS` is 4) -- so the number of
+// storage buffers a kernel writes to is a hard resource budget, not just a
+// memory-size concern; see `gpuFuzzTest`'s `maxColumnsPerSite` option below
+// for where that budget is spent explicitly rather than by accident.
+
+import { Fn, If, Stack, instanceIndex, instancedArray, float, vec4 } from 'three/tsl';
+import { WebGPURenderer, Node } from 'three/webgpu';
+
+export const Kind = {
+ EQ: 'eq',
+ CLOSE_ABS: 'closeAbs',
+ CLOSE_REL: 'closeRel',
+ GT: 'greaterThan',
+ GE: 'greaterThanOrEqual',
+ LT: 'lessThan',
+ LE: 'lessThanOrEqual'
+};
+
+const SWIZZLE = [ 'x', 'y', 'z', 'w' ];
+
+// Matrix types are represented as `columns` column-vectors of `columnLength`
+// components each (mat3: 3 x vec3, mat4: 4 x vec4) -- see gpu-test-utils.js
+// file header and NodeBuilder.getTypeLength/getElementType.
+const MATRIX_LAYOUT = {
+ mat3: { columns: 3, columnLength: 3 },
+ mat4: { columns: 4, columnLength: 4 }
+};
+
+// The widest supported type (mat4) needs 4 columns -- callers that reserve
+// resources up front (gpuTest's per-assertion row stride, gpuFuzzTest's
+// opt-in `maxColumnsPerSite`) size against this constant.
+const MAX_COLUMNS = 4;
+
+// Zero-pads `value` (a resolved-`count`-component node) out to a vec4, so it
+// can be written with a single `.assign()` -- one write, whatever the real
+// component count turns out to be.
+function toVec4( value, count ) {
+
+ if ( count === 4 ) return value;
+
+ const components = [];
+
+ for ( let i = 0; i < 4; i ++ ) {
+
+ components.push( i < count ? float( count === 1 ? value : value[ SWIZZLE[ i ] ] ) : float( 0 ) );
+
+ }
+
+ return vec4( ...components );
+
+}
+
+// Resolves how many "columns" a type needs and how long each column is.
+// Vectors/scalars are a single column of their own length; mat3/mat4 are
+// `MATRIX_LAYOUT`-many columns of their own (shorter) length.
+function resolveLayout( type, builder ) {
+
+ const matrixLayout = MATRIX_LAYOUT[ type ];
+
+ if ( matrixLayout !== undefined ) {
+
+ return { columns: matrixLayout.columns, columnLength: matrixLayout.columnLength, isMatrix: true };
+
+ }
+
+ const count = builder.getTypeLength( type );
+
+ if ( count > 4 ) {
+
+ throw new Error( `gpuTest: type "${ type }" (${ count } components) is not supported -- only scalars, vecN, mat3 and mat4 are.` );
+
+ }
+
+ return { columns: 1, columnLength: count, isMatrix: false };
+
+}
+
+// A statement node: at real shader-build time (setup(builder), when a real
+// NodeBuilder -- and therefore real type information -- exists) it asks the
+// builder what type `value1`/`value2` resolved to, then hands each column
+// (1 for scalars/vectors, 3 or 4 for mat3/mat4), zero-padded to a vec4, to
+// the caller-supplied `writeColumn(columnIndex, actualVec4, expectedVec4)`.
+// How -- and at what addressing cost -- a column actually gets written to a
+// buffer is entirely up to `writeColumn`; see `gpuTest`/`gpuFuzzTest` for the
+// two different strategies. `resolved*` fields are stashed on the instance
+// for the CPU harness to read back afterwards.
+class AssertWriteNode extends Node {
+
+ constructor( writeColumn, value1, value2 ) {
+
+ super( 'void' );
+
+ this.writeColumn = writeColumn;
+ this.value1 = value1;
+ this.value2 = value2;
+
+ this.resolvedType = null;
+ this.resolvedColumns = null;
+ this.resolvedColumnLength = null;
+ this.resolvedIsMatrix = null;
+
+ }
+
+ get resolvedCount() {
+
+ return this.resolvedColumns * this.resolvedColumnLength;
+
+ }
+
+ setup( builder ) {
+
+ const type1 = this.value1.getNodeType( builder );
+ const type2 = this.value2.getNodeType( builder );
+
+ if ( type1 !== type2 ) {
+
+ throw new Error( `gpuTest: type mismatch -- comparing "${ type1 }" against "${ type2 }".` );
+
+ }
+
+ const { columns, columnLength, isMatrix } = resolveLayout( type1, builder );
+
+ if ( columns > MAX_COLUMNS ) {
+
+ throw new Error( `gpuTest: type "${ type1 }" needs ${ columns } columns, more than the supported ${ MAX_COLUMNS }.` );
+
+ }
+
+ this.resolvedType = type1;
+ this.resolvedColumns = columns;
+ this.resolvedColumnLength = columnLength;
+ this.resolvedIsMatrix = isMatrix;
+
+ // Force value1/value2 to evaluate ONCE, here, unconditionally --
+ // *before* any of writeColumn's per-column branching (an `If` per
+ // column, for gpuTest's addressing scheme; see gpuTest's own comment).
+ // Skipping this and reading `this.value1.element(c)` directly from
+ // inside each column's conditional branch is a real, confirmed trap:
+ // a node's generated value gets cached/declared in whichever branch
+ // happens to build it first, so any *sibling* conditional branch that
+ // references the same node sees an uninitialized (zero) variable
+ // instead of re-evaluating it. `.toVar()` sidesteps this by forcing
+ // the evaluation to happen up front, outside every branch, so each
+ // column's branch only ever *reads* an already-computed variable.
+ // (Recall multi-column values only arise for mat3/mat4 here since
+ // scalars/vectors are always a single column -- but `.toVar()` is
+ // cheap and correct for those too, so it's applied unconditionally.)
+ const v1 = this.value1.toVar();
+ const v2 = this.value2.toVar();
+
+ for ( let c = 0; c < columns; c ++ ) {
+
+ const column1 = isMatrix ? v1.element( c ) : v1;
+ const column2 = isMatrix ? v2.element( c ) : v2;
+
+ this.writeColumn( c, toVec4( column1, columnLength ), toVec4( column2, columnLength ) );
+
+ }
+
+ return undefined;
+
+ }
+
+}
+
+// One shared renderer per backend, reused across all tests in the suite.
+// `'webgpu'` is the real WebGPU backend (when available); `'webgl'` forces
+// WebGPURenderer's WebGL2 fallback backend (`forceWebGL: true`), so the same
+// TSL expression can be checked against both -- useful since not every node
+// is (or needs to be) WebGL2-compatible, but most math/color/BRDF nodes are.
+const BACKEND_OPTIONS = {
+ webgpu: {},
+ webgl: { forceWebGL: true }
+};
+
+// Cached per backend: a real renderer once `init()` succeeds, or `null` once
+// it's failed -- some CI images can support one backend but not the other
+// (confirmed in practice: WebGPU-via-software-Vulkan can work while a forced
+// WebGL2 context comes back `null` in the same environment, or vice versa),
+// so availability is detected empirically per backend rather than assumed.
+const sharedRenderers = {};
+
+async function getSharedRenderer( backend ) {
+
+ if ( BACKEND_OPTIONS[ backend ] === undefined ) {
+
+ throw new Error( `gpuTest: unknown backend "${ backend }" -- expected one of ${ Object.keys( BACKEND_OPTIONS ).join( ', ' ) }.` );
+
+ }
+
+ if ( sharedRenderers[ backend ] === undefined ) {
+
+ const renderer = new WebGPURenderer( { antialias: false, ...BACKEND_OPTIONS[ backend ] } );
+
+ try {
+
+ await renderer.init();
+ sharedRenderers[ backend ] = renderer;
+
+ } catch ( error ) {
+
+ console.warn( `gpu-test-utils: "${ backend }" backend is not available in this environment (${ error.message }) -- skipping tests that require it.` );
+ sharedRenderers[ backend ] = null;
+
+ }
+
+ }
+
+ return sharedRenderers[ backend ];
+
+}
+
+function diffComponents( actual, expected, tolerance, kind ) {
+
+ const diffs = [];
+
+ for ( let i = 0; i < expected.length; i ++ ) {
+
+ const a = actual[ i ];
+ const e = expected[ i ];
+ let delta, bad;
+
+ if ( kind === Kind.CLOSE_REL ) {
+
+ delta = Math.abs( a - e ) / Math.max( Math.abs( a ), Math.abs( e ), 1e-12 );
+ bad = delta > tolerance;
+
+ } else if ( kind === Kind.CLOSE_ABS ) {
+
+ delta = Math.abs( a - e );
+ bad = delta > tolerance;
+
+ } else if ( kind === Kind.GT ) {
+
+ bad = ! ( a > e );
+ delta = e - a;
+
+ } else if ( kind === Kind.GE ) {
+
+ bad = ! ( a >= e );
+ delta = e - a;
+
+ } else if ( kind === Kind.LT ) {
+
+ bad = ! ( a < e );
+ delta = a - e;
+
+ } else if ( kind === Kind.LE ) {
+
+ bad = ! ( a <= e );
+ delta = a - e;
+
+ } else { // EQ
+
+ delta = Math.abs( a - e );
+ bad = a !== e;
+
+ }
+
+ diffs.push( { index: i, actual: a, expected: e, delta, bad } );
+
+ }
+
+ return diffs;
+
+}
+
+const RELATIONAL_OPS = {
+ [ Kind.GT ]: '>',
+ [ Kind.GE ]: '>=',
+ [ Kind.LT ]: '<',
+ [ Kind.LE ]: '<='
+};
+
+// Per-component labels for diagnostic output: swizzle letters for a plain
+// vector/scalar (`x`, `y`, ...), or `col0.x`-style labels for a matrix, whose
+// flattened component order is column-major (matching `resolveLayout`).
+function componentLabels( columns, columnLength ) {
+
+ if ( columns === 1 ) return SWIZZLE.slice( 0, columnLength );
+
+ const labels = [];
+
+ for ( let c = 0; c < columns; c ++ ) {
+
+ for ( let r = 0; r < columnLength; r ++ ) {
+
+ labels.push( `col${ c }.${ SWIZZLE[ r ] }` );
+
+ }
+
+ }
+
+ return labels;
+
+}
+
+function describeExpectation( d, kind, tolerance ) {
+
+ const op = RELATIONAL_OPS[ kind ];
+
+ if ( op !== undefined ) {
+
+ return `expected ${ op } ${ d.expected.toFixed( 6 ) }, got ${ d.actual.toFixed( 6 ) }`;
+
+ }
+
+ const toleranceSuffix = kind === Kind.EQ ? '' : ` (Δ${ d.delta.toFixed( 6 ) }, tolerance ${ tolerance })`;
+ return `expected ${ d.expected.toFixed( 6 ) }, got ${ d.actual.toFixed( 6 ) }${ toleranceSuffix }`;
+
+}
+
+function formatFailure( label, diffs, tolerance, kind, labels ) {
+
+ const bad = diffs.filter( ( d ) => d.bad );
+
+ if ( bad.length === 0 ) return null;
+
+ if ( diffs.length === 1 ) {
+
+ return `${ label }: ${ describeExpectation( bad[ 0 ], kind, tolerance ) }`;
+
+ }
+
+ const lines = bad.map( ( d ) => ` [${ labels[ d.index ] }]: ${ describeExpectation( d, kind, tolerance ) }` );
+ const reason = RELATIONAL_OPS[ kind ] !== undefined ? 'fail the comparison' : `exceed tolerance ${ tolerance }`;
+
+ return `${ label }: ${ bad.length }/${ diffs.length } components ${ reason }\n${ lines.join( '\n' ) }`;
+
+}
+
+function evaluateAssertion( assert, actual, expected, meta ) {
+
+ const labels = componentLabels( meta.columns, meta.columnLength );
+ const diffs = diffComponents( actual, expected, meta.tolerance, meta.kind );
+ const failure = formatFailure( meta.label, diffs, meta.tolerance, meta.kind, labels );
+
+ assert.pushResult( {
+ result: failure === null,
+ actual: actual.length === 1 ? actual[ 0 ] : actual,
+ expected: expected.length === 1 ? expected[ 0 ] : expected,
+ message: failure || `${ meta.label }: OK`
+ } );
+
+}
+
+// Builds the assertion object handed to test bodies -- names follow QUnit's
+// own assertion terminology (`equal`/`notEqual` style: full words, no
+// abbreviations) for the relational checks, alongside the tolerance-based
+// `closeAbs`/`closeRel` pair. `makeNode(kind, tolerance)` returns a function
+// that creates and registers an AssertWriteNode for one (value1, value2)
+// pair; each concrete TSL entry point (gpuTest / gpuFuzzTest) supplies its
+// own `makeNode` since the two differ in how a row is selected/populated.
+function buildAssertAPI( makeNode ) {
+
+ return {
+ eq: ( actual, expected, message ) => makeNode( Kind.EQ, 0, message )( actual, expected ),
+ closeAbs: ( actual, expected, tolerance, message ) => makeNode( Kind.CLOSE_ABS, tolerance, message )( actual, expected ),
+ closeRel: ( actual, expected, tolerance, message ) => makeNode( Kind.CLOSE_REL, tolerance, message )( actual, expected ),
+ greaterThan: ( actual, expected, message ) => makeNode( Kind.GT, 0, message )( actual, expected ),
+ greaterThanOrEqual: ( actual, expected, message ) => makeNode( Kind.GE, 0, message )( actual, expected ),
+ lessThan: ( actual, expected, message ) => makeNode( Kind.LT, 0, message )( actual, expected ),
+ lessThanOrEqual: ( actual, expected, message ) => makeNode( Kind.LE, 0, message )( actual, expected )
+ };
+
+}
+
+// Registers one QUnit.test per requested backend. When only one backend is
+// requested (the default), the test name is left untouched; with more than
+// one, each gets a `[backend]` suffix so failures say which backend failed.
+// Backend availability is detected at runtime (see getSharedRenderer) rather
+// than assumed, so no static "skip this backend" flag is needed here.
+function declareTest( name, backends, run ) {
+
+ for ( const backend of backends ) {
+
+ const testName = backends.length > 1 ? `${ name } [${ backend }]` : name;
+
+ QUnit.test( testName, async ( assert ) => {
+
+ const renderer = await getSharedRenderer( backend );
+
+ if ( renderer === null ) {
+
+ // Availability can only be known after an async init() call,
+ // so this can't use QUnit.skip() (which needs to be decided
+ // at registration time) -- a clearly-labeled soft pass is the
+ // practical equivalent: it never fails the build, and the
+ // console.warn from getSharedRenderer explains why.
+ assert.ok( true, `SKIPPED: "${ backend }" backend is not available in this environment.` );
+ return;
+
+ }
+
+ await run( assert, renderer );
+
+ } );
+
+ }
+
+}
+
+async function readBuffer( renderer, buffer ) {
+
+ return new Float32Array( await renderer.getArrayBufferAsync( buffer.value ) );
+
+}
+
+// Detects a silent kernel-build/dispatch failure that would otherwise be
+// invisible to the CPU-side harness. Confirmed root cause: when a compute
+// pipeline fails to build (e.g. invalid WGSL/GLSL generated from a genuine
+// TSL bug -- a `NaN` literal reaching a shader source position, say), the
+// backing renderer (`WebGPURenderer`, on both its native WebGPU and WebGL2
+// fallback paths) reports the failure asynchronously via a console
+// error/"uncaptured device error" -- it does **not** reject the
+// `computeAsync()` promise or throw. The dispatch that would have written
+// this suite's `actual`/`expected` buffers simply never runs, so BOTH sides
+// read back as their zero-initialized default -- not just `actual`, since
+// `expected` is itself computed and written by the same (now-unrun) kernel,
+// not supplied as a precomputed CPU-side constant. Every assertion in that
+// kernel then silently compares `0` against `0` and passes, regardless of
+// what it actually claimed to check -- confirmed by deliberately reproducing
+// the exact shape of the original `pcurve()`/`sinc()` compile-failure bugs:
+// a `gpuTest` block whose 3 assertions expected `0`, `0.5` and `1` reported
+// all 3 as passing, because all 3 read back `0` against `0`.
+//
+// The fix: an unconditional "canary" write, in the *same* kernel, of a
+// value that can't arise from an uninitialized (zero) buffer by chance. If
+// the kernel fails to build, the canary is never written either (a shader
+// module either compiles as a whole or not at all), and its absence proves
+// the whole dispatch never ran -- so the caller can fail loudly instead of
+// silently trusting a buffer that only *looks* like a real 0-vs-0 pass.
+//
+// The canary deliberately reuses one extra reserved row of a caller-supplied
+// buffer (rather than allocating a dedicated buffer, which tipped some call
+// sites over the WebGL2 fallback's tight simultaneously-bound-buffer budget)
+// -- see `gpuTest`'s own comment for where that row lives and why. Currently
+// only wired into `gpuTest`; `gpuFuzzTest` doesn't use this yet -- extending
+// its `count`-many-instances/multi-site addressing to reserve a row safely
+// turned out riskier (a native-WebGPU-only `getArrayBufferAsync()` failure,
+// "Cannot read properties of undefined (reading 'size')", specifically when
+// reusing an unused site/instance for the canary) and needs a more careful
+// follow-up pass rather than shipping alongside this fix.
+const CANARY_VALUE = 12345.6789;
+
+function writeCanary( buffer, row ) {
+
+ If( instanceIndex.equal( row ), () => {
+
+ buffer.element( instanceIndex ).assign( vec4( CANARY_VALUE, 0, 0, 0 ) );
+
+ } );
+
+}
+
+// Takes an already-read `Float32Array` (not a buffer + renderer) rather than
+// reading the canary's own host buffer a second time -- confirmed the WebGL2
+// fallback's storage buffers are effectively single-read: a second
+// `getArrayBufferAsync()` call against a buffer already read once earlier in
+// the same test fails outright (`getBufferSubData: no buffer`). Every caller
+// here already needs to read that same buffer's full data right afterwards
+// anyway, so read once and pass the array to both.
+function assertKernelRan( assert, data, row, name, kind = 'gpuTest' ) {
+
+ const value = data[ row * 4 ];
+ const ran = Math.abs( value - CANARY_VALUE ) < 1e-3;
+
+ if ( ! ran ) {
+
+ assert.pushResult( {
+ result: false,
+ actual: value,
+ expected: CANARY_VALUE,
+ message: `${ kind } "${ name }": the compute kernel never ran (canary value missing -- ` +
+ `got ${ value }, expected ${ CANARY_VALUE }). This means the shader failed to build ` +
+ '(invalid WGSL/GLSL, most likely a NaN or otherwise malformed literal reaching ' +
+ 'generated shader source) -- check the console for the underlying WebGPU/WebGL compile ' +
+ 'error. Every assertion below would otherwise have silently compared a never-written 0 ' +
+ 'against a never-written 0 and passed regardless of what it claimed to check.'
+ } );
+
+ }
+
+ return ran;
+
+}
+
+/**
+ * Declare a GPU-native test suite. `buildFn` runs once (at graph-build time)
+ * and receives `{ assert }` with `assert.eq/closeAbs/closeRel(actual, expected,
+ * [tolerance], [message])`.
+ *
+ * Addressing strategy: a single shared `actual`/`expected` buffer pair, sized
+ * `maxAssertions * MAX_COLUMNS` rows -- every assertion reserves a fixed
+ * `MAX_COLUMNS`-row stride (`row = assertionIndex * MAX_COLUMNS`), and only
+ * uses as many of those rows as its resolved type needs (1 for a scalar/
+ * vector, up to `MAX_COLUMNS` for a mat3/mat4). Each row is still written
+ * only via the bare `instanceIndex` node, guarded by
+ * `If( instanceIndex.equal( row ), ... )`, per the file header's WebGL2
+ * addressing constraint. This costs a larger (but cheap: still just 2
+ * buffers total) dispatch -- `maxAssertions * MAX_COLUMNS` compute
+ * invocations -- rather than more simultaneously-bound buffers, which is
+ * the resource that's actually scarce on the WebGL2 fallback.
+ *
+ * Supports scalars, vecN and mat3/mat4 -- see the file header's "Matrix
+ * support" section.
+ *
+ * `maxAssertions` (default 64) sizes the backing buffers and dispatch count
+ * generously so callers don't need to pre-count assertions; override via the
+ * options object if a suite exceeds it.
+ *
+ * `backends` (default `[ 'webgpu', 'webgl' ]`) selects which renderer
+ * backend(s) to run the suite against -- both by default, so a backend
+ * regression can't slip by unnoticed; narrow it (e.g. `[ 'webgpu' ]`) only
+ * for a node that's deliberately WebGPU-only.
+ */
+export function gpuTest( name, buildFn, { maxAssertions = 64, backends = [ 'webgpu', 'webgl' ] } = {} ) {
+
+ declareTest( name, backends, async ( assert, renderer ) => {
+
+ const nodes = [];
+ const totalRows = maxAssertions * MAX_COLUMNS;
+ const actualBuffer = instancedArray( totalRows, 'vec4' );
+ const expectedBuffer = instancedArray( totalRows, 'vec4' );
+
+ // The *last* row is reserved for the "did this kernel actually run"
+ // canary (see `writeCanary`/`assertKernelRan`) rather than a growing
+ // the buffers/dispatch by one extra slot -- growing them (tried
+ // first) silently overran the WebGL2 fallback's transform-feedback
+ // vertex buffer sizing and crashed the whole test page, not just
+ // this one test. Reusing an existing row costs exactly one
+ // assertion's worth of capacity out of `maxAssertions`, with no
+ // buffer-size or dispatch-count change at all.
+ const canaryRow = totalRows - 1;
+ const maxUsableAssertions = maxAssertions - 1;
+
+ const kernel = Fn( () => {
+
+ // TSL callbacks passed to Fn()/If() are not guaranteed to run
+ // exactly once -- three.js builds nodes across multiple stages
+ // (setup/analyze/generate), and this callback can be invoked more
+ // than once during that process. `nodes` is a side effect *outside*
+ // the node graph (CPU-side bookkeeping: "which buffer row does
+ // assertion N read back from"), so it has to be reset on every
+ // invocation of this callback rather than accumulated across
+ // invocations -- otherwise a second (or later) pass appends
+ // duplicate/phantom entries whose `baseRow` never matches what the
+ // *final* pass actually generated (confirmed: this is exactly what
+ // broke the `gpuFuzzTest` canary attempt below -- see
+ // tsl-unit-test-findings.md). Resetting here is safe specifically
+ // because rebuilding is idempotent: each invocation walks buildFn
+ // in the same order and recomputes identical baseRow values from
+ // scratch, so only the *last* invocation's bookkeeping needs to
+ // survive to match the actually-compiled kernel.
+ nodes.length = 0;
+
+ writeCanary( actualBuffer, canaryRow );
+
+ const makeNode = ( kind, tolerance, message ) => ( value1, value2 ) => {
+
+ if ( nodes.length >= maxUsableAssertions ) {
+
+ throw new Error( `gpuTest "${ name }": exceeded maxAssertions (${ maxAssertions }); pass a higher value via options.` );
+
+ }
+
+ const baseRow = nodes.length * MAX_COLUMNS;
+
+ const writeColumn = ( c, actualVec4, expectedVec4 ) => {
+
+ If( instanceIndex.equal( baseRow + c ), () => {
+
+ actualBuffer.element( instanceIndex ).assign( actualVec4 );
+ expectedBuffer.element( instanceIndex ).assign( expectedVec4 );
+
+ } );
+
+ };
+
+ const node = new AssertWriteNode( writeColumn, value1, value2 );
+ node.kind = kind;
+ node.tolerance = tolerance;
+ node.message = message;
+ node.baseRow = baseRow;
+
+ nodes.push( node );
+
+ Stack( node );
+
+ };
+
+ buildFn( { assert: buildAssertAPI( makeNode ) } );
+
+ } )().compute( totalRows );
+
+ await renderer.computeAsync( kernel );
+
+ const actualData = await readBuffer( renderer, actualBuffer );
+ const expectedData = await readBuffer( renderer, expectedBuffer );
+
+ if ( ! assertKernelRan( assert, actualData, canaryRow, name ) ) return;
+
+ nodes.forEach( ( node, id ) => {
+
+ const actual = [];
+ const expected = [];
+
+ for ( let c = 0; c < node.resolvedColumns; c ++ ) {
+
+ const base = ( node.baseRow + c ) * 4;
+ actual.push( ...actualData.slice( base, base + node.resolvedColumnLength ) );
+ expected.push( ...expectedData.slice( base, base + node.resolvedColumnLength ) );
+
+ }
+
+ evaluateAssertion( assert, actual, expected, {
+ label: node.message || `${ name } #${ id }`,
+ kind: node.kind,
+ tolerance: node.tolerance,
+ columns: node.resolvedColumns,
+ columnLength: node.resolvedColumnLength
+ } );
+
+ } );
+
+ } );
+
+}
+
+/**
+ * Declare a GPU-native fuzz/property test: `buildFn` runs once (at graph-build
+ * time) and is dispatched over `count` invocations, receiving `{ instanceIndex,
+ * assert }` so it can derive per-invocation inputs from `instanceIndex` and
+ * assert on them the same way as `gpuTest`.
+ *
+ * Addressing strategy: each call site gets its own dedicated set of
+ * column-buffers (1 by default, up to `maxColumnsPerSite` -- see below), all
+ * written *unconditionally* at the bare `instanceIndex` (which already
+ * uniquely addresses "this fuzz instance", so no `If`-guard is needed here,
+ * unlike `gpuTest`).
+ *
+ * `maxSitesPerInstance` (default 4) bounds how many `assert.*` calls buildFn
+ * may make per invocation. `maxColumnsPerSite` (default 1) bounds how wide a
+ * single site's value may be: 1 covers every scalar/vector type; pass 3 or 4
+ * to allow a site to assert on a mat3/mat4. Both knobs spend the same scarce
+ * resource -- WebGL2's fallback guarantees only a handful of simultaneously-
+ * bound output buffers (spec minimum is 4) -- so `maxSitesPerInstance *
+ * maxColumnsPerSite` total buffer pairs is a real budget, not just memory;
+ * widen `maxColumnsPerSite` only for the sites that actually need it by
+ * splitting matrix-asserting fuzz tests out from scalar/vector-heavy ones
+ * rather than raising it globally.
+ *
+ * In practice the default of 4 sites is itself already close to some
+ * software/CI WebGL2 implementations' actual (not just spec-guaranteed)
+ * ceiling -- confirmed empirically: 3 simultaneous sites silently corrupted
+ * one site's readback (to all-zero) on this project's sandboxed lavapipe
+ * WebGL2 fallback, while 2 sites worked reliably. If a fuzz test with
+ * several `assert.*` calls starts seeing implausible all-zero failures,
+ * try splitting it into multiple smaller `gpuFuzzTest` calls before
+ * suspecting the node under test.
+ *
+ * `backends` (default `[ 'webgpu', 'webgl' ]`) -- see `gpuTest`.
+ */
+export function gpuFuzzTest( name, count, buildFn, { maxSitesPerInstance = 4, maxColumnsPerSite = 1, backends = [ 'webgpu', 'webgl' ] } = {} ) {
+
+ declareTest( name, backends, async ( assert, renderer ) => {
+
+ const nodes = []; // one entry per call site (not per instance)
+ const actualBuffers = []; // actualBuffers[site][column]
+ const expectedBuffers = [];
+
+ // The *last* fuzz instance is reserved for the "did this kernel
+ // actually run" canary -- see `gpuTest`'s matching comment for why
+ // this reuses an existing slot instead of growing the dispatch/
+ // buffers by one (that overran the WebGL2 fallback's vertex buffer
+ // sizing and crashed the whole page). This costs one real fuzz
+ // instance out of `count`, negligible for the counts fuzz tests use.
+ const canaryRow = count - 1;
+ const maxUsableCount = count - 1;
+
+ for ( let site = 0; site < maxSitesPerInstance; site ++ ) {
+
+ const actualColumns = [];
+ const expectedColumns = [];
+
+ for ( let c = 0; c < maxColumnsPerSite; c ++ ) {
+
+ actualColumns.push( instancedArray( count, 'vec4' ) );
+ expectedColumns.push( instancedArray( count, 'vec4' ) );
+
+ }
+
+ actualBuffers.push( actualColumns );
+ expectedBuffers.push( expectedColumns );
+
+ }
+
+ const kernel = Fn( () => {
+
+ writeCanary( actualBuffers[ 0 ][ 0 ], canaryRow );
+
+ const makeNode = ( kind, tolerance, message ) => ( value1, value2 ) => {
+
+ const site = nodes.length;
+
+ if ( site >= maxSitesPerInstance ) {
+
+ throw new Error( `gpuFuzzTest "${ name }": exceeded maxSitesPerInstance (${ maxSitesPerInstance }); pass a higher value via options.` );
+
+ }
+
+ const writeColumn = ( c, actualVec4, expectedVec4 ) => {
+
+ if ( c >= maxColumnsPerSite ) {
+
+ throw new Error( `gpuFuzzTest "${ name }": a value at site ${ site } needs column ${ c + 1 }, more than maxColumnsPerSite (${ maxColumnsPerSite }); raise that option to assert on wider values (e.g. mat3/mat4).` );
+
+ }
+
+ actualBuffers[ site ][ c ].element( instanceIndex ).assign( actualVec4 );
+ expectedBuffers[ site ][ c ].element( instanceIndex ).assign( expectedVec4 );
+
+ };
+
+ const node = new AssertWriteNode( writeColumn, value1, value2 );
+ node.kind = kind;
+ node.tolerance = tolerance;
+ node.message = message;
+ node.site = site;
+
+ nodes.push( node );
+ Stack( node );
+
+ };
+
+ // Guarded so the canary's reserved last instance never also runs
+ // buildFn's real per-instance writes (which would overwrite the
+ // canary value it just wrote, and would be an out-of-bounds
+ // concern if any buffer were sized tighter than `count`).
+ //
+ // Critically, THIS callback -- not the outer Fn() callback -- is
+ // the one TSL invokes more than once during node-graph
+ // construction (confirmed empirically: nesting `buildFn` inside
+ // an extra `If()` like this is exactly what triggers a second
+ // build pass over it here). `nodes`/`site` numbering is a side
+ // effect outside the node graph, so it has to be reset at the
+ // start of *this specific* callback -- not just once at the top
+ // of the outer Fn() -- or a second pass appends a phantom
+ // duplicate site whose buffer the final compiled kernel never
+ // actually writes (confirmed root cause of the "Cannot read
+ // properties of undefined (reading 'size')" failure recorded in
+ // tsl-unit-test-findings.md). Resetting here is safe because
+ // rebuilding is idempotent: each invocation walks buildFn in the
+ // same order and recomputes identical site numbers from scratch.
+ If( instanceIndex.lessThan( maxUsableCount ), () => {
+
+ nodes.length = 0;
+
+ buildFn( { instanceIndex, assert: buildAssertAPI( makeNode ) } );
+
+ } );
+
+ } )().compute( count );
+
+ await renderer.computeAsync( kernel );
+
+ // One set of column-buffers per site (not shared across sites, unlike
+ // gpuTest's shared buffer), so read each site's data back once and
+ // slice per instance below. Site 0 is read unconditionally (even if
+ // buildFn made zero assert.* calls) since that's the canary's host
+ // buffer, and assertKernelRan needs its already-read data -- see
+ // assertKernelRan's own comment for why it must not be read twice.
+ const actualData = [];
+ const expectedData = [];
+
+ actualData[ 0 ] = await Promise.all( actualBuffers[ 0 ].map( ( buf ) => readBuffer( renderer, buf ) ) );
+ expectedData[ 0 ] = await Promise.all( expectedBuffers[ 0 ].map( ( buf ) => readBuffer( renderer, buf ) ) );
+
+ if ( ! assertKernelRan( assert, actualData[ 0 ][ 0 ], canaryRow, name, 'gpuFuzzTest' ) ) return;
+
+ for ( const node of nodes ) {
+
+ if ( actualData[ node.site ] === undefined ) {
+
+ actualData[ node.site ] = await Promise.all( actualBuffers[ node.site ].map( ( buf ) => readBuffer( renderer, buf ) ) );
+ expectedData[ node.site ] = await Promise.all( expectedBuffers[ node.site ].map( ( buf ) => readBuffer( renderer, buf ) ) );
+
+ }
+
+ }
+
+ for ( let instance = 0; instance < maxUsableCount; instance ++ ) {
+
+ for ( const node of nodes ) {
+
+ const actual = [];
+ const expected = [];
+
+ for ( let c = 0; c < node.resolvedColumns; c ++ ) {
+
+ const base = instance * 4;
+ actual.push( ...actualData[ node.site ][ c ].slice( base, base + node.resolvedColumnLength ) );
+ expected.push( ...expectedData[ node.site ][ c ].slice( base, base + node.resolvedColumnLength ) );
+
+ }
+
+ const label = node.message ? `${ name } #${ instance }: ${ node.message }` : `${ name } #${ instance }`;
+
+ evaluateAssertion( assert, actual, expected, {
+ label,
+ kind: node.kind,
+ tolerance: node.tolerance,
+ columns: node.resolvedColumns,
+ columnLength: node.resolvedColumnLength
+ } );
+
+ }
+
+ }
+
+ } );
+
+}
diff --git a/test/unit/puppeteer.unit.js b/test/unit/puppeteer.unit.js
index e0de114fa5064b..94941b1018ee8b 100644
--- a/test/unit/puppeteer.unit.js
+++ b/test/unit/puppeteer.unit.js
@@ -40,9 +40,9 @@ const captureConsole = ( page ) => {
page.on( 'console', async ( message ) => {
const type = message.type().toUpperCase();
- const color = colors[ type ] || blue;
+ const printer = colors[ type ] || blue;
- color( `${type}: ${message.text()} ` );
+ printer( `${type}: ${message.text()} ` );
} );
@@ -107,6 +107,53 @@ function main() {
captureConsole( page );
+ // Collect per-test failure details (name + assertion messages) so
+ // they can be printed below -- QUnit doesn't log these to the console
+ // itself, and `window._QUnitStats` (used below) only holds aggregate
+ // counts. Installed before navigation since QUnit starts running as
+ // soon as the test page's scripts load.
+ await page.evaluateOnNewDocument( () => {
+
+ window._QUnitFailures = [];
+
+ const install = () => {
+
+ window.QUnit.on( 'testEnd', ( test ) => {
+
+ if ( test.status === 'failed' ) {
+
+ window._QUnitFailures.push( {
+ name: test.fullName.join( ' > ' ),
+ messages: test.errors.map( ( e ) => e.message )
+ } );
+
+ }
+
+ } );
+
+ };
+
+ if ( window.QUnit ) {
+
+ install();
+
+ } else {
+
+ const interval = setInterval( () => {
+
+ if ( window.QUnit ) {
+
+ clearInterval( interval );
+ install();
+
+ }
+
+ }, 1 );
+
+ }
+
+ } );
+
const testUrl = `http://localhost:${port}/test/unit/${testPage}`;
// Load the test page
@@ -130,12 +177,21 @@ function main() {
} );
+ const failures = await page.evaluate( () => window._QUnitFailures );
+
white( `1..${stats.total}` );
green( `# pass ${stats.passed}` );
yellow( `# skip ${stats.skipped}` );
cyan( `# todo ${stats.todo}` );
red( `# fail ${stats.failed}` );
+ for ( const failure of failures ) {
+
+ red( `not ok - ${failure.name}` );
+ for ( const message of failure.messages ) red( ` ${message.replace( /\n/g, '\n ' )}` );
+
+ }
+
// Keep the process running if testing in headful mode, otherwise close it.
testMode === 'headless' && close( stats.failed > 0 ? 1 : 0 );
diff --git a/test/unit/three.addons.unit.js b/test/unit/three.addons.unit.js
index 8f5d15137d5f11..16b4c117a7a8e9 100644
--- a/test/unit/three.addons.unit.js
+++ b/test/unit/three.addons.unit.js
@@ -15,3 +15,4 @@ import './addons/loaders/SPZLoader.tests.js';
import './addons/loaders/USDLoader.tests.js';
import './addons/exporters/USDZExporter.tests.js';
import './addons/tsl/WebGLNodesHandler.tests.js';
+import './addons/tsl/GPUTest.tests.js';