From c30a490025e12e539f87274fb075af3ccea64bb3 Mon Sep 17 00:00:00 2001 From: mrdoob Date: Sat, 22 Aug 2026 09:35:08 +0900 Subject: [PATCH 1/5] Backends: Don't scale render target viewports by the pixel ratio. (#34333) Co-authored-by: Claude Fable 5 --- src/renderers/webgl-fallback/WebGLBackend.js | 4 ++-- src/renderers/webgpu/WebGPUBackend.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) 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 ++ ) { From c7cf2d06d2b8b34f3f91ef39132c236cead28847 Mon Sep 17 00:00:00 2001 From: mrdoob Date: Sat, 22 Aug 2026 09:57:46 +0900 Subject: [PATCH 2/5] Nodes: Remove top-level side effects for better tree-shaking. (#34332) Co-authored-by: Claude Fable 5 --- src/nodes/accessors/BuiltinNode.js | 2 +- src/nodes/accessors/Texture3DNode.js | 2 +- src/nodes/display/BumpMapNode.js | 4 +- src/nodes/display/ColorAdjustment.js | 2 +- src/nodes/display/PassNode.js | 34 +++-- src/nodes/fog/Fog.js | 8 +- src/nodes/gpgpu/AtomicFunctionNode.js | 66 +++++++-- src/nodes/gpgpu/BarrierNode.js | 2 +- src/nodes/gpgpu/SubgroupFunctionNode.js | 184 +++++++++++++++++++----- src/nodes/math/BitcountNode.js | 22 ++- src/nodes/math/OperatorNode.js | 4 +- src/nodes/shapes/Shapes.js | 2 +- src/nodes/utils/PostProcessingUtils.js | 4 +- 13 files changed, 261 insertions(+), 75 deletions(-) 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 ) ) ); From 577ca661eebc8b130362e95c56555a624c99e4da Mon Sep 17 00:00:00 2001 From: William Candillon Date: Sat, 22 Aug 2026 03:07:41 +0200 Subject: [PATCH 3/5] WebGPURenderer: Dispose render objects when the renderer is disposed. (#34327) Co-authored-by: Michael Herzog --- src/renderers/common/RenderObjects.js | 27 ++++++++++++++++++++++++--- src/renderers/common/Renderer.js | 3 ++- 2 files changed, 26 insertions(+), 4 deletions(-) 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 ); From b2c4d3c642f2ec385e75ce75f48e9e4bc1b144c8 Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Sat, 22 Aug 2026 10:40:37 +0900 Subject: [PATCH 4/5] Updated builds. --- build/three.core.js | 1446 +++++++++++++---------------------- build/three.module.js | 18 +- build/three.tsl.js | 97 +-- build/three.webgpu.js | 419 +++++++--- build/three.webgpu.nodes.js | 419 +++++++--- 5 files changed, 1233 insertions(+), 1166 deletions(-) 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 ++ ) { From 5132c1fa0b7fb5eba6df3d2c577d9ecf5025ac45 Mon Sep 17 00:00:00 2001 From: Ben Houston Date: Fri, 21 Aug 2026 22:44:30 -0400 Subject: [PATCH 5/5] GPU-native unit tests for TSL (#34331) --- test/unit/addons/tsl/GPUTest.tests.js | 52 ++ test/unit/addons/tsl/gpu-test-utils.js | 885 +++++++++++++++++++++++++ test/unit/puppeteer.unit.js | 60 +- test/unit/three.addons.unit.js | 1 + 4 files changed, 996 insertions(+), 2 deletions(-) create mode 100644 test/unit/addons/tsl/GPUTest.tests.js create mode 100644 test/unit/addons/tsl/gpu-test-utils.js 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';