Răsfoiți Sursa

Updated builds.

Mugen87 2 luni în urmă
părinte
comite
cb7251095a
100 a modificat fișierele cu 2558 adăugiri și 477 ștergeri
  1. 1 1
      build/three.cjs
  2. 1 1
      build/three.core.js
  3. 0 0
      build/three.core.min.js
  4. 489 51
      build/three.webgpu.js
  5. 0 0
      build/three.webgpu.min.js
  6. 489 51
      build/three.webgpu.nodes.js
  7. 0 0
      build/three.webgpu.nodes.min.js
  8. 6 1
      docs/index.html
  9. 3 0
      docs/llms-full.txt
  10. 2 3
      docs/pages/AmmoPhysics.html
  11. 3 5
      docs/pages/AmmoPhysics.html.md
  12. 0 32
      docs/pages/AnimationClip.html
  13. 0 16
      docs/pages/AnimationClip.html.md
  14. 3 0
      docs/pages/ArcballControls.html
  15. 2 0
      docs/pages/ArcballControls.html.md
  16. 2 5
      docs/pages/BezierInterpolant.html
  17. 1 4
      docs/pages/BezierInterpolant.html.md
  18. 6 7
      docs/pages/BloomNode.html
  19. 8 10
      docs/pages/BloomNode.html.md
  20. 5 6
      docs/pages/BufferAttributeNode.html
  21. 6 8
      docs/pages/BufferAttributeNode.html.md
  22. 16 0
      docs/pages/CSMFrustum.html
  23. 9 0
      docs/pages/CSMFrustum.html.md
  24. 120 0
      docs/pages/ClusteredLighting.html
  25. 74 0
      docs/pages/ClusteredLighting.html.md
  26. 86 0
      docs/pages/ClusteredLightsNode.html
  27. 47 0
      docs/pages/ClusteredLightsNode.html.md
  28. 3 4
      docs/pages/Color.html
  29. 5 7
      docs/pages/Color.html.md
  30. 0 1
      docs/pages/ConditionalNode.html
  31. 0 2
      docs/pages/ConditionalNode.html.md
  32. 2 3
      docs/pages/FlipNode.html
  33. 3 5
      docs/pages/FlipNode.html.md
  34. 139 1
      docs/pages/GLSLNodeBuilder.html
  35. 69 1
      docs/pages/GLSLNodeBuilder.html.md
  36. 2 3
      docs/pages/GPUComputationRenderer.html
  37. 4 6
      docs/pages/GPUComputationRenderer.html.md
  38. 46 1
      docs/pages/IESSpotLightNode.html
  39. 27 1
      docs/pages/IESSpotLightNode.html.md
  40. 2 3
      docs/pages/ImageBitmapLoader.html
  41. 4 6
      docs/pages/ImageBitmapLoader.html.md
  42. 82 26
      docs/pages/Info.html
  43. 52 26
      docs/pages/Info.html.md
  44. 2 0
      docs/pages/LightProbeGrid.html
  45. 2 0
      docs/pages/LightProbeGrid.html.md
  46. 1 1
      docs/pages/LightProbeGridHelper.html
  47. 1 1
      docs/pages/LightProbeGridHelper.html.md
  48. 3 4
      docs/pages/LoopNode.html
  49. 5 7
      docs/pages/LoopNode.html.md
  50. 4 5
      docs/pages/Matrix2.html
  51. 6 8
      docs/pages/Matrix2.html.md
  52. 5 6
      docs/pages/Matrix3.html
  53. 7 9
      docs/pages/Matrix3.html.md
  54. 6 7
      docs/pages/Matrix4.html
  55. 8 10
      docs/pages/Matrix4.html.md
  56. 3 1
      docs/pages/MeshLambertMaterial.html
  57. 1 1
      docs/pages/MeshLambertMaterial.html.md
  58. 3 1
      docs/pages/MeshMatcapMaterial.html
  59. 1 1
      docs/pages/MeshMatcapMaterial.html.md
  60. 3 1
      docs/pages/MeshNormalMaterial.html
  61. 1 1
      docs/pages/MeshNormalMaterial.html.md
  62. 3 1
      docs/pages/MeshPhongMaterial.html
  63. 1 1
      docs/pages/MeshPhongMaterial.html.md
  64. 3 1
      docs/pages/MeshStandardMaterial.html
  65. 1 1
      docs/pages/MeshStandardMaterial.html.md
  66. 3 1
      docs/pages/MeshToonMaterial.html
  67. 1 1
      docs/pages/MeshToonMaterial.html.md
  68. 32 1
      docs/pages/NodeBuilder.html
  69. 19 1
      docs/pages/NodeBuilder.html.md
  70. 6 4
      docs/pages/PMREMGenerator.html
  71. 2 2
      docs/pages/PMREMGenerator.html.md
  72. 2 3
      docs/pages/PointsNodeMaterial.html
  73. 3 5
      docs/pages/PointsNodeMaterial.html.md
  74. 35 0
      docs/pages/RapierPhysics.html
  75. 18 0
      docs/pages/RapierPhysics.html.md
  76. 22 0
      docs/pages/Reflector.html
  77. 10 0
      docs/pages/Reflector.html.md
  78. 21 1
      docs/pages/RenderTarget.html
  79. 14 1
      docs/pages/RenderTarget.html.md
  80. 10 0
      docs/pages/Renderer.html
  81. 4 0
      docs/pages/Renderer.html.md
  82. 0 14
      docs/pages/SSAAPassNode.html
  83. 0 12
      docs/pages/SSAAPassNode.html.md
  84. 4 5
      docs/pages/STLLoader.html
  85. 6 8
      docs/pages/STLLoader.html.md
  86. 45 0
      docs/pages/SVGLoader.html
  87. 22 0
      docs/pages/SVGLoader.html.md
  88. 8 14
      docs/pages/ShapePath.html
  89. 5 5
      docs/pages/ShapePath.html.md
  90. 4 5
      docs/pages/Sky.html
  91. 6 8
      docs/pages/Sky.html.md
  92. 4 5
      docs/pages/SkyMesh.html
  93. 6 8
      docs/pages/SkyMesh.html.md
  94. 2 2
      docs/pages/StackNode.html
  95. 2 2
      docs/pages/StackNode.html.md
  96. 175 0
      docs/pages/StorageTexture3DNode.html
  97. 89 0
      docs/pages/StorageTexture3DNode.html.md
  98. 56 0
      docs/pages/StorageTextureNode.html
  99. 28 0
      docs/pages/StorageTextureNode.html.md
  100. 5 4
      docs/pages/StructTypeNode.html

+ 1 - 1
build/three.cjs

@@ -55661,7 +55661,7 @@ class Raycaster {
 
 		} else if ( camera.isOrthographicCamera ) {
 
-			this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
+			this.ray.origin.set( coords.x, coords.y, camera.projectionMatrix.elements[ 14 ] ).unproject( camera ); // set origin in plane of camera
 			this.ray.direction.set( 0, 0, -1 ).transformDirection( camera.matrixWorld );
 			this.camera = camera;
 

+ 1 - 1
build/three.core.js

@@ -55681,7 +55681,7 @@ class Raycaster {
 
 		} else if ( camera.isOrthographicCamera ) {
 
-			this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
+			this.ray.origin.set( coords.x, coords.y, camera.projectionMatrix.elements[ 14 ] ).unproject( camera ); // set origin in plane of camera
 			this.ray.direction.set( 0, 0, -1 ).transformDirection( camera.matrixWorld );
 			this.camera = camera;
 

Fișier diff suprimat deoarece este prea mare
+ 0 - 0
build/three.core.min.js


+ 489 - 51
build/three.webgpu.js

@@ -4938,6 +4938,20 @@ class PropertyNode extends Node {
 
 	}
 
+	getNodeType( builder ) {
+
+		const nodeType = super.getNodeType( builder );
+
+		if ( nodeType === 'output' ) {
+
+			return builder.getOutputType();
+
+		}
+
+		return nodeType;
+
+	}
+
 	customCacheKey() {
 
 		return hashString( this.type + ':' + ( this.name || '' ) + ':' + ( this.varying ? '1' : '0' ) );
@@ -5159,7 +5173,7 @@ const shininess = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Shininess
  * @tsl
  * @type {PropertyNode<vec4>}
  */
-const output = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec4', 'Output' );
+const output = /*@__PURE__*/ nodeImmutable( PropertyNode, 'output', 'Output' );
 
 /**
  * TSL object that represents the shader variable `dashSize`.
@@ -8138,12 +8152,12 @@ addMethodChaining( 'rand', rand );
  * Represents a logical `if/else` statement. Can be used as an alternative
  * to the `If()`/`Else()` syntax.
  *
- * The corresponding TSL `select()` looks like so:
+ * The `select()` method is called in a chaining fashion on a condition. The parameter nodes of `select()`
+ * determine the outcome of the entire statement.
+ *
  * ```js
  * velocity = position.greaterThanEqual( limit ).select( velocity.negate(), velocity );
  * ```
- * The `select()` method is called in a chaining fashion on a condition. The parameter nodes of `select()`
- * determine the outcome of the entire statement.
  *
  * @augments Node
  */
@@ -13012,7 +13026,7 @@ class TextureNode extends UniformNode {
 	/**
 	 * Gathers four texels from the texture.
 	 *
-	 * @param {[Node<int>]} gatherNode - The index of the channel to read. This must be in range [0, 3] and a compile-time constant.
+	 * @param {Node<int>} gatherNode - The index of the channel to read. This must be in range [0, 3] and a compile-time constant.
 	 * @return {TextureNode} A texture node representing the texture sample.
 	 */
 	gather( gatherNode = 0 ) {
@@ -21238,7 +21252,7 @@ class NodeMaterial extends Material {
 
 			if ( fragmentNode.isOutputStructNode !== true ) {
 
-				fragmentNode = vec4( fragmentNode );
+				fragmentNode = fragmentNode.convert( builder.getOutputType() );
 
 			}
 
@@ -22260,7 +22274,11 @@ class Line2NodeMaterial extends NodeMaterial {
 
 			const a = cameraProjectionMatrix.element( 2 ).element( 2 ); // 3nd entry in 3th column
 			const b = cameraProjectionMatrix.element( 3 ).element( 2 ); // 3nd entry in 4th column
-			const nearEstimate = b.mul( -0.5 ).div( a );
+
+			// we need different nearEstimate formula for reversed and default depth buffer
+			// a is positive with a reversed depth buffer so it can be used for controlling the code flow
+
+			const nearEstimate = a.greaterThan( 0 ).select( b.negate().div( a.add( 1 ) ), b.mul( -0.5 ).div( a ) );
 
 			const alpha = nearEstimate.sub( start.z ).div( end.z.sub( start.z ) );
 
@@ -35264,7 +35282,7 @@ class OutputStructNode extends Node {
 
 		for ( let i = 0; i < members.length; i ++ ) {
 
-			const snippet = members[ i ].build( builder );
+			const snippet = members[ i ].build( builder, nodeData.membersLayout[ i ].type );
 
 			builder.addLineFlowCode( `${ structPrefix }m${ i } = ${ snippet }`, this );
 
@@ -35593,8 +35611,9 @@ class MRTNode extends OutputStructNode {
 		for ( const name in outputNodes ) {
 
 			const index = getTextureIndex( textures, name );
+			const type = builder.getOutputType( index );
 
-			members[ index ] = vec4( outputNodes[ name ] );
+			members[ index ] = outputNodes[ name ].convert( type );
 
 		}
 
@@ -40062,7 +40081,7 @@ class PassNode extends TempNode {
 		 * A dictionary holding the internal result textures.
 		 *
 		 * @private
-		 * @type {{ output: Texture, depth?: DepthTexture }}
+		 * @type {{ output: Texture, depth: ?DepthTexture }}
 		 */
 		this._textures = {
 			output: renderTarget.texture
@@ -45160,6 +45179,11 @@ const pointShadowFilter = /*@__PURE__*/ Fn( ( { filterFn, depthTexture, shadowCo
 			dp = viewZToReversedPerspectiveDepth( viewZ.negate(), shadowCameraNear, shadowCameraFar );
 			dp.subAssign( bias );
 
+		} else if ( builder.renderer.logarithmicDepthBuffer ) {
+
+			dp = viewZToLogarithmicDepth( viewZ.negate(), shadowCameraNear, shadowCameraFar );
+			dp.addAssign( bias );
+
 		} else {
 
 			dp = viewZToPerspectiveDepth( viewZ.negate(), shadowCameraNear, shadowCameraFar );
@@ -50423,6 +50447,61 @@ class NodeBuilder {
 
 	}
 
+	/**
+	 * Returns the type of the color output based on the renderer's render target.
+	 *
+	 * @param {number} [index=0] - The index of the render target texture.
+	 * @return {string} The type.
+	 */
+	getOutputType( index = 0 ) {
+
+		let type = 'vec4';
+
+		const renderTarget = this.renderer.getRenderTarget();
+
+		if ( renderTarget !== null ) {
+
+			const renderTargetType = renderTarget.textures[ index ].type;
+			const renderTargetFormat = renderTarget.textures[ index ].format;
+
+			let typeStr = 'vec';
+
+			if ( renderTargetType === IntType ) {
+
+				typeStr = 'ivec';
+
+			} else if ( renderTargetType === UnsignedIntType ) {
+
+				typeStr = 'uvec';
+
+			}
+
+			if ( renderTargetFormat === RedFormat || renderTargetFormat === RedIntegerFormat ) {
+
+				if ( renderTargetType === IntType ) type = 'int';
+				else if ( renderTargetType === UnsignedIntType ) type = 'uint';
+				else type = 'float';
+
+			} else if ( renderTargetFormat === RGFormat || renderTargetFormat === RGIntegerFormat ) {
+
+				type = `${ typeStr }2`;
+
+			} else if ( renderTargetFormat === RGBFormat || renderTargetFormat === RGBIntegerFormat ) {
+
+				type = `${ typeStr }3`;
+
+			} else {
+
+				type = `${ typeStr }4`;
+
+			}
+
+		}
+
+		return type;
+
+	}
+
 	/**
 	 * Returns the output struct name which is required by
 	 * {@link OutputStructNode}.
@@ -51357,12 +51436,10 @@ class NodeBuilder {
 
 		const type = texture.type;
 
-		if ( texture.isDataTexture ) {
-
-			if ( type === IntType ) return 'int';
-			if ( type === UnsignedIntType ) return 'uint';
+		if ( texture.isDepthTexture === true ) return 'float';
 
-		}
+		if ( type === IntType ) return 'int';
+		if ( type === UnsignedIntType ) return 'uint';
 
 		return 'float';
 
@@ -55562,6 +55639,13 @@ class ClippingContext {
 		 */
 		this.shadowPass = false;
 
+		/**
+		 * The view matrix.
+		 *
+		 * @type {Matrix4}
+		 */
+		this.viewMatrix = new Matrix4();
+
 		/**
 		 * The view normal matrix.
 		 *
@@ -55600,11 +55684,11 @@ class ClippingContext {
 
 		if ( parentContext !== null ) {
 
+			this.viewMatrix = parentContext.viewMatrix;
 			this.viewNormalMatrix = parentContext.viewNormalMatrix;
 			this.clippingGroupContexts = parentContext.clippingGroupContexts;
 
 			this.shadowPass = parentContext.shadowPass;
-			this.viewMatrix = parentContext.viewMatrix;
 
 		}
 
@@ -55647,8 +55731,8 @@ class ClippingContext {
 	updateGlobal( scene, camera ) {
 
 		this.shadowPass = ( scene.overrideMaterial !== null && scene.overrideMaterial.isShadowPassMaterial );
-		this.viewMatrix = camera.matrixWorldInverse;
 
+		this.viewMatrix.copy( camera.matrixWorldInverse );
 		this.viewNormalMatrix.getNormalMatrix( this.viewMatrix );
 
 	}
@@ -56203,9 +56287,7 @@ const _contextNodeLib = /*@__PURE__*/ new WeakMap();
 
 /**
  * The XR manager is built on top of the WebXR Device API to
- * manage XR sessions with `WebGPURenderer`.
- *
- * XR is currently only supported with a WebGL 2 backend.
+ * manage XR sessions with renderer backends.
  *
  * @augments EventDispatcher
  */
@@ -56264,6 +56346,7 @@ class XRManager extends EventDispatcher {
 		 */
 		this._cameraL = new PerspectiveCamera();
 		this._cameraL.viewport = new Vector4();
+		this._cameraL.matrixWorldAutoUpdate = false;
 
 		/**
 		 * Represents the camera for the right eye.
@@ -56273,6 +56356,7 @@ class XRManager extends EventDispatcher {
 		 */
 		this._cameraR = new PerspectiveCamera();
 		this._cameraR.viewport = new Vector4();
+		this._cameraR.matrixWorldAutoUpdate = false;
 
 		/**
 		 * A list of cameras used for rendering the XR views.
@@ -56361,6 +56445,7 @@ class XRManager extends EventDispatcher {
 		 * @readonly
 		 */
 		this._supportsGlBinding = typeof XRWebGLBinding !== 'undefined';
+		this._supportsWebGPUBinding = typeof globalThis.XRGPUBinding !== 'undefined';
 
 		/**
 		 * Helper function to create native WebXR Layer.
@@ -56406,6 +56491,15 @@ class XRManager extends EventDispatcher {
 		 */
 		this._currentPixelRatio = null;
 
+		/**
+		 * The renderer's sample count before XR temporarily overrides it.
+		 *
+		 * @private
+		 * @type {?number}
+		 * @default null
+		 */
+		this._currentSamples = null;
+
 		/**
 		 * The current size of the renderer's canvas
 		 * in logical pixel unit.
@@ -56521,6 +56615,16 @@ class XRManager extends EventDispatcher {
 		 */
 		this._glBinding = null;
 
+		/**
+		 * A reference to the current XR WebGPU binding.
+		 *
+		 * @private
+		 * @type {?XRGPUBinding}
+		 * @default null
+		 */
+
+		this._webgpuBinding = null;
+
 		/**
 		 * A reference to the current XR projection layer.
 		 *
@@ -56624,16 +56728,10 @@ class XRManager extends EventDispatcher {
 	/**
 	 * Returns the foveation value.
 	 *
-	 * @return {number|undefined} The foveation value. Returns `undefined` if no base or projection layer is defined.
+	 * @return {number|undefined} The foveation value.
 	 */
 	getFoveation() {
 
-		if ( this._glProjLayer === null && this._glBaseLayer === null ) {
-
-			return undefined;
-
-		}
-
 		return this._foveation;
 
 	}
@@ -56860,6 +56958,203 @@ class XRManager extends EventDispatcher {
 
 	}
 
+	/**
+	 * Returns the current XR WebGPU binding.
+	 *
+	 * Creates a new binding if needed and the browser is
+	 * capable of doing so.
+	 *
+	 * @return {?XRGPUBinding} The XR WebGPU binding. Returns `null` if one cannot be created.
+	 */
+	getWebGPUBinding() {
+
+		if ( this._webgpuBinding === null && this._supportsWebGPUBinding ) {
+
+			this._webgpuBinding = new globalThis.XRGPUBinding( this._session, this._renderer.backend.device );
+
+		}
+
+		return this._webgpuBinding;
+
+	}
+
+	/**
+	 * Returns whether the current XR session is using WebGPU.
+	 *
+	 * @private
+	 * @return {boolean} Whether the current session uses the WebGPU backend and the `webgpu` session feature.
+	 */
+	_isWebGPUSession() {
+
+		return this._renderer.backend.isWebGPUBackend === true &&
+			this._session !== null &&
+			this._session.enabledFeatures.includes( 'webgpu' );
+
+	}
+
+	/**
+	 * Validates the current WebGPU XR session requirements.
+	 *
+	 * @private
+	 */
+	_validateWebGPUSession() {
+
+		const renderer = this._renderer;
+
+		if ( renderer.backend.isWebGPUBackend !== true ) return;
+
+		if ( this._session.enabledFeatures.includes( 'webgpu' ) === false ) {
+
+			throw new Error( 'THREE.XRManager: WebGPU XR sessions require the "webgpu" session feature. Use VRButtonGPU/XRButton with "webgpu" enabled or use a WebGL backend.' );
+
+		}
+
+		if ( renderer.samples > 0 ) {
+
+			warnOnce( 'THREE.XRManager: WebGPU XR does not support MSAA yet. Disabling MSAA for this XR session.' );
+
+			if ( this._currentSamples === null ) this._currentSamples = renderer.samples;
+			renderer._samples = 0;
+
+		}
+
+	}
+
+	/**
+	 * Initializes the WebGPU XR projection layer and render target.
+	 *
+	 * @private
+	 * @async
+	 * @param {XRSession} session - The XR session.
+	 * @return {Promise<void>}
+	 */
+	async _initWebGPUSession( session ) {
+
+		const webgpuBinding = this.getWebGPUBinding();
+		const glProjLayer = webgpuBinding.createProjectionLayer( {
+			colorFormat: webgpuBinding.getPreferredColorFormat(),
+			depthStencilFormat: 'depth24plus'
+		} );
+
+		this._glProjLayer = glProjLayer;
+
+		session.updateRenderState( { layers: [ glProjLayer ] } );
+
+		this._referenceSpace = await session.requestReferenceSpace( this.getReferenceSpaceType() );
+
+		this._xrRenderTarget = new RenderTarget( glProjLayer.textureWidth, glProjLayer.textureHeight, {
+			depth: 2,
+			minFilter: LinearFilter,
+			magFilter: LinearFilter,
+			depthBuffer: true,
+			multiview: false,
+			useArrayDepthTexture: true,
+			samples: 0
+		} );
+
+		this._xrRenderTarget.texture.isArrayTexture = true;
+
+		if ( this._useMultiviewIfPossible === true ) {
+
+			warnOnce( 'THREE.XRManager: WebGPU XR does not support multiview yet. Disabling multiview for this XR session.' );
+
+		}
+
+		this._useMultiview = false;
+
+	}
+
+	/**
+	 * Releases WebGPU XR resources associated with the current session.
+	 *
+	 * @private
+	 */
+	_disposeWebGPUSession() {
+
+		const renderer = this._renderer;
+		const xrRenderTarget = this._xrRenderTarget;
+
+		if ( xrRenderTarget === null || renderer.backend.isWebGPUBackend !== true ) return;
+
+		// XR textures are external (from XRGPUBinding), so clear cached state before disposal.
+		const backend = renderer.backend;
+		const texturesModule = renderer._textures;
+
+		const renderTargetData = backend.get ? backend.get( xrRenderTarget ) : null;
+		if ( renderTargetData ) {
+
+			renderTargetData.descriptors = undefined;
+
+		}
+
+		const deleteResource = ( resource ) => {
+
+			if ( resource === null || resource === undefined ) return;
+
+			if ( backend.delete ) backend.delete( resource );
+			if ( texturesModule.delete ) texturesModule.delete( resource );
+
+		};
+
+		for ( let i = 0; i < xrRenderTarget.textures.length; i ++ ) {
+
+			deleteResource( xrRenderTarget.textures[ i ] );
+
+		}
+
+		deleteResource( xrRenderTarget.depthTexture );
+		deleteResource( xrRenderTarget );
+
+		if ( renderer._renderContexts && renderer._renderContexts.dispose ) {
+
+			renderer._renderContexts.dispose();
+
+		}
+
+		xrRenderTarget.dispose();
+
+	}
+
+	/**
+	 * Collects WebGPU XR sub-image data for the current frame.
+	 *
+	 * @private
+	 * @param {Array<XRView>} views - The XR views for the current pose.
+	 * @return {{colorTexture:?GPUTexture, viewDescriptors:Array<Object>, viewports:Array<XRViewport>}} The WebGPU XR view data.
+	 */
+	_getWebGPUViewData( views ) {
+
+		const webgpuBinding = this.getWebGPUBinding();
+		const viewData = {
+			colorTexture: null,
+			viewDescriptors: [],
+			viewports: []
+		};
+
+		for ( let i = 0; i < views.length; i ++ ) {
+
+			const gpuSubImage = webgpuBinding.getViewSubImage( this._glProjLayer, views[ i ] );
+
+			if ( viewData.colorTexture === null ) {
+
+				viewData.colorTexture = gpuSubImage.colorTexture;
+
+			}
+
+			viewData.viewports.push( gpuSubImage.viewport );
+
+			if ( gpuSubImage.getViewDescriptor ) {
+
+				viewData.viewDescriptors.push( gpuSubImage.getViewDescriptor() );
+
+			}
+
+		}
+
+		return viewData;
+
+	}
+
 	/**
 	 * Returns the current XR frame.
 	 *
@@ -57173,22 +57468,16 @@ class XRManager extends EventDispatcher {
 	async setSession( session ) {
 
 		const renderer = this._renderer;
-		const backend = renderer.backend;
 
-		if ( session !== null && backend.isWebGPUBackend === true ) {
+		if ( renderer.initialized === false ) await renderer.init();
 
-			throw new Error( 'THREE.XRManager: XR is currently not supported with a WebGPU backend. Use WebGL by passing "{ forceWebGL: true }" to the constructor of the renderer.' );
-
-		}
+		this._gl = renderer.getContext();
+		const gl = this._gl;
 
 		this._session = session;
 
 		if ( session !== null ) {
 
-			this._gl = renderer.getContext();
-			const gl = this._gl;
-			const attributes = gl.getContextAttributes();
-
 			session.addEventListener( 'select', this._onSessionEvent );
 			session.addEventListener( 'selectstart', this._onSessionEvent );
 			session.addEventListener( 'selectend', this._onSessionEvent );
@@ -57198,7 +57487,7 @@ class XRManager extends EventDispatcher {
 			session.addEventListener( 'end', this._onSessionEnd );
 			session.addEventListener( 'inputsourceschange', this._onInputSourcesChange );
 
-			await backend.makeXRCompatible();
+			this._validateWebGPUSession();
 
 			this._currentPixelRatio = renderer.getPixelRatio();
 			renderer.getSize( this._currentSize );
@@ -57209,7 +57498,11 @@ class XRManager extends EventDispatcher {
 
 			//
 
-			if ( this._supportsLayers === true ) {
+			if ( this._isWebGPUSession() ) {
+
+				await this._initWebGPUSession( session );
+
+			} else if ( this._supportsLayers === true ) {
 
 				// default path using XRProjectionLayer
 
@@ -57217,6 +57510,10 @@ class XRManager extends EventDispatcher {
 				let depthType = null;
 				let glDepthFormat = null;
 
+				const attributes = gl.getContextAttributes();
+				await renderer.backend.makeXRCompatible();
+				this.setFoveation( this.getFoveation() );
+
 				if ( renderer.depth ) {
 
 					glDepthFormat = renderer.stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT24;
@@ -57299,6 +57596,8 @@ class XRManager extends EventDispatcher {
 			} else {
 
 				// fallback to XRWebGLLayer
+				await renderer.backend.makeXRCompatible();
+				this.setFoveation( this.getFoveation() );
 
 				const layerInit = {
 					antialias: renderer.currentSamples > 0,
@@ -57336,8 +57635,6 @@ class XRManager extends EventDispatcher {
 
 			//
 
-			this.setFoveation( this.getFoveation() );
-
 			renderer._animation.setAnimationLoop( this._onAnimationFrame );
 			renderer._animation.setContext( session );
 			renderer._animation.start();
@@ -57635,13 +57932,23 @@ function onSessionEnd() {
 	this._currentDepthNear = null;
 	this._currentDepthFar = null;
 
+	if ( this._currentSamples !== null ) {
+
+		renderer._samples = this._currentSamples;
+		this._currentSamples = null;
+
+	}
+
 	// restore framebuffer/rendering state
 
 	renderer._resetXRState();
 
+	this._disposeWebGPUSession();
+
 	this._session = null;
 	this._xrRenderTarget = null;
 	this._glBinding = null;
+	this._webgpuBinding = null;
 	this._glBaseLayer = null;
 	this._glProjLayer = null;
 
@@ -57825,7 +58132,9 @@ function onAnimationFrame( time, frame ) {
 
 		const views = pose.views;
 
-		if ( this._glBaseLayer !== null ) {
+		const webgpuViewData = this._isWebGPUSession() ? this._getWebGPUViewData( views ) : null;
+
+		if ( this._glBaseLayer !== null && webgpuViewData === null ) {
 
 			backend.setXRTarget( glBaseLayer.framebuffer );
 
@@ -57848,8 +58157,13 @@ function onAnimationFrame( time, frame ) {
 
 			let viewport;
 
-			if ( this._supportsLayers === true ) {
+			if ( webgpuViewData !== null ) {
+
+				viewport = webgpuViewData.viewports[ i ];
+
+			} else if ( this._supportsLayers === true ) {
 
+				// WebGL path: Use XRWebGLBinding
 				const glSubImage = this._glBinding.getViewSubImage( this._glProjLayer, view );
 				viewport = glSubImage.viewport;
 
@@ -57877,6 +58191,7 @@ function onAnimationFrame( time, frame ) {
 				camera = new PerspectiveCamera();
 				camera.layers.enable( i );
 				camera.viewport = new Vector4();
+				camera.matrixWorldAutoUpdate = false;
 				this._cameras[ i ] = camera;
 
 			}
@@ -57902,6 +58217,16 @@ function onAnimationFrame( time, frame ) {
 
 		}
 
+		if ( webgpuViewData !== null && webgpuViewData.colorTexture !== null ) {
+
+			backend.setXRRenderTargetTextures(
+				this._xrRenderTarget,
+				webgpuViewData.colorTexture,
+				webgpuViewData.viewDescriptors
+			);
+
+		}
+
 		renderer.setOutputRenderTarget( this._xrRenderTarget );
 
 		const frameBufferTarget = renderer._getFrameBufferTarget();
@@ -64293,7 +64618,7 @@ ${ flowData.code }
 
 		if ( shaderStage === 'fragment' && outputSnippet.length === 0 ) {
 
-			outputSnippet.push( 'layout( location = 0 ) out vec4 fragColor;' );
+			outputSnippet.push( `layout( location = 0 ) out ${ this.getOutputType() } fragColor;` );
 
 		}
 
@@ -64851,14 +65176,14 @@ void main() {
 					if ( shaderStage === 'vertex' ) {
 
 						flow += 'gl_Position = ';
-						flow += `${ flowSlotData.result };`;
+						flow += `${ this.format( flowSlotData.result, mainNode.getNodeType( this ), 'vec4' ) };`;
 
 					} else if ( shaderStage === 'fragment' ) {
 
 						if ( ! node.outputNode.isOutputStructNode ) {
 
 							flow += 'fragColor = ';
-							flow += `${ flowSlotData.result };`;
+							flow += `${ this.format( flowSlotData.result, mainNode.getNodeType( this ), this.getOutputType() ) };`;
 
 						}
 
@@ -65142,6 +65467,15 @@ class Backend {
 	 */
 	finishRender( /*renderContext*/ ) {}
 
+	/**
+	 * Sets the XR rendering destination.
+	 *
+	 * Backends that render directly into XR framebuffers can override this hook.
+	 *
+	 * @param {?Object} xrTarget - The XR rendering destination.
+	 */
+	setXRTarget( /*xrTarget*/ ) {}
+
 	/**
 	 * This method is executed at the beginning of a compute call and
 	 * can be used by the backend to prepare the state for upcoming
@@ -75360,6 +75694,13 @@ class WebGPUTextureUtils {
 
 		if ( textureData.initialized ) {
 
+			// Skip creation for external XR textures - they are already set up
+			if ( textureData.externalTexture === true ) {
+
+				return;
+
+			}
+
 			throw new Error( 'WebGPUTextureUtils: Texture already initialized.' );
 
 		}
@@ -79262,7 +79603,7 @@ ${ flowData.code }
 
 						} else {
 
-							let structSnippet = '\t@location( 0 ) color: vec4<f32>';
+							let structSnippet = `\t@location( 0 ) color: ${ this.getType( this.getOutputType() ) }`;
 
 							const builtins = this.getBuiltins( 'output' );
 
@@ -79272,7 +79613,7 @@ ${ flowData.code }
 							stageData.structs += this._getWGSLStruct( 'OutputStruct', structSnippet );
 							stageData.structs += '\nvar<private> output : OutputStruct;';
 
-							flow += `output.color = ${ flowSlotData.result };\n\n\treturn output;`;
+							flow += `output.color = ${ this.format( flowSlotData.result, mainNode.getNodeType( this ), this.getOutputType() ) };\n\n\treturn output;`;
 
 						}
 
@@ -80655,7 +80996,7 @@ class WebGPUBindingUtils {
 
 					}
 
-				} else if ( binding.texture.isDataTexture || binding.texture.isDataArrayTexture || binding.texture.isData3DTexture || binding.texture.isStorageTexture ) {
+				} else {
 
 					const type = binding.texture.type;
 
@@ -82566,7 +82907,8 @@ class WebGPUBackend extends Backend {
 
 			const adapterOptions = {
 				powerPreference: parameters.powerPreference,
-				featureLevel: 'compatibility'
+				featureLevel: 'compatibility',
+				xrCompatible: renderer.xr.enabled
 			};
 
 			const adapter = ( typeof navigator !== 'undefined' ) ? await navigator.gpu.requestAdapter( adapterOptions ) : null;
@@ -82652,6 +82994,25 @@ class WebGPUBackend extends Backend {
 
 	}
 
+	/**
+	 * Registers external GPU textures from `XRGPUBinding` for use in rendering.
+	 *
+	 * @param {RenderTarget} renderTarget - The render target to register the textures for.
+	 * @param {GPUTexture} colorTexture - The shared XR color GPUTexture.
+	 * @param {?Array<Object>} [viewDescriptors=null] - Optional view descriptors, one per XR view.
+	 */
+	setXRRenderTargetTextures( renderTarget, colorTexture, viewDescriptors = null ) {
+
+		this.set( renderTarget.texture, {
+			texture: colorTexture,
+			format: colorTexture.format,
+			externalTexture: true,
+			xrViewDescriptors: viewDescriptors,
+			initialized: true
+		} );
+
+	}
+
 	/**
 	 * A reference to the context.
 	 *
@@ -82827,6 +83188,74 @@ class WebGPUBackend extends Backend {
 
 	}
 
+	/**
+	 * Returns whether the current render context references external textures.
+	 *
+	 * External textures can change every frame, so their descriptors must not be cached.
+	 *
+	 * @private
+	 * @param {RenderContext} renderContext - The render context.
+	 * @return {boolean} Whether the render context uses external textures.
+	 */
+	_hasExternalTexture( renderContext ) {
+
+		const textures = renderContext.textures;
+
+		if ( textures === null ) return false;
+
+		for ( let i = 0; i < textures.length; i ++ ) {
+
+			if ( this.get( textures[ i ] ).externalTexture === true ) return true;
+
+		}
+
+		return false;
+
+	}
+
+	/**
+	 * Creates attachment views for an external texture render target.
+	 *
+	 * @private
+	 * @param {RenderContext} renderContext - The render context.
+	 * @param {Object} textureData - The backend data for the texture.
+	 * @return {Array<Object>} The attachment view descriptors.
+	 */
+	_createExternalTextureViews( renderContext, textureData ) {
+
+		const textureViews = [];
+		const camera = renderContext.camera;
+
+		if ( textureData.xrViewDescriptors && camera !== null && camera.isArrayCamera === true ) {
+
+			for ( let i = 0; i < textureData.xrViewDescriptors.length; i ++ ) {
+
+				textureViews.push( {
+					view: textureData.texture.createView( textureData.xrViewDescriptors[ i ] ),
+					resolveTarget: undefined,
+					depthSlice: undefined
+				} );
+
+			}
+
+		} else {
+
+			textureViews.push( {
+				view: textureData.texture.createView( {
+					dimension: GPUTextureViewDimension.TwoD,
+					baseArrayLayer: renderContext.activeCubeFace,
+					arrayLayerCount: 1
+				} ),
+				resolveTarget: undefined,
+				depthSlice: undefined
+			} );
+
+		}
+
+		return textureViews;
+
+	}
+
 	/**
 	 * Returns the render pass descriptor for the given render context.
 	 *
@@ -82839,13 +83268,15 @@ class WebGPUBackend extends Backend {
 
 		const renderTarget = renderContext.renderTarget;
 		const renderTargetData = this.get( renderTarget );
+		const hasExternalTexture = this._hasExternalTexture( renderContext );
 
 		let descriptors = renderTargetData.descriptors;
 
 		if ( descriptors === undefined ||
 			renderTargetData.width !== renderTarget.width ||
 			renderTargetData.height !== renderTarget.height ||
-			renderTargetData.samples !== renderTarget.samples
+			renderTargetData.samples !== renderTarget.samples ||
+			hasExternalTexture
 		) {
 
 			descriptors = {};
@@ -82857,7 +83288,7 @@ class WebGPUBackend extends Backend {
 		const cacheKey = renderContext.getCacheKey();
 		let descriptorBase = descriptors[ cacheKey ];
 
-		if ( descriptorBase === undefined ) {
+		if ( descriptorBase === undefined || hasExternalTexture ) {
 
 			const textures = renderContext.textures;
 			const textureViews = [];
@@ -82870,6 +83301,13 @@ class WebGPUBackend extends Backend {
 
 				const textureData = this.get( textures[ i ] );
 
+				if ( textureData.externalTexture === true ) {
+
+					textureViews.push( ...this._createExternalTextureViews( renderContext, textureData ) );
+					continue;
+
+				}
+
 				_viewDescriptor.label = `colorAttachment_${ i }`;
 				_viewDescriptor.baseMipLevel = renderContext.activeMipmapLevel;
 				_viewDescriptor.mipLevelCount = 1;

Fișier diff suprimat deoarece este prea mare
+ 0 - 0
build/three.webgpu.min.js


+ 489 - 51
build/three.webgpu.nodes.js

@@ -4938,6 +4938,20 @@ class PropertyNode extends Node {
 
 	}
 
+	getNodeType( builder ) {
+
+		const nodeType = super.getNodeType( builder );
+
+		if ( nodeType === 'output' ) {
+
+			return builder.getOutputType();
+
+		}
+
+		return nodeType;
+
+	}
+
 	customCacheKey() {
 
 		return hashString( this.type + ':' + ( this.name || '' ) + ':' + ( this.varying ? '1' : '0' ) );
@@ -5159,7 +5173,7 @@ const shininess = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Shininess
  * @tsl
  * @type {PropertyNode<vec4>}
  */
-const output = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec4', 'Output' );
+const output = /*@__PURE__*/ nodeImmutable( PropertyNode, 'output', 'Output' );
 
 /**
  * TSL object that represents the shader variable `dashSize`.
@@ -8138,12 +8152,12 @@ addMethodChaining( 'rand', rand );
  * Represents a logical `if/else` statement. Can be used as an alternative
  * to the `If()`/`Else()` syntax.
  *
- * The corresponding TSL `select()` looks like so:
+ * The `select()` method is called in a chaining fashion on a condition. The parameter nodes of `select()`
+ * determine the outcome of the entire statement.
+ *
  * ```js
  * velocity = position.greaterThanEqual( limit ).select( velocity.negate(), velocity );
  * ```
- * The `select()` method is called in a chaining fashion on a condition. The parameter nodes of `select()`
- * determine the outcome of the entire statement.
  *
  * @augments Node
  */
@@ -13012,7 +13026,7 @@ class TextureNode extends UniformNode {
 	/**
 	 * Gathers four texels from the texture.
 	 *
-	 * @param {[Node<int>]} gatherNode - The index of the channel to read. This must be in range [0, 3] and a compile-time constant.
+	 * @param {Node<int>} gatherNode - The index of the channel to read. This must be in range [0, 3] and a compile-time constant.
 	 * @return {TextureNode} A texture node representing the texture sample.
 	 */
 	gather( gatherNode = 0 ) {
@@ -21238,7 +21252,7 @@ class NodeMaterial extends Material {
 
 			if ( fragmentNode.isOutputStructNode !== true ) {
 
-				fragmentNode = vec4( fragmentNode );
+				fragmentNode = fragmentNode.convert( builder.getOutputType() );
 
 			}
 
@@ -22260,7 +22274,11 @@ class Line2NodeMaterial extends NodeMaterial {
 
 			const a = cameraProjectionMatrix.element( 2 ).element( 2 ); // 3nd entry in 3th column
 			const b = cameraProjectionMatrix.element( 3 ).element( 2 ); // 3nd entry in 4th column
-			const nearEstimate = b.mul( -0.5 ).div( a );
+
+			// we need different nearEstimate formula for reversed and default depth buffer
+			// a is positive with a reversed depth buffer so it can be used for controlling the code flow
+
+			const nearEstimate = a.greaterThan( 0 ).select( b.negate().div( a.add( 1 ) ), b.mul( -0.5 ).div( a ) );
 
 			const alpha = nearEstimate.sub( start.z ).div( end.z.sub( start.z ) );
 
@@ -35264,7 +35282,7 @@ class OutputStructNode extends Node {
 
 		for ( let i = 0; i < members.length; i ++ ) {
 
-			const snippet = members[ i ].build( builder );
+			const snippet = members[ i ].build( builder, nodeData.membersLayout[ i ].type );
 
 			builder.addLineFlowCode( `${ structPrefix }m${ i } = ${ snippet }`, this );
 
@@ -35593,8 +35611,9 @@ class MRTNode extends OutputStructNode {
 		for ( const name in outputNodes ) {
 
 			const index = getTextureIndex( textures, name );
+			const type = builder.getOutputType( index );
 
-			members[ index ] = vec4( outputNodes[ name ] );
+			members[ index ] = outputNodes[ name ].convert( type );
 
 		}
 
@@ -40062,7 +40081,7 @@ class PassNode extends TempNode {
 		 * A dictionary holding the internal result textures.
 		 *
 		 * @private
-		 * @type {{ output: Texture, depth?: DepthTexture }}
+		 * @type {{ output: Texture, depth: ?DepthTexture }}
 		 */
 		this._textures = {
 			output: renderTarget.texture
@@ -45160,6 +45179,11 @@ const pointShadowFilter = /*@__PURE__*/ Fn( ( { filterFn, depthTexture, shadowCo
 			dp = viewZToReversedPerspectiveDepth( viewZ.negate(), shadowCameraNear, shadowCameraFar );
 			dp.subAssign( bias );
 
+		} else if ( builder.renderer.logarithmicDepthBuffer ) {
+
+			dp = viewZToLogarithmicDepth( viewZ.negate(), shadowCameraNear, shadowCameraFar );
+			dp.addAssign( bias );
+
 		} else {
 
 			dp = viewZToPerspectiveDepth( viewZ.negate(), shadowCameraNear, shadowCameraFar );
@@ -50423,6 +50447,61 @@ class NodeBuilder {
 
 	}
 
+	/**
+	 * Returns the type of the color output based on the renderer's render target.
+	 *
+	 * @param {number} [index=0] - The index of the render target texture.
+	 * @return {string} The type.
+	 */
+	getOutputType( index = 0 ) {
+
+		let type = 'vec4';
+
+		const renderTarget = this.renderer.getRenderTarget();
+
+		if ( renderTarget !== null ) {
+
+			const renderTargetType = renderTarget.textures[ index ].type;
+			const renderTargetFormat = renderTarget.textures[ index ].format;
+
+			let typeStr = 'vec';
+
+			if ( renderTargetType === IntType ) {
+
+				typeStr = 'ivec';
+
+			} else if ( renderTargetType === UnsignedIntType ) {
+
+				typeStr = 'uvec';
+
+			}
+
+			if ( renderTargetFormat === RedFormat || renderTargetFormat === RedIntegerFormat ) {
+
+				if ( renderTargetType === IntType ) type = 'int';
+				else if ( renderTargetType === UnsignedIntType ) type = 'uint';
+				else type = 'float';
+
+			} else if ( renderTargetFormat === RGFormat || renderTargetFormat === RGIntegerFormat ) {
+
+				type = `${ typeStr }2`;
+
+			} else if ( renderTargetFormat === RGBFormat || renderTargetFormat === RGBIntegerFormat ) {
+
+				type = `${ typeStr }3`;
+
+			} else {
+
+				type = `${ typeStr }4`;
+
+			}
+
+		}
+
+		return type;
+
+	}
+
 	/**
 	 * Returns the output struct name which is required by
 	 * {@link OutputStructNode}.
@@ -51357,12 +51436,10 @@ class NodeBuilder {
 
 		const type = texture.type;
 
-		if ( texture.isDataTexture ) {
-
-			if ( type === IntType ) return 'int';
-			if ( type === UnsignedIntType ) return 'uint';
+		if ( texture.isDepthTexture === true ) return 'float';
 
-		}
+		if ( type === IntType ) return 'int';
+		if ( type === UnsignedIntType ) return 'uint';
 
 		return 'float';
 
@@ -55562,6 +55639,13 @@ class ClippingContext {
 		 */
 		this.shadowPass = false;
 
+		/**
+		 * The view matrix.
+		 *
+		 * @type {Matrix4}
+		 */
+		this.viewMatrix = new Matrix4();
+
 		/**
 		 * The view normal matrix.
 		 *
@@ -55600,11 +55684,11 @@ class ClippingContext {
 
 		if ( parentContext !== null ) {
 
+			this.viewMatrix = parentContext.viewMatrix;
 			this.viewNormalMatrix = parentContext.viewNormalMatrix;
 			this.clippingGroupContexts = parentContext.clippingGroupContexts;
 
 			this.shadowPass = parentContext.shadowPass;
-			this.viewMatrix = parentContext.viewMatrix;
 
 		}
 
@@ -55647,8 +55731,8 @@ class ClippingContext {
 	updateGlobal( scene, camera ) {
 
 		this.shadowPass = ( scene.overrideMaterial !== null && scene.overrideMaterial.isShadowPassMaterial );
-		this.viewMatrix = camera.matrixWorldInverse;
 
+		this.viewMatrix.copy( camera.matrixWorldInverse );
 		this.viewNormalMatrix.getNormalMatrix( this.viewMatrix );
 
 	}
@@ -56203,9 +56287,7 @@ const _contextNodeLib = /*@__PURE__*/ new WeakMap();
 
 /**
  * The XR manager is built on top of the WebXR Device API to
- * manage XR sessions with `WebGPURenderer`.
- *
- * XR is currently only supported with a WebGL 2 backend.
+ * manage XR sessions with renderer backends.
  *
  * @augments EventDispatcher
  */
@@ -56264,6 +56346,7 @@ class XRManager extends EventDispatcher {
 		 */
 		this._cameraL = new PerspectiveCamera();
 		this._cameraL.viewport = new Vector4();
+		this._cameraL.matrixWorldAutoUpdate = false;
 
 		/**
 		 * Represents the camera for the right eye.
@@ -56273,6 +56356,7 @@ class XRManager extends EventDispatcher {
 		 */
 		this._cameraR = new PerspectiveCamera();
 		this._cameraR.viewport = new Vector4();
+		this._cameraR.matrixWorldAutoUpdate = false;
 
 		/**
 		 * A list of cameras used for rendering the XR views.
@@ -56361,6 +56445,7 @@ class XRManager extends EventDispatcher {
 		 * @readonly
 		 */
 		this._supportsGlBinding = typeof XRWebGLBinding !== 'undefined';
+		this._supportsWebGPUBinding = typeof globalThis.XRGPUBinding !== 'undefined';
 
 		/**
 		 * Helper function to create native WebXR Layer.
@@ -56406,6 +56491,15 @@ class XRManager extends EventDispatcher {
 		 */
 		this._currentPixelRatio = null;
 
+		/**
+		 * The renderer's sample count before XR temporarily overrides it.
+		 *
+		 * @private
+		 * @type {?number}
+		 * @default null
+		 */
+		this._currentSamples = null;
+
 		/**
 		 * The current size of the renderer's canvas
 		 * in logical pixel unit.
@@ -56521,6 +56615,16 @@ class XRManager extends EventDispatcher {
 		 */
 		this._glBinding = null;
 
+		/**
+		 * A reference to the current XR WebGPU binding.
+		 *
+		 * @private
+		 * @type {?XRGPUBinding}
+		 * @default null
+		 */
+
+		this._webgpuBinding = null;
+
 		/**
 		 * A reference to the current XR projection layer.
 		 *
@@ -56624,16 +56728,10 @@ class XRManager extends EventDispatcher {
 	/**
 	 * Returns the foveation value.
 	 *
-	 * @return {number|undefined} The foveation value. Returns `undefined` if no base or projection layer is defined.
+	 * @return {number|undefined} The foveation value.
 	 */
 	getFoveation() {
 
-		if ( this._glProjLayer === null && this._glBaseLayer === null ) {
-
-			return undefined;
-
-		}
-
 		return this._foveation;
 
 	}
@@ -56860,6 +56958,203 @@ class XRManager extends EventDispatcher {
 
 	}
 
+	/**
+	 * Returns the current XR WebGPU binding.
+	 *
+	 * Creates a new binding if needed and the browser is
+	 * capable of doing so.
+	 *
+	 * @return {?XRGPUBinding} The XR WebGPU binding. Returns `null` if one cannot be created.
+	 */
+	getWebGPUBinding() {
+
+		if ( this._webgpuBinding === null && this._supportsWebGPUBinding ) {
+
+			this._webgpuBinding = new globalThis.XRGPUBinding( this._session, this._renderer.backend.device );
+
+		}
+
+		return this._webgpuBinding;
+
+	}
+
+	/**
+	 * Returns whether the current XR session is using WebGPU.
+	 *
+	 * @private
+	 * @return {boolean} Whether the current session uses the WebGPU backend and the `webgpu` session feature.
+	 */
+	_isWebGPUSession() {
+
+		return this._renderer.backend.isWebGPUBackend === true &&
+			this._session !== null &&
+			this._session.enabledFeatures.includes( 'webgpu' );
+
+	}
+
+	/**
+	 * Validates the current WebGPU XR session requirements.
+	 *
+	 * @private
+	 */
+	_validateWebGPUSession() {
+
+		const renderer = this._renderer;
+
+		if ( renderer.backend.isWebGPUBackend !== true ) return;
+
+		if ( this._session.enabledFeatures.includes( 'webgpu' ) === false ) {
+
+			throw new Error( 'THREE.XRManager: WebGPU XR sessions require the "webgpu" session feature. Use VRButtonGPU/XRButton with "webgpu" enabled or use a WebGL backend.' );
+
+		}
+
+		if ( renderer.samples > 0 ) {
+
+			warnOnce( 'THREE.XRManager: WebGPU XR does not support MSAA yet. Disabling MSAA for this XR session.' );
+
+			if ( this._currentSamples === null ) this._currentSamples = renderer.samples;
+			renderer._samples = 0;
+
+		}
+
+	}
+
+	/**
+	 * Initializes the WebGPU XR projection layer and render target.
+	 *
+	 * @private
+	 * @async
+	 * @param {XRSession} session - The XR session.
+	 * @return {Promise<void>}
+	 */
+	async _initWebGPUSession( session ) {
+
+		const webgpuBinding = this.getWebGPUBinding();
+		const glProjLayer = webgpuBinding.createProjectionLayer( {
+			colorFormat: webgpuBinding.getPreferredColorFormat(),
+			depthStencilFormat: 'depth24plus'
+		} );
+
+		this._glProjLayer = glProjLayer;
+
+		session.updateRenderState( { layers: [ glProjLayer ] } );
+
+		this._referenceSpace = await session.requestReferenceSpace( this.getReferenceSpaceType() );
+
+		this._xrRenderTarget = new RenderTarget( glProjLayer.textureWidth, glProjLayer.textureHeight, {
+			depth: 2,
+			minFilter: LinearFilter,
+			magFilter: LinearFilter,
+			depthBuffer: true,
+			multiview: false,
+			useArrayDepthTexture: true,
+			samples: 0
+		} );
+
+		this._xrRenderTarget.texture.isArrayTexture = true;
+
+		if ( this._useMultiviewIfPossible === true ) {
+
+			warnOnce( 'THREE.XRManager: WebGPU XR does not support multiview yet. Disabling multiview for this XR session.' );
+
+		}
+
+		this._useMultiview = false;
+
+	}
+
+	/**
+	 * Releases WebGPU XR resources associated with the current session.
+	 *
+	 * @private
+	 */
+	_disposeWebGPUSession() {
+
+		const renderer = this._renderer;
+		const xrRenderTarget = this._xrRenderTarget;
+
+		if ( xrRenderTarget === null || renderer.backend.isWebGPUBackend !== true ) return;
+
+		// XR textures are external (from XRGPUBinding), so clear cached state before disposal.
+		const backend = renderer.backend;
+		const texturesModule = renderer._textures;
+
+		const renderTargetData = backend.get ? backend.get( xrRenderTarget ) : null;
+		if ( renderTargetData ) {
+
+			renderTargetData.descriptors = undefined;
+
+		}
+
+		const deleteResource = ( resource ) => {
+
+			if ( resource === null || resource === undefined ) return;
+
+			if ( backend.delete ) backend.delete( resource );
+			if ( texturesModule.delete ) texturesModule.delete( resource );
+
+		};
+
+		for ( let i = 0; i < xrRenderTarget.textures.length; i ++ ) {
+
+			deleteResource( xrRenderTarget.textures[ i ] );
+
+		}
+
+		deleteResource( xrRenderTarget.depthTexture );
+		deleteResource( xrRenderTarget );
+
+		if ( renderer._renderContexts && renderer._renderContexts.dispose ) {
+
+			renderer._renderContexts.dispose();
+
+		}
+
+		xrRenderTarget.dispose();
+
+	}
+
+	/**
+	 * Collects WebGPU XR sub-image data for the current frame.
+	 *
+	 * @private
+	 * @param {Array<XRView>} views - The XR views for the current pose.
+	 * @return {{colorTexture:?GPUTexture, viewDescriptors:Array<Object>, viewports:Array<XRViewport>}} The WebGPU XR view data.
+	 */
+	_getWebGPUViewData( views ) {
+
+		const webgpuBinding = this.getWebGPUBinding();
+		const viewData = {
+			colorTexture: null,
+			viewDescriptors: [],
+			viewports: []
+		};
+
+		for ( let i = 0; i < views.length; i ++ ) {
+
+			const gpuSubImage = webgpuBinding.getViewSubImage( this._glProjLayer, views[ i ] );
+
+			if ( viewData.colorTexture === null ) {
+
+				viewData.colorTexture = gpuSubImage.colorTexture;
+
+			}
+
+			viewData.viewports.push( gpuSubImage.viewport );
+
+			if ( gpuSubImage.getViewDescriptor ) {
+
+				viewData.viewDescriptors.push( gpuSubImage.getViewDescriptor() );
+
+			}
+
+		}
+
+		return viewData;
+
+	}
+
 	/**
 	 * Returns the current XR frame.
 	 *
@@ -57173,22 +57468,16 @@ class XRManager extends EventDispatcher {
 	async setSession( session ) {
 
 		const renderer = this._renderer;
-		const backend = renderer.backend;
 
-		if ( session !== null && backend.isWebGPUBackend === true ) {
+		if ( renderer.initialized === false ) await renderer.init();
 
-			throw new Error( 'THREE.XRManager: XR is currently not supported with a WebGPU backend. Use WebGL by passing "{ forceWebGL: true }" to the constructor of the renderer.' );
-
-		}
+		this._gl = renderer.getContext();
+		const gl = this._gl;
 
 		this._session = session;
 
 		if ( session !== null ) {
 
-			this._gl = renderer.getContext();
-			const gl = this._gl;
-			const attributes = gl.getContextAttributes();
-
 			session.addEventListener( 'select', this._onSessionEvent );
 			session.addEventListener( 'selectstart', this._onSessionEvent );
 			session.addEventListener( 'selectend', this._onSessionEvent );
@@ -57198,7 +57487,7 @@ class XRManager extends EventDispatcher {
 			session.addEventListener( 'end', this._onSessionEnd );
 			session.addEventListener( 'inputsourceschange', this._onInputSourcesChange );
 
-			await backend.makeXRCompatible();
+			this._validateWebGPUSession();
 
 			this._currentPixelRatio = renderer.getPixelRatio();
 			renderer.getSize( this._currentSize );
@@ -57209,7 +57498,11 @@ class XRManager extends EventDispatcher {
 
 			//
 
-			if ( this._supportsLayers === true ) {
+			if ( this._isWebGPUSession() ) {
+
+				await this._initWebGPUSession( session );
+
+			} else if ( this._supportsLayers === true ) {
 
 				// default path using XRProjectionLayer
 
@@ -57217,6 +57510,10 @@ class XRManager extends EventDispatcher {
 				let depthType = null;
 				let glDepthFormat = null;
 
+				const attributes = gl.getContextAttributes();
+				await renderer.backend.makeXRCompatible();
+				this.setFoveation( this.getFoveation() );
+
 				if ( renderer.depth ) {
 
 					glDepthFormat = renderer.stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT24;
@@ -57299,6 +57596,8 @@ class XRManager extends EventDispatcher {
 			} else {
 
 				// fallback to XRWebGLLayer
+				await renderer.backend.makeXRCompatible();
+				this.setFoveation( this.getFoveation() );
 
 				const layerInit = {
 					antialias: renderer.currentSamples > 0,
@@ -57336,8 +57635,6 @@ class XRManager extends EventDispatcher {
 
 			//
 
-			this.setFoveation( this.getFoveation() );
-
 			renderer._animation.setAnimationLoop( this._onAnimationFrame );
 			renderer._animation.setContext( session );
 			renderer._animation.start();
@@ -57635,13 +57932,23 @@ function onSessionEnd() {
 	this._currentDepthNear = null;
 	this._currentDepthFar = null;
 
+	if ( this._currentSamples !== null ) {
+
+		renderer._samples = this._currentSamples;
+		this._currentSamples = null;
+
+	}
+
 	// restore framebuffer/rendering state
 
 	renderer._resetXRState();
 
+	this._disposeWebGPUSession();
+
 	this._session = null;
 	this._xrRenderTarget = null;
 	this._glBinding = null;
+	this._webgpuBinding = null;
 	this._glBaseLayer = null;
 	this._glProjLayer = null;
 
@@ -57825,7 +58132,9 @@ function onAnimationFrame( time, frame ) {
 
 		const views = pose.views;
 
-		if ( this._glBaseLayer !== null ) {
+		const webgpuViewData = this._isWebGPUSession() ? this._getWebGPUViewData( views ) : null;
+
+		if ( this._glBaseLayer !== null && webgpuViewData === null ) {
 
 			backend.setXRTarget( glBaseLayer.framebuffer );
 
@@ -57848,8 +58157,13 @@ function onAnimationFrame( time, frame ) {
 
 			let viewport;
 
-			if ( this._supportsLayers === true ) {
+			if ( webgpuViewData !== null ) {
+
+				viewport = webgpuViewData.viewports[ i ];
+
+			} else if ( this._supportsLayers === true ) {
 
+				// WebGL path: Use XRWebGLBinding
 				const glSubImage = this._glBinding.getViewSubImage( this._glProjLayer, view );
 				viewport = glSubImage.viewport;
 
@@ -57877,6 +58191,7 @@ function onAnimationFrame( time, frame ) {
 				camera = new PerspectiveCamera();
 				camera.layers.enable( i );
 				camera.viewport = new Vector4();
+				camera.matrixWorldAutoUpdate = false;
 				this._cameras[ i ] = camera;
 
 			}
@@ -57902,6 +58217,16 @@ function onAnimationFrame( time, frame ) {
 
 		}
 
+		if ( webgpuViewData !== null && webgpuViewData.colorTexture !== null ) {
+
+			backend.setXRRenderTargetTextures(
+				this._xrRenderTarget,
+				webgpuViewData.colorTexture,
+				webgpuViewData.viewDescriptors
+			);
+
+		}
+
 		renderer.setOutputRenderTarget( this._xrRenderTarget );
 
 		const frameBufferTarget = renderer._getFrameBufferTarget();
@@ -64293,7 +64618,7 @@ ${ flowData.code }
 
 		if ( shaderStage === 'fragment' && outputSnippet.length === 0 ) {
 
-			outputSnippet.push( 'layout( location = 0 ) out vec4 fragColor;' );
+			outputSnippet.push( `layout( location = 0 ) out ${ this.getOutputType() } fragColor;` );
 
 		}
 
@@ -64851,14 +65176,14 @@ void main() {
 					if ( shaderStage === 'vertex' ) {
 
 						flow += 'gl_Position = ';
-						flow += `${ flowSlotData.result };`;
+						flow += `${ this.format( flowSlotData.result, mainNode.getNodeType( this ), 'vec4' ) };`;
 
 					} else if ( shaderStage === 'fragment' ) {
 
 						if ( ! node.outputNode.isOutputStructNode ) {
 
 							flow += 'fragColor = ';
-							flow += `${ flowSlotData.result };`;
+							flow += `${ this.format( flowSlotData.result, mainNode.getNodeType( this ), this.getOutputType() ) };`;
 
 						}
 
@@ -65142,6 +65467,15 @@ class Backend {
 	 */
 	finishRender( /*renderContext*/ ) {}
 
+	/**
+	 * Sets the XR rendering destination.
+	 *
+	 * Backends that render directly into XR framebuffers can override this hook.
+	 *
+	 * @param {?Object} xrTarget - The XR rendering destination.
+	 */
+	setXRTarget( /*xrTarget*/ ) {}
+
 	/**
 	 * This method is executed at the beginning of a compute call and
 	 * can be used by the backend to prepare the state for upcoming
@@ -75360,6 +75694,13 @@ class WebGPUTextureUtils {
 
 		if ( textureData.initialized ) {
 
+			// Skip creation for external XR textures - they are already set up
+			if ( textureData.externalTexture === true ) {
+
+				return;
+
+			}
+
 			throw new Error( 'WebGPUTextureUtils: Texture already initialized.' );
 
 		}
@@ -79262,7 +79603,7 @@ ${ flowData.code }
 
 						} else {
 
-							let structSnippet = '\t@location( 0 ) color: vec4<f32>';
+							let structSnippet = `\t@location( 0 ) color: ${ this.getType( this.getOutputType() ) }`;
 
 							const builtins = this.getBuiltins( 'output' );
 
@@ -79272,7 +79613,7 @@ ${ flowData.code }
 							stageData.structs += this._getWGSLStruct( 'OutputStruct', structSnippet );
 							stageData.structs += '\nvar<private> output : OutputStruct;';
 
-							flow += `output.color = ${ flowSlotData.result };\n\n\treturn output;`;
+							flow += `output.color = ${ this.format( flowSlotData.result, mainNode.getNodeType( this ), this.getOutputType() ) };\n\n\treturn output;`;
 
 						}
 
@@ -80655,7 +80996,7 @@ class WebGPUBindingUtils {
 
 					}
 
-				} else if ( binding.texture.isDataTexture || binding.texture.isDataArrayTexture || binding.texture.isData3DTexture || binding.texture.isStorageTexture ) {
+				} else {
 
 					const type = binding.texture.type;
 
@@ -82566,7 +82907,8 @@ class WebGPUBackend extends Backend {
 
 			const adapterOptions = {
 				powerPreference: parameters.powerPreference,
-				featureLevel: 'compatibility'
+				featureLevel: 'compatibility',
+				xrCompatible: renderer.xr.enabled
 			};
 
 			const adapter = ( typeof navigator !== 'undefined' ) ? await navigator.gpu.requestAdapter( adapterOptions ) : null;
@@ -82652,6 +82994,25 @@ class WebGPUBackend extends Backend {
 
 	}
 
+	/**
+	 * Registers external GPU textures from `XRGPUBinding` for use in rendering.
+	 *
+	 * @param {RenderTarget} renderTarget - The render target to register the textures for.
+	 * @param {GPUTexture} colorTexture - The shared XR color GPUTexture.
+	 * @param {?Array<Object>} [viewDescriptors=null] - Optional view descriptors, one per XR view.
+	 */
+	setXRRenderTargetTextures( renderTarget, colorTexture, viewDescriptors = null ) {
+
+		this.set( renderTarget.texture, {
+			texture: colorTexture,
+			format: colorTexture.format,
+			externalTexture: true,
+			xrViewDescriptors: viewDescriptors,
+			initialized: true
+		} );
+
+	}
+
 	/**
 	 * A reference to the context.
 	 *
@@ -82827,6 +83188,74 @@ class WebGPUBackend extends Backend {
 
 	}
 
+	/**
+	 * Returns whether the current render context references external textures.
+	 *
+	 * External textures can change every frame, so their descriptors must not be cached.
+	 *
+	 * @private
+	 * @param {RenderContext} renderContext - The render context.
+	 * @return {boolean} Whether the render context uses external textures.
+	 */
+	_hasExternalTexture( renderContext ) {
+
+		const textures = renderContext.textures;
+
+		if ( textures === null ) return false;
+
+		for ( let i = 0; i < textures.length; i ++ ) {
+
+			if ( this.get( textures[ i ] ).externalTexture === true ) return true;
+
+		}
+
+		return false;
+
+	}
+
+	/**
+	 * Creates attachment views for an external texture render target.
+	 *
+	 * @private
+	 * @param {RenderContext} renderContext - The render context.
+	 * @param {Object} textureData - The backend data for the texture.
+	 * @return {Array<Object>} The attachment view descriptors.
+	 */
+	_createExternalTextureViews( renderContext, textureData ) {
+
+		const textureViews = [];
+		const camera = renderContext.camera;
+
+		if ( textureData.xrViewDescriptors && camera !== null && camera.isArrayCamera === true ) {
+
+			for ( let i = 0; i < textureData.xrViewDescriptors.length; i ++ ) {
+
+				textureViews.push( {
+					view: textureData.texture.createView( textureData.xrViewDescriptors[ i ] ),
+					resolveTarget: undefined,
+					depthSlice: undefined
+				} );
+
+			}
+
+		} else {
+
+			textureViews.push( {
+				view: textureData.texture.createView( {
+					dimension: GPUTextureViewDimension.TwoD,
+					baseArrayLayer: renderContext.activeCubeFace,
+					arrayLayerCount: 1
+				} ),
+				resolveTarget: undefined,
+				depthSlice: undefined
+			} );
+
+		}
+
+		return textureViews;
+
+	}
+
 	/**
 	 * Returns the render pass descriptor for the given render context.
 	 *
@@ -82839,13 +83268,15 @@ class WebGPUBackend extends Backend {
 
 		const renderTarget = renderContext.renderTarget;
 		const renderTargetData = this.get( renderTarget );
+		const hasExternalTexture = this._hasExternalTexture( renderContext );
 
 		let descriptors = renderTargetData.descriptors;
 
 		if ( descriptors === undefined ||
 			renderTargetData.width !== renderTarget.width ||
 			renderTargetData.height !== renderTarget.height ||
-			renderTargetData.samples !== renderTarget.samples
+			renderTargetData.samples !== renderTarget.samples ||
+			hasExternalTexture
 		) {
 
 			descriptors = {};
@@ -82857,7 +83288,7 @@ class WebGPUBackend extends Backend {
 		const cacheKey = renderContext.getCacheKey();
 		let descriptorBase = descriptors[ cacheKey ];
 
-		if ( descriptorBase === undefined ) {
+		if ( descriptorBase === undefined || hasExternalTexture ) {
 
 			const textures = renderContext.textures;
 			const textureViews = [];
@@ -82870,6 +83301,13 @@ class WebGPUBackend extends Backend {
 
 				const textureData = this.get( textures[ i ] );
 
+				if ( textureData.externalTexture === true ) {
+
+					textureViews.push( ...this._createExternalTextureViews( renderContext, textureData ) );
+					continue;
+
+				}
+
 				_viewDescriptor.label = `colorAttachment_${ i }`;
 				_viewDescriptor.baseMipLevel = renderContext.activeMipmapLevel;
 				_viewDescriptor.mipLevelCount = 1;

Fișier diff suprimat deoarece este prea mare
+ 0 - 0
build/three.webgpu.nodes.min.js


+ 6 - 1
docs/index.html

@@ -399,6 +399,7 @@
 						<li><a href="StackTrace.html">StackTrace</a></li>
 						<li><a href="StorageArrayElementNode.html">StorageArrayElementNode</a></li>
 						<li><a href="StorageBufferNode.html">StorageBufferNode</a></li>
+						<li><a href="StorageTexture3DNode.html">StorageTexture3DNode</a></li>
 						<li><a href="StorageTextureNode.html">StorageTextureNode</a></li>
 						<li><a href="StructNode.html">StructNode</a></li>
 						<li><a href="StructTypeNode.html">StructTypeNode</a></li>
@@ -633,6 +634,7 @@
 					</ul>
 					<h3>Lighting</h3>
 					<ul>
+						<li><a href="ClusteredLighting.html">ClusteredLighting</a></li>
 						<li><a href="DynamicLighting.html">DynamicLighting</a></li>
 						<li><a href="LightProbeGrid.html">LightProbeGrid</a></li>
 						<li><a href="TiledLighting.html">TiledLighting</a></li>
@@ -881,6 +883,7 @@
 						<li><a href="BilateralBlurNode.html">BilateralBlurNode</a></li>
 						<li><a href="BloomNode.html">BloomNode</a></li>
 						<li><a href="ChromaticAberrationNode.html">ChromaticAberrationNode</a></li>
+						<li><a href="ClusteredLightsNode.html">ClusteredLightsNode</a></li>
 						<li><a href="DenoiseNode.html">DenoiseNode</a></li>
 						<li><a href="DepthOfFieldNode.html">DepthOfFieldNode</a></li>
 						<li><a href="DirectionalLightDataNode.html">DirectionalLightDataNode</a></li>
@@ -1084,6 +1087,7 @@
 						<li><a href="TSL.html#clipSpace">clipSpace</a></li>
 						<li><a href="TSL.html#clipping">clipping</a></li>
 						<li><a href="TSL.html#clippingAlpha">clippingAlpha</a></li>
+						<li><a href="TSL.html#clusteredLights">clusteredLights</a></li>
 						<li><a href="TSL.html#code">code</a></li>
 						<li><a href="TSL.html#colorBleeding">colorBleeding</a></li>
 						<li><a href="TSL.html#colorSpaceToWorking">colorSpaceToWorking</a></li>
@@ -1268,7 +1272,6 @@
 						<li><a href="TSL.html#mix">mix</a></li>
 						<li><a href="TSL.html#mixElement">mixElement</a></li>
 						<li><a href="TSL.html#mod">mod</a></li>
-						<li><a href="TSL.html#modInt">modInt</a></li>
 						<li><a href="TSL.html#modelDirection">modelDirection</a></li>
 						<li><a href="TSL.html#modelNormalMatrix">modelNormalMatrix</a></li>
 						<li><a href="TSL.html#modelPosition">modelPosition</a></li>
@@ -1431,6 +1434,7 @@
 						<li><a href="TSL.html#storageBarrier">storageBarrier</a></li>
 						<li><a href="TSL.html#storageElement">storageElement</a></li>
 						<li><a href="TSL.html#storageTexture">storageTexture</a></li>
+						<li><a href="TSL.html#storageTexture3D">storageTexture3D</a></li>
 						<li><a href="TSL.html#struct">struct</a></li>
 						<li><a href="TSL.html#sub">sub</a></li>
 						<li><a href="TSL.html#subBuild">subBuild</a></li>
@@ -1827,6 +1831,7 @@
 						<li><a href="global.html#setConsoleFunction">setConsoleFunction</a></li>
 						<li><a href="global.html#setProjectionFromUnion">setProjectionFromUnion</a></li>
 						<li><a href="global.html#setQuaternionFromProperEuler">setQuaternionFromProperEuler</a></li>
+						<li><a href="global.html#setupWebGLXRFallback">setupWebGLXRFallback</a></li>
 						<li><a href="global.html#shadowRenderObjectFunction">shadowRenderObjectFunction</a></li>
 						<li><a href="global.html#smootherstep">smootherstep</a></li>
 						<li><a href="global.html#sortedArray">sortedArray</a></li>

+ 3 - 0
docs/llms-full.txt

@@ -1921,6 +1921,7 @@ The following documentation pages are available in markdown format at `https://t
 - [CinquefoilKnot](https://threejs.org/docs/pages/CinquefoilKnot.html.md)
 - [ClippingGroup](https://threejs.org/docs/pages/ClippingGroup.html.md)
 - [Clock](https://threejs.org/docs/pages/Clock.html.md)
+- [ClusteredLighting](https://threejs.org/docs/pages/ClusteredLighting.html.md)
 - [ColladaComposer](https://threejs.org/docs/pages/ColladaComposer.html.md)
 - [ColladaParser](https://threejs.org/docs/pages/ColladaParser.html.md)
 - [ColorConverter](https://threejs.org/docs/pages/ColorConverter.html.md)
@@ -2508,6 +2509,7 @@ The following documentation pages are available in markdown format at `https://t
 - [CSMShadowNode](https://threejs.org/docs/pages/CSMShadowNode.html.md)
 - [ChromaticAberrationNode](https://threejs.org/docs/pages/ChromaticAberrationNode.html.md)
 - [ClippingNode](https://threejs.org/docs/pages/ClippingNode.html.md)
+- [ClusteredLightsNode](https://threejs.org/docs/pages/ClusteredLightsNode.html.md)
 - [CodeNode](https://threejs.org/docs/pages/CodeNode.html.md)
 - [ColorSpaceNode](https://threejs.org/docs/pages/ColorSpaceNode.html.md)
 - [ComputeBuiltinNode](https://threejs.org/docs/pages/ComputeBuiltinNode.html.md)
@@ -2611,6 +2613,7 @@ The following documentation pages are available in markdown format at `https://t
 - [StackNode](https://threejs.org/docs/pages/StackNode.html.md)
 - [StorageArrayElementNode](https://threejs.org/docs/pages/StorageArrayElementNode.html.md)
 - [StorageBufferNode](https://threejs.org/docs/pages/StorageBufferNode.html.md)
+- [StorageTexture3DNode](https://threejs.org/docs/pages/StorageTexture3DNode.html.md)
 - [StorageTextureNode](https://threejs.org/docs/pages/StorageTextureNode.html.md)
 - [StructNode](https://threejs.org/docs/pages/StructNode.html.md)
 - [StructTypeNode](https://threejs.org/docs/pages/StructTypeNode.html.md)

+ 2 - 3
docs/pages/AmmoPhysics.html

@@ -14,11 +14,10 @@
 			<header>
 				<div class="class-description"><p>Can be used to include Ammo.js as a Physics engine into
 <code>three.js</code> apps. Make sure to include <code>ammo.wasm.js</code> first:</p>
+<pre class="prettyprint source"><code>&lt;script src=&quot;jsm/libs/ammo.wasm.js&quot;>&lt;/script>
+</code></pre>
 <p>It is then possible to initialize the API via:</p>
 <pre><code class="language-js">const physics = await AmmoPhysics();
-</code></pre></div>
-				<h2>Code Example</h2>
-				<div translate="no"><pre class="prettyprint source"><code>&lt;script src=&quot;jsm/libs/ammo.wasm.js&quot;>&lt;/script>
 </code></pre></div>
 			</header>
 			<article>

+ 3 - 5
docs/pages/AmmoPhysics.html.md

@@ -2,16 +2,14 @@
 
 Can be used to include Ammo.js as a Physics engine into `three.js` apps. Make sure to include `ammo.wasm.js` first:
 
-It is then possible to initialize the API via:
-
 ```js
-const physics = await AmmoPhysics();
+<script src="jsm/libs/ammo.wasm.js"></script>
 ```
 
-## Code Example
+It is then possible to initialize the API via:
 
 ```js
-<script src="jsm/libs/ammo.wasm.js"></script>
+const physics = await AmmoPhysics();
 ```
 
 ## Import

+ 0 - 32
docs/pages/AnimationClip.html

@@ -305,38 +305,6 @@ array named &quot;animations&quot; property.</p>
 							<dt class="tag-returns"><strong>Returns:</strong> The new animation clip.</dt>
 						</dl>
 					</div>
-					<h3 class="name name-method" id=".parseAnimation" translate="no">.<a href="#.parseAnimation">parseAnimation</a><span class="signature">( animation : <span class="param-type">Object</span>, bones : <span class="param-type">Array.&lt;<a href="Bone.html">Bone</a>></span> )</span><span class="type-signature"> : <a href="AnimationClip.html">AnimationClip</a></span> </h3>
-					<div class="method">
-						<div class="description">
-							<p>Parses the <code>animation.hierarchy</code> format and returns a new animation clip.</p>
-						</div>
-						<table class="params">
-							<tbody>
-								<tr>
-									<td class="name">
-										<strong translate="no">animation</strong>
-									</td>
-									<td class="description last">
-										<p>A serialized animation clip as JSON.</p>
-									</td>
-								</tr>
-								<tr>
-									<td class="name">
-										<strong translate="no">bones</strong>
-									</td>
-									<td class="description last">
-										<p>An array of bones.</p>
-									</td>
-								</tr>
-							</tbody>
-						</table>
-						<dl class="details">
-							<dt class="important tag-deprecated"><strong>Deprecated:</strong> since r175.</dt>
-						</dl>
-						<dl class="details">
-							<dt class="tag-returns"><strong>Returns:</strong> The new animation clip.</dt>
-						</dl>
-					</div>
 					<h3 class="name name-method" id=".toJSON" translate="no">.<a href="#.toJSON">toJSON</a><span class="signature">( clip : <span class="param-type"><a href="AnimationClip.html">AnimationClip</a></span> )</span><span class="type-signature"> : Object</span> </h3>
 					<div class="method">
 						<div class="description">

+ 0 - 16
docs/pages/AnimationClip.html.md

@@ -166,22 +166,6 @@ The serialized animation clip.
 
 **Returns:** The new animation clip.
 
-### .parseAnimation( animation : Object, bones : Array.<Bone> ) : AnimationClip
-
-Parses the `animation.hierarchy` format and returns a new animation clip.
-
-**animation**
-
-A serialized animation clip as JSON.
-
-**bones**
-
-An array of bones.
-
-**Deprecated:** since r175.
-
-**Returns:** The new animation clip.
-
 ### .toJSON( clip : AnimationClip ) : Object
 
 Serializes the given animation clip into JSON.

+ 3 - 0
docs/pages/ArcballControls.html

@@ -74,6 +74,9 @@ animation loop when animations are on.</p></div>
 						<p>If set to <code>true</code>, the camera's near and far values will be adjusted every time zoom is
 performed trying to maintain the same visible portion given by initial near and far
 values. Only works with perspective cameras.</p>
+<p>This feature only works as expected if the camera's initial state (position, near and far values)
+is correctly configured before creating the controls. Otherwise <a href="ArcballControls.html#setCamera">ArcballControls#setCamera</a>
+must be called by the application.</p>
 						<p>Default is <code>false</code>.</p>
 					</div>
 				</div>

+ 2 - 0
docs/pages/ArcballControls.html.md

@@ -44,6 +44,8 @@ Default is `null`.
 
 If set to `true`, the camera's near and far values will be adjusted every time zoom is performed trying to maintain the same visible portion given by initial near and far values. Only works with perspective cameras.
 
+This feature only works as expected if the camera's initial state (position, near and far values) is correctly configured before creating the controls. Otherwise [ArcballControls#setCamera](ArcballControls.html#setCamera) must be called by the application.
+
 Default is `false`.
 
 ### .cursorZoom : boolean

+ 2 - 5
docs/pages/BezierInterpolant.html

@@ -17,11 +17,8 @@
 <p>This interpolant supports the COLLADA/Maya style of Bezier animation where
 each keyframe has explicit in/out tangent control points specified as
 2D coordinates (time, value).</p>
-<p>The tangent data must be provided via the <code>settings</code> object:</p>
-<ul>
-<li><code>settings.inTangents</code>: Float32Array with [time, value] pairs per keyframe per component</li>
-<li><code>settings.outTangents</code>: Float32Array with [time, value] pairs per keyframe per component</li>
-</ul>
+<p>Tangent data is read from <code>inTangents</code> and <code>outTangents</code> on the interpolant
+(populated by <code>KeyframeTrack.InterpolantFactoryMethodBezier</code>).</p>
 <p>For a track with N keyframes and stride S:</p>
 <ul>
 <li>Each tangent array has N * S * 2 values</li>

+ 1 - 4
docs/pages/BezierInterpolant.html.md

@@ -6,10 +6,7 @@ A Bezier interpolant using cubic Bezier curves with 2D control points.
 
 This interpolant supports the COLLADA/Maya style of Bezier animation where each keyframe has explicit in/out tangent control points specified as 2D coordinates (time, value).
 
-The tangent data must be provided via the `settings` object:
-
-*   `settings.inTangents`: Float32Array with \[time, value\] pairs per keyframe per component
-*   `settings.outTangents`: Float32Array with \[time, value\] pairs per keyframe per component
+Tangent data is read from `inTangents` and `outTangents` on the interpolant (populated by `KeyframeTrack.InterpolantFactoryMethodBezier`).
 
 For a track with N keyframes and stride S:
 

+ 6 - 7
docs/pages/BloomNode.html

@@ -14,6 +14,12 @@
 		<section>
 			<header>
 				<div class="class-description"><p>Post processing node for creating a bloom effect.</p>
+<pre><code class="language-js">const renderPipeline = new THREE.RenderPipeline( renderer );
+const scenePass = pass( scene, camera );
+const scenePassColor = scenePass.getTextureNode( 'output' );
+const bloomPass = bloom( scenePassColor );
+renderPipeline.outputNode = scenePassColor.add( bloomPass );
+</code></pre>
 <p>By default, the node affects the entire image. For a selective bloom,
 use the <code>emissive</code> material property to control which objects should
 contribute to bloom or not. This can be achieved via MRT.</p>
@@ -27,13 +33,6 @@ const scenePassColor = scenePass.getTextureNode( 'output' );
 const emissivePass = scenePass.getTextureNode( 'emissive' );
 const bloomPass = bloom( emissivePass );
 renderPipeline.outputNode = scenePassColor.add( bloomPass );
-</code></pre></div>
-				<h2>Code Example</h2>
-				<div translate="no"><pre><code class="language-js">const renderPipeline = new THREE.RenderPipeline( renderer );
-const scenePass = pass( scene, camera );
-const scenePassColor = scenePass.getTextureNode( 'output' );
-const bloomPass = bloom( scenePassColor );
-renderPipeline.outputNode = scenePassColor.add( bloomPass );
 </code></pre></div>
 			</header>
 			<article>

+ 8 - 10
docs/pages/BloomNode.html.md

@@ -4,28 +4,26 @@
 
 Post processing node for creating a bloom effect.
 
-By default, the node affects the entire image. For a selective bloom, use the `emissive` material property to control which objects should contribute to bloom or not. This can be achieved via MRT.
-
 ```js
 const renderPipeline = new THREE.RenderPipeline( renderer );
 const scenePass = pass( scene, camera );
-scenePass.setMRT( mrt( {
-	output,
-	emissive
-} ) );
 const scenePassColor = scenePass.getTextureNode( 'output' );
-const emissivePass = scenePass.getTextureNode( 'emissive' );
-const bloomPass = bloom( emissivePass );
+const bloomPass = bloom( scenePassColor );
 renderPipeline.outputNode = scenePassColor.add( bloomPass );
 ```
 
-## Code Example
+By default, the node affects the entire image. For a selective bloom, use the `emissive` material property to control which objects should contribute to bloom or not. This can be achieved via MRT.
 
 ```js
 const renderPipeline = new THREE.RenderPipeline( renderer );
 const scenePass = pass( scene, camera );
+scenePass.setMRT( mrt( {
+	output,
+	emissive
+} ) );
 const scenePassColor = scenePass.getTextureNode( 'output' );
-const bloomPass = bloom( scenePassColor );
+const emissivePass = scenePass.getTextureNode( 'emissive' );
+const bloomPass = bloom( emissivePass );
 renderPipeline.outputNode = scenePassColor.add( bloomPass );
 ```
 

+ 5 - 6
docs/pages/BufferAttributeNode.html

@@ -16,18 +16,17 @@
 				<div class="class-description"><p>In earlier <code>three.js</code> versions it was only possible to define attribute data
 on geometry level. With <code>BufferAttributeNode</code>, it is also possible to do this
 on the node level.</p>
-<p>This new approach is especially interesting when geometry data are generated via
-compute shaders. The below line converts a storage buffer into an attribute node.</p>
-<pre><code class="language-js">material.positionNode = positionBuffer.toAttribute();
-</code></pre></div>
-				<h2>Code Example</h2>
-				<div translate="no"><pre><code class="language-js">const geometry = new THREE.PlaneGeometry();
+<pre><code class="language-js">const geometry = new THREE.PlaneGeometry();
 const positionAttribute = geometry.getAttribute( 'position' );
 const colors = [];
 for ( let i = 0; i &lt; position.count; i ++ ) {
 	colors.push( 1, 0, 0 );
 }
 material.colorNode = bufferAttribute( new THREE.Float32BufferAttribute( colors, 3 ) );
+</code></pre>
+<p>This new approach is especially interesting when geometry data are generated via
+compute shaders. The below line converts a storage buffer into an attribute node.</p>
+<pre><code class="language-js">material.positionNode = positionBuffer.toAttribute();
 </code></pre></div>
 			</header>
 			<article>

+ 6 - 8
docs/pages/BufferAttributeNode.html.md

@@ -4,14 +4,6 @@
 
 In earlier `three.js` versions it was only possible to define attribute data on geometry level. With `BufferAttributeNode`, it is also possible to do this on the node level.
 
-This new approach is especially interesting when geometry data are generated via compute shaders. The below line converts a storage buffer into an attribute node.
-
-```js
-material.positionNode = positionBuffer.toAttribute();
-```
-
-## Code Example
-
 ```js
 const geometry = new THREE.PlaneGeometry();
 const positionAttribute = geometry.getAttribute( 'position' );
@@ -22,6 +14,12 @@ for ( let i = 0; i < position.count; i ++ ) {
 material.colorNode = bufferAttribute( new THREE.Float32BufferAttribute( colors, 3 ) );
 ```
 
+This new approach is especially interesting when geometry data are generated via compute shaders. The below line converts a storage buffer into an attribute node.
+
+```js
+material.positionNode = positionBuffer.toAttribute();
+```
+
 ## Constructor
 
 ### new BufferAttributeNode( value : BufferAttribute | InterleavedBuffer | TypedArray, bufferType : string, bufferStride : number, bufferOffset : number )

+ 16 - 0
docs/pages/CSMFrustum.html

@@ -47,6 +47,12 @@
 far plane in view space.</p>
 					</div>
 				</div>
+				<div class="member">
+					<h3 class="name" id="zFar" translate="no">.<a href="#zFar">zFar</a><span class="type-signature"> : number</span> </h3>
+					<div class="description">
+						<p>The zFar value.</p>
+					</div>
+				</div>
 				<div class="member">
 					<h3 class="name" id="zNear" translate="no">.<a href="#zNear">zNear</a><span class="type-signature"> : number</span> </h3>
 					<div class="description">
@@ -158,6 +164,16 @@ given camera matrix.</p>
 				<p>Whether this CSM frustum is used with WebGL or WebGPU.</p>
 			</td>
 		</tr>
+		<tr>
+				<td class="name">
+					<strong>reversedDepth</strong>
+						<br>
+<span class="param-type">boolean</span>
+				</td>
+			<td class="description last">
+				<p>Whether reversed depth buffer is enabled.</p>
+			</td>
+		</tr>
 		<tr>
 				<td class="name">
 					<strong>projectionMatrix</strong>

+ 9 - 0
docs/pages/CSMFrustum.html.md

@@ -26,6 +26,10 @@ The CSM data.
 
 An object representing the vertices of the near and far plane in view space.
 
+### .zFar : number
+
+The zFar value.
+
 ### .zNear : number
 
 The zNear value. This value depends on whether the CSM is used with WebGL or WebGPU. Both API use different conventions for their projection matrices.
@@ -81,6 +85,11 @@ boolean
 
 Whether this CSM frustum is used with WebGL or WebGPU.
 
+**reversedDepth**  
+boolean
+
+Whether reversed depth buffer is enabled.
+
 **projectionMatrix**  
 [Matrix4](Matrix4.html)
 

+ 120 - 0
docs/pages/ClusteredLighting.html

@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+	<meta charset="utf-8">
+	<title>ClusteredLighting - Three.js Docs</title>
+	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+	<script src="../scripts/highlight.min.js"></script>
+	<link type="text/css" rel="stylesheet" href="../styles/highlight-three.css">
+	<link type="text/css" rel="stylesheet" href="../styles/page.css">
+</head>
+<body>
+		<p class="inheritance" translate="no"><a href="Lighting.html">Lighting</a> → </p>
+	<h1 translate="no">ClusteredLighting</h1>
+		<section>
+			<header>
+				<div class="class-description"><p>A custom lighting implementation based on Forward+ Clustered Shading that
+overwrites the default lighting system in <a href="WebGPURenderer.html">WebGPURenderer</a>. Suitable
+for 3D scenes with many point lights and real depth complexity — the view
+frustum is partitioned into a 3D cluster grid so only the lights actually
+reaching each fragment are evaluated.</p></div>
+				<h2>Code Example</h2>
+				<div translate="no"><pre><code class="language-js">const lighting = new ClusteredLighting();
+renderer.lighting = lighting; // set lighting system
+</code></pre></div>
+			</header>
+			<article>
+				<h2 class="subsection-title">Import</h2>
+				<p><span translate="no">ClusteredLighting</span> is an addon, and must be imported explicitly, see <a href="https://threejs.org/manual/#en/installation" target="_blank" rel="noopener">Installation#Addons</a>.</p>
+				<pre><code class="language-js">import { ClusteredLighting } from 'three/addons/lighting/ClusteredLighting.js';</code></pre>
+				<div class="container-overview">
+					<h2>Constructor</h2>
+					<h3 class="name name-method" id="ClusteredLighting" translate="no">new <a href="#ClusteredLighting">ClusteredLighting</a><span class="signature">( maxLights : <span class="param-type">number</span>, tileSize : <span class="param-type">number</span>, zSlices : <span class="param-type">number</span>, maxLightsPerCluster : <span class="param-type">number</span> )</span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Constructs a new clustered lighting system.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">maxLights</strong>
+									</td>
+									<td class="description last">
+										<p>Maximum number of point lights.</p>
+										<p>Default is <code>1024</code>.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">tileSize</strong>
+									</td>
+									<td class="description last">
+										<p>Screen tile size in pixels (cluster XY size).</p>
+										<p>Default is <code>32</code>.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">zSlices</strong>
+									</td>
+									<td class="description last">
+										<p>Number of exponential depth slices.</p>
+										<p>Default is <code>24</code>.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">maxLightsPerCluster</strong>
+									</td>
+									<td class="description last">
+										<p>Per-cluster light-list capacity.</p>
+										<p>Default is <code>64</code>.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+					</div>
+				</div>
+				<h2 class="subsection-title">Classes</h2>
+				<dl>
+					<dt><a href="ClusteredLighting.html">ClusteredLighting</a></dt>
+					<dd></dd>
+				</dl>
+				<h2 class="subsection-title">Methods</h2>
+					<h3 class="name name-method" id="createNode" translate="no">.<a href="#createNode">createNode</a><span class="signature">( lights : <span class="param-type">Array.&lt;<a href="Light.html">Light</a>></span> )</span><span class="type-signature"> : <a href="ClusteredLightsNode.html">ClusteredLightsNode</a></span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Creates a new clustered lights node for the given array of lights.</p>
+<p>This method is called internally by the renderer and must be overwritten by
+all custom lighting implementations.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">lights</strong>
+									</td>
+									<td class="description last">
+										<p>The lights.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+						<dl class="details">
+							<dt class="tag-overrides"><strong>Overrides:</strong> <a href="Lighting.html#createNode">Lighting#createNode</a></dt>
+						</dl>
+						<dl class="details">
+							<dt class="tag-returns"><strong>Returns:</strong> The clustered lights node.</dt>
+						</dl>
+					</div>
+				<h2 class="subsection-title">Source</h2>
+				<p>
+					<a href="https://github.com/mrdoob/three.js/blob/master/examples/jsm/lighting/ClusteredLighting.js" translate="no" target="_blank" rel="noopener">examples/jsm/lighting/ClusteredLighting.js</a>
+				</p>
+			</article>
+		</section>
+<script src="../scripts/linenumber.js"></script>
+<script src="../scripts/page.js"></script>
+</body>
+</html>

+ 74 - 0
docs/pages/ClusteredLighting.html.md

@@ -0,0 +1,74 @@
+*Inheritance: Lighting →*
+
+# ClusteredLighting
+
+A custom lighting implementation based on Forward+ Clustered Shading that overwrites the default lighting system in [WebGPURenderer](WebGPURenderer.html). Suitable for 3D scenes with many point lights and real depth complexity — the view frustum is partitioned into a 3D cluster grid so only the lights actually reaching each fragment are evaluated.
+
+## Code Example
+
+```js
+const lighting = new ClusteredLighting();
+renderer.lighting = lighting; // set lighting system
+```
+
+## Import
+
+ClusteredLighting is an addon, and must be imported explicitly, see [Installation#Addons](https://threejs.org/manual/#en/installation).
+
+```js
+import { ClusteredLighting } from 'three/addons/lighting/ClusteredLighting.js';
+```
+
+## Constructor
+
+### new ClusteredLighting( maxLights : number, tileSize : number, zSlices : number, maxLightsPerCluster : number )
+
+Constructs a new clustered lighting system.
+
+**maxLights**
+
+Maximum number of point lights.
+
+Default is `1024`.
+
+**tileSize**
+
+Screen tile size in pixels (cluster XY size).
+
+Default is `32`.
+
+**zSlices**
+
+Number of exponential depth slices.
+
+Default is `24`.
+
+**maxLightsPerCluster**
+
+Per-cluster light-list capacity.
+
+Default is `64`.
+
+## Classes
+
+[ClusteredLighting](ClusteredLighting.html)
+
+## Methods
+
+### .createNode( lights : Array.<Light> ) : ClusteredLightsNode
+
+Creates a new clustered lights node for the given array of lights.
+
+This method is called internally by the renderer and must be overwritten by all custom lighting implementations.
+
+**lights**
+
+The lights.
+
+**Overrides:** [Lighting#createNode](Lighting.html#createNode)
+
+**Returns:** The clustered lights node.
+
+## Source
+
+[examples/jsm/lighting/ClusteredLighting.js](https://github.com/mrdoob/three.js/blob/master/examples/jsm/lighting/ClusteredLighting.js)

+ 86 - 0
docs/pages/ClusteredLightsNode.html

@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+	<meta charset="utf-8">
+	<title>ClusteredLightsNode - Three.js Docs</title>
+	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+	<script src="../scripts/highlight.min.js"></script>
+	<link type="text/css" rel="stylesheet" href="../styles/highlight-three.css">
+	<link type="text/css" rel="stylesheet" href="../styles/page.css">
+</head>
+<body>
+		<p class="inheritance" translate="no"><a href="EventDispatcher.html">EventDispatcher</a> → <a href="Node.html">Node</a> → <a href="LightsNode.html">LightsNode</a> → </p>
+	<h1 translate="no">ClusteredLightsNode</h1>
+		<section>
+			<header>
+				<div class="class-description"><p>A custom version of <code>LightsNode</code> implementing Forward+ clustered shading:
+the view frustum is subdivided into a 3D grid of clusters (X × Y screen tiles
+times an exponentially-spaced set of Z depth slices), and each cluster holds
+only the point lights whose spheres intersect it. At shading time each fragment
+looks up its cluster and loops over just that cluster's lights. Unlike 2D tiled
+lighting, clustered shading culls lights that share screen pixels but lie at
+different depths — suitable for 3D scenes with real depth complexity.</p></div>
+			</header>
+			<article>
+				<h2 class="subsection-title">Import</h2>
+				<p><span translate="no">ClusteredLightsNode</span> is an addon, and must be imported explicitly, see <a href="https://threejs.org/manual/#en/installation" target="_blank" rel="noopener">Installation#Addons</a>.</p>
+				<pre><code class="language-js">import { clusteredLights } from 'three/addons/tsl/lighting/ClusteredLightsNode.js';</code></pre>
+				<div class="container-overview">
+					<h2>Constructor</h2>
+					<h3 class="name name-method" id="ClusteredLightsNode" translate="no">new <a href="#ClusteredLightsNode">ClusteredLightsNode</a><span class="signature">( maxLights : <span class="param-type">number</span>, tileSize : <span class="param-type">number</span>, zSlices : <span class="param-type">number</span>, maxLightsPerCluster : <span class="param-type">number</span> )</span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Constructs a new clustered lights node.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">maxLights</strong>
+									</td>
+									<td class="description last">
+										<p>Maximum number of point lights.</p>
+										<p>Default is <code>1024</code>.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">tileSize</strong>
+									</td>
+									<td class="description last">
+										<p>Screen tile size in pixels (cluster XY size).</p>
+										<p>Default is <code>32</code>.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">zSlices</strong>
+									</td>
+									<td class="description last">
+										<p>Number of exponential depth slices.</p>
+										<p>Default is <code>24</code>.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">maxLightsPerCluster</strong>
+									</td>
+									<td class="description last">
+										<p>Per-cluster light-list capacity.</p>
+										<p>Default is <code>64</code>.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+					</div>
+				</div>
+				<h2 class="subsection-title">Source</h2>
+				<p>
+					<a href="https://github.com/mrdoob/three.js/blob/master/examples/jsm/tsl/lighting/ClusteredLightsNode.js" translate="no" target="_blank" rel="noopener">examples/jsm/tsl/lighting/ClusteredLightsNode.js</a>
+				</p>
+			</article>
+		</section>
+<script src="../scripts/linenumber.js"></script>
+<script src="../scripts/page.js"></script>
+</body>
+</html>

+ 47 - 0
docs/pages/ClusteredLightsNode.html.md

@@ -0,0 +1,47 @@
+*Inheritance: EventDispatcher → Node → LightsNode →*
+
+# ClusteredLightsNode
+
+A custom version of `LightsNode` implementing Forward+ clustered shading: the view frustum is subdivided into a 3D grid of clusters (X × Y screen tiles times an exponentially-spaced set of Z depth slices), and each cluster holds only the point lights whose spheres intersect it. At shading time each fragment looks up its cluster and loops over just that cluster's lights. Unlike 2D tiled lighting, clustered shading culls lights that share screen pixels but lie at different depths — suitable for 3D scenes with real depth complexity.
+
+## Import
+
+ClusteredLightsNode is an addon, and must be imported explicitly, see [Installation#Addons](https://threejs.org/manual/#en/installation).
+
+```js
+import { clusteredLights } from 'three/addons/tsl/lighting/ClusteredLightsNode.js';
+```
+
+## Constructor
+
+### new ClusteredLightsNode( maxLights : number, tileSize : number, zSlices : number, maxLightsPerCluster : number )
+
+Constructs a new clustered lights node.
+
+**maxLights**
+
+Maximum number of point lights.
+
+Default is `1024`.
+
+**tileSize**
+
+Screen tile size in pixels (cluster XY size).
+
+Default is `32`.
+
+**zSlices**
+
+Number of exponential depth slices.
+
+Default is `24`.
+
+**maxLightsPerCluster**
+
+Per-cluster light-list capacity.
+
+Default is `64`.
+
+## Source
+
+[examples/jsm/tsl/lighting/ClusteredLightsNode.js](https://github.com/mrdoob/three.js/blob/master/examples/jsm/tsl/lighting/ClusteredLightsNode.js)

+ 3 - 4
docs/pages/Color.html

@@ -16,6 +16,9 @@
 color space</i>, which defaults to <code>LinearSRGBColorSpace</code>. Inputs
 conventionally using <code>SRGBColorSpace</code> (such as hexadecimals and CSS
 strings) are converted to the working color space automatically.</p>
+<pre><code class="language-js">// converted automatically from SRGBColorSpace to LinearSRGBColorSpace
+const color = new THREE.Color().setHex( 0x112233 );
+</code></pre>
 <p>Source color spaces may be specified explicitly, to ensure correct conversions.</p>
 <pre><code class="language-js">// assumed already LinearSRGBColorSpace; no conversion
 const color = new THREE.Color().setRGB( 0.5, 0.5, 0.5 );
@@ -40,10 +43,6 @@ const color5 = new THREE.Color( 'skyblue' );
 const color6 = new THREE.Color(&quot;hsl(0, 100%, 50%)&quot;);
 //Separate RGB values between 0 and 1
 const color7 = new THREE.Color( 1, 0, 0 );
-</code></pre></div>
-				<h2>Code Example</h2>
-				<div translate="no"><pre><code class="language-js">// converted automatically from SRGBColorSpace to LinearSRGBColorSpace
-const color = new THREE.Color().setHex( 0x112233 );
 </code></pre></div>
 			</header>
 			<article>

+ 5 - 7
docs/pages/Color.html.md

@@ -2,6 +2,11 @@
 
 A Color instance is represented by RGB components in the linear _working color space_, which defaults to `LinearSRGBColorSpace`. Inputs conventionally using `SRGBColorSpace` (such as hexadecimals and CSS strings) are converted to the working color space automatically.
 
+```js
+// converted automatically from SRGBColorSpace to LinearSRGBColorSpace
+const color = new THREE.Color().setHex( 0x112233 );
+```
+
 Source color spaces may be specified explicitly, to ensure correct conversions.
 
 ```js
@@ -30,13 +35,6 @@ const color6 = new THREE.Color("hsl(0, 100%, 50%)");
 const color7 = new THREE.Color( 1, 0, 0 );
 ```
 
-## Code Example
-
-```js
-// converted automatically from SRGBColorSpace to LinearSRGBColorSpace
-const color = new THREE.Color().setHex( 0x112233 );
-```
-
 ## Constructor
 
 ### new Color( r : number | string | Color, g : number, b : number )

+ 0 - 1
docs/pages/ConditionalNode.html

@@ -15,7 +15,6 @@
 			<header>
 				<div class="class-description"><p>Represents a logical <code>if/else</code> statement. Can be used as an alternative
 to the <code>If()</code>/<code>Else()</code> syntax.</p>
-<p>The corresponding TSL <code>select()</code> looks like so:</p>
 <p>The <code>select()</code> method is called in a chaining fashion on a condition. The parameter nodes of <code>select()</code>
 determine the outcome of the entire statement.</p></div>
 				<h2>Code Example</h2>

+ 0 - 2
docs/pages/ConditionalNode.html.md

@@ -4,8 +4,6 @@
 
 Represents a logical `if/else` statement. Can be used as an alternative to the `If()`/`Else()` syntax.
 
-The corresponding TSL `select()` looks like so:
-
 The `select()` method is called in a chaining fashion on a condition. The parameter nodes of `select()` determine the outcome of the entire statement.
 
 ## Code Example

+ 2 - 3
docs/pages/FlipNode.html

@@ -16,12 +16,11 @@
 				<div class="class-description"><p>This module is part of the TSL core and usually not used in app level code.
 It represents a flip operation during the shader generation process
 meaning it flips normalized values with the following formula:</p>
+<pre class="prettyprint source"><code>x = 1 - x;
+</code></pre>
 <p><code>FlipNode</code> is internally used to implement any <code>flipXYZW()</code>, <code>flipRGBA()</code> and
 <code>flipSTPQ()</code> method invocations on node objects. For example:</p>
 <pre><code class="language-js">uvNode = uvNode.flipY();
-</code></pre></div>
-				<h2>Code Example</h2>
-				<div translate="no"><pre class="prettyprint source"><code>x = 1 - x;
 </code></pre></div>
 			</header>
 			<article>

+ 3 - 5
docs/pages/FlipNode.html.md

@@ -4,16 +4,14 @@
 
 This module is part of the TSL core and usually not used in app level code. It represents a flip operation during the shader generation process meaning it flips normalized values with the following formula:
 
-`FlipNode` is internally used to implement any `flipXYZW()`, `flipRGBA()` and `flipSTPQ()` method invocations on node objects. For example:
-
 ```js
-uvNode = uvNode.flipY();
+x = 1 - x;
 ```
 
-## Code Example
+`FlipNode` is internally used to implement any `flipXYZW()`, `flipRGBA()` and `flipSTPQ()` method invocations on node objects. For example:
 
 ```js
-x = 1 - x;
+uvNode = uvNode.flipY();
 ```
 
 ## Constructor

+ 139 - 1
docs/pages/GLSLNodeBuilder.html

@@ -379,6 +379,144 @@ against a reference value.</p>
 							<dt class="tag-returns"><strong>Returns:</strong> The GLSL snippet.</dt>
 						</dl>
 					</div>
+					<h3 class="name name-method" id="generateTextureGather" translate="no">.<a href="#generateTextureGather">generateTextureGather</a><span class="signature">( texture : <span class="param-type"><a href="Texture.html">Texture</a></span>, textureProperty : <span class="param-type">string</span>, uvSnippet : <span class="param-type">string</span>, gatherSnippet : <span class="param-type">string</span>, depthSnippet : <span class="param-type">string</span>, offsetSnippet : <span class="param-type">string</span>, flipYSnippet : <span class="param-type">string</span> )</span><span class="type-signature"> : string</span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Generates the GLSL snippet for gathering four texels from the given texture.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">texture</strong>
+									</td>
+									<td class="description last">
+										<p>The texture.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">textureProperty</strong>
+									</td>
+									<td class="description last">
+										<p>The name of the texture uniform in the shader.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">uvSnippet</strong>
+									</td>
+									<td class="description last">
+										<p>A GLSL snippet that represents texture coordinates used for sampling.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">gatherSnippet</strong>
+									</td>
+									<td class="description last">
+										<p>A GLSL snippet that represents the index of the channel to read.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">depthSnippet</strong>
+									</td>
+									<td class="description last">
+										<p>A GLSL snippet that represents 0-based texture array index to sample.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">offsetSnippet</strong>
+									</td>
+									<td class="description last">
+										<p>A GLSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">flipYSnippet</strong>
+									</td>
+									<td class="description last">
+										<p>A GLSL snippet that represents the y-flip. Only used for WebGL.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+						<dl class="details">
+							<dt class="tag-returns"><strong>Returns:</strong> The GLSL snippet.</dt>
+						</dl>
+					</div>
+					<h3 class="name name-method" id="generateTextureGatherCompare" translate="no">.<a href="#generateTextureGatherCompare">generateTextureGatherCompare</a><span class="signature">( texture : <span class="param-type"><a href="Texture.html">Texture</a></span>, textureProperty : <span class="param-type">string</span>, uvSnippet : <span class="param-type">string</span>, compareSnippet : <span class="param-type">string</span>, depthSnippet : <span class="param-type">string</span>, offsetSnippet : <span class="param-type">string</span>, flipYSnippet : <span class="param-type">string</span> )</span><span class="type-signature"> : string</span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Generates the GLSL snippet for performing a depth comparison on four texels in the given depth texture.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">texture</strong>
+									</td>
+									<td class="description last">
+										<p>The texture.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">textureProperty</strong>
+									</td>
+									<td class="description last">
+										<p>The name of the texture uniform in the shader.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">uvSnippet</strong>
+									</td>
+									<td class="description last">
+										<p>A GLSL snippet that represents texture coordinates used for sampling.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">compareSnippet</strong>
+									</td>
+									<td class="description last">
+										<p>A GLSL snippet that represents the reference value.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">depthSnippet</strong>
+									</td>
+									<td class="description last">
+										<p>A GLSL snippet that represents 0-based texture array index to sample.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">offsetSnippet</strong>
+									</td>
+									<td class="description last">
+										<p>A GLSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">flipYSnippet</strong>
+									</td>
+									<td class="description last">
+										<p>A GLSL snippet that represents the y-flip. Only used for WebGL.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+						<dl class="details">
+							<dt class="tag-returns"><strong>Returns:</strong> The GLSL snippet.</dt>
+						</dl>
+					</div>
 					<h3 class="name name-method" id="generateTextureGrad" translate="no">.<a href="#generateTextureGrad">generateTextureGrad</a><span class="signature">( texture : <span class="param-type"><a href="Texture.html">Texture</a></span>, textureProperty : <span class="param-type">string</span>, uvSnippet : <span class="param-type">string</span>, gradSnippet : <span class="param-type">Array.&lt;string></span>, depthSnippet : <span class="param-type">string</span>, offsetSnippet : <span class="param-type">string</span> )</span><span class="type-signature"> : string</span> </h3>
 					<div class="method">
 						<div class="description">
@@ -612,7 +750,7 @@ against a reference value.</p>
 							</tbody>
 						</table>
 						<dl class="details">
-							<dt class="tag-returns"><strong>Returns:</strong> The resolved WGSL bitcast invocation.</dt>
+							<dt class="tag-returns"><strong>Returns:</strong> The resolved GLSL bitcast invocation.</dt>
 						</dl>
 					</div>
 					<h3 class="name name-method" id="getClipDistance" translate="no">.<a href="#getClipDistance">getClipDistance</a><span class="signature">()</span><span class="type-signature"> : string</span> </h3>

+ 69 - 1
docs/pages/GLSLNodeBuilder.html.md

@@ -192,6 +192,74 @@ Default is `this.shaderStage`.
 
 **Returns:** The GLSL snippet.
 
+### .generateTextureGather( texture : Texture, textureProperty : string, uvSnippet : string, gatherSnippet : string, depthSnippet : string, offsetSnippet : string, flipYSnippet : string ) : string
+
+Generates the GLSL snippet for gathering four texels from the given texture.
+
+**texture**
+
+The texture.
+
+**textureProperty**
+
+The name of the texture uniform in the shader.
+
+**uvSnippet**
+
+A GLSL snippet that represents texture coordinates used for sampling.
+
+**gatherSnippet**
+
+A GLSL snippet that represents the index of the channel to read.
+
+**depthSnippet**
+
+A GLSL snippet that represents 0-based texture array index to sample.
+
+**offsetSnippet**
+
+A GLSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
+
+**flipYSnippet**
+
+A GLSL snippet that represents the y-flip. Only used for WebGL.
+
+**Returns:** The GLSL snippet.
+
+### .generateTextureGatherCompare( texture : Texture, textureProperty : string, uvSnippet : string, compareSnippet : string, depthSnippet : string, offsetSnippet : string, flipYSnippet : string ) : string
+
+Generates the GLSL snippet for performing a depth comparison on four texels in the given depth texture.
+
+**texture**
+
+The texture.
+
+**textureProperty**
+
+The name of the texture uniform in the shader.
+
+**uvSnippet**
+
+A GLSL snippet that represents texture coordinates used for sampling.
+
+**compareSnippet**
+
+A GLSL snippet that represents the reference value.
+
+**depthSnippet**
+
+A GLSL snippet that represents 0-based texture array index to sample.
+
+**offsetSnippet**
+
+A GLSL snippet that represents the offset that will be applied to the unnormalized texture coordinate before sampling the texture.
+
+**flipYSnippet**
+
+A GLSL snippet that represents the y-flip. Only used for WebGL.
+
+**Returns:** The GLSL snippet.
+
 ### .generateTextureGrad( texture : Texture, textureProperty : string, uvSnippet : string, gradSnippet : Array.<string>, depthSnippet : string, offsetSnippet : string ) : string
 
 Generates the GLSL snippet for sampling/loading the given texture using explicit gradients.
@@ -306,7 +374,7 @@ The output type to bitcast to.
 
 The input type of the.
 
-**Returns:** The resolved WGSL bitcast invocation.
+**Returns:** The resolved GLSL bitcast invocation.
 
 ### .getClipDistance() : string
 

+ 2 - 3
docs/pages/GPUComputationRenderer.html

@@ -24,6 +24,8 @@ as inputs to render the textures of the next frame.</p>
 <p>Variable names should be valid identifiers and should not collide with THREE GLSL used identifiers.
 a common approach could be to use 'texture' prefixing the variable name; i.e texturePosition, textureVelocity...</p>
 <p>The size of the computation (sizeX * sizeY) is defined as 'resolution' automatically in the shader. For example:</p>
+<pre class="prettyprint source"><code>#DEFINE resolution vec2( 1024.0, 1024.0 )
+</code></pre>
 <p>Basic use:</p>
 <pre><code class="language-js">// Initialization...
 // Create computation renderer
@@ -68,9 +70,6 @@ myMaterial.uniforms.map.value = outputRenderTarget.texture;
 // And compute each frame, before rendering to screen:
 gpuCompute.doRenderTarget( myFilter1, myRenderTarget );
 gpuCompute.doRenderTarget( myFilter2, outputRenderTarget );
-</code></pre></div>
-				<h2>Code Example</h2>
-				<div translate="no"><pre class="prettyprint source"><code>#DEFINE resolution vec2( 1024.0, 1024.0 )
 </code></pre></div>
 			</header>
 			<article>

+ 4 - 6
docs/pages/GPUComputationRenderer.html.md

@@ -14,6 +14,10 @@ Variable names should be valid identifiers and should not collide with THREE GLS
 
 The size of the computation (sizeX \* sizeY) is defined as 'resolution' automatically in the shader. For example:
 
+```js
+#DEFINE resolution vec2( 1024.0, 1024.0 )
+```
+
 Basic use:
 
 ```js
@@ -64,12 +68,6 @@ gpuCompute.doRenderTarget( myFilter1, myRenderTarget );
 gpuCompute.doRenderTarget( myFilter2, outputRenderTarget );
 ```
 
-## Code Example
-
-```js
-#DEFINE resolution vec2( 1024.0, 1024.0 )
-```
-
 ## Import
 
 GPUComputationRenderer is an addon, and must be imported explicitly, see [Installation#Addons](https://threejs.org/manual/#en/installation).

+ 46 - 1
docs/pages/IESSpotLightNode.html

@@ -18,8 +18,32 @@
 			<article>
 				<div class="container-overview">
 					<h2>Constructor</h2>
-					<h3 class="name name-method" id="IESSpotLightNode" translate="no">new <a href="#IESSpotLightNode">IESSpotLightNode</a><span class="signature">()</span> </h3>
+					<h3 class="name name-method" id="IESSpotLightNode" translate="no">new <a href="#IESSpotLightNode">IESSpotLightNode</a><span class="signature">( light : <span class="param-type"><a href="SpotLight.html">SpotLight</a></span> )</span> </h3>
 					<div class="method">
+						<div class="description">
+							<p>Constructs a new IES spot light node.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">light</strong>
+									</td>
+									<td class="description last">
+										<p>The spot light source.</p>
+										<p>Default is <code>null</code>.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+					</div>
+				</div>
+				<h2 class="subsection-title">Properties</h2>
+				<div class="member">
+					<h3 class="name" id="_iesTextureNode" translate="no">.<a href="#_iesTextureNode">_iesTextureNode</a><span class="type-signature"> : <a href="TextureNode.html">TextureNode</a></span> </h3>
+					<div class="description">
+						<p>The texture node representing the IES texture.</p>
+						<p>Default is <code>null</code>.</p>
 					</div>
 				</div>
 				<h2 class="subsection-title">Methods</h2>
@@ -55,6 +79,27 @@
 							<dt class="tag-returns"><strong>Returns:</strong> The spot attenuation.</dt>
 						</dl>
 					</div>
+					<h3 class="name name-method" id="update" translate="no">.<a href="#update">update</a><span class="signature">( frame : <span class="param-type"><a href="NodeFrame.html">NodeFrame</a></span> )</span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Overwritten to update the IES spot light texture.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">frame</strong>
+									</td>
+									<td class="description last">
+										<p>A reference to the current node frame.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+						<dl class="details">
+							<dt class="tag-overrides"><strong>Overrides:</strong> <a href="SpotLightNode.html#update">SpotLightNode#update</a></dt>
+						</dl>
+					</div>
 				<h2 class="subsection-title">Source</h2>
 				<p>
 					<a href="https://github.com/mrdoob/three.js/blob/master/src/nodes/lighting/IESSpotLightNode.js" translate="no" target="_blank" rel="noopener">src/nodes/lighting/IESSpotLightNode.js</a>

+ 27 - 1
docs/pages/IESSpotLightNode.html.md

@@ -6,7 +6,23 @@ An IES version of the default spot light node.
 
 ## Constructor
 
-### new IESSpotLightNode()
+### new IESSpotLightNode( light : SpotLight )
+
+Constructs a new IES spot light node.
+
+**light**
+
+The spot light source.
+
+Default is `null`.
+
+## Properties
+
+### ._iesTextureNode : TextureNode
+
+The texture node representing the IES texture.
+
+Default is `null`.
 
 ## Methods
 
@@ -26,6 +42,16 @@ The angle to compute the spot attenuation for.
 
 **Returns:** The spot attenuation.
 
+### .update( frame : NodeFrame )
+
+Overwritten to update the IES spot light texture.
+
+**frame**
+
+A reference to the current node frame.
+
+**Overrides:** [SpotLightNode#update](SpotLightNode.html#update)
+
 ## Source
 
 [src/nodes/lighting/IESSpotLightNode.js](https://github.com/mrdoob/three.js/blob/master/src/nodes/lighting/IESSpotLightNode.js)

+ 2 - 3
docs/pages/ImageBitmapLoader.html

@@ -20,15 +20,14 @@ textures for rendering.</p>
 These options need to be configured via <a href="ImageBitmapLoader.html#setOptions">ImageBitmapLoader#setOptions</a> prior to loading,
 unlike regular images which can be configured on the Texture to set these options on GPU upload instead.</p>
 <p>To match the default behaviour of <a href="Texture.html">Texture</a>, the following options are needed:</p>
+<pre><code class="language-js">{ imageOrientation: 'flipY', premultiplyAlpha: 'none' }
+</code></pre>
 <p>Also note that unlike <a href="FileLoader.html">FileLoader</a>, this loader will only avoid multiple concurrent requests to the same URL if <a href="Cache.html">Cache</a> is enabled.</p>
 <pre><code class="language-js">const loader = new THREE.ImageBitmapLoader();
 loader.setOptions( { imageOrientation: 'flipY' } ); // set options if needed
 const imageBitmap = await loader.loadAsync( 'image.png' );
 const texture = new THREE.Texture( imageBitmap );
 texture.needsUpdate = true;
-</code></pre></div>
-				<h2>Code Example</h2>
-				<div translate="no"><pre><code class="language-js">{ imageOrientation: 'flipY', premultiplyAlpha: 'none' }
 </code></pre></div>
 			</header>
 			<article>

+ 4 - 6
docs/pages/ImageBitmapLoader.html.md

@@ -8,6 +8,10 @@ Note that [Texture#flipY](Texture.html#flipY) and [Texture#premultiplyAlpha](Tex
 
 To match the default behaviour of [Texture](Texture.html), the following options are needed:
 
+```js
+{ imageOrientation: 'flipY', premultiplyAlpha: 'none' }
+```
+
 Also note that unlike [FileLoader](FileLoader.html), this loader will only avoid multiple concurrent requests to the same URL if [Cache](Cache.html) is enabled.
 
 ```js
@@ -18,12 +22,6 @@ const texture = new THREE.Texture( imageBitmap );
 texture.needsUpdate = true;
 ```
 
-## Code Example
-
-```js
-{ imageOrientation: 'flipY', premultiplyAlpha: 'none' }
-```
-
 ## Constructor
 
 ### new ImageBitmapLoader( manager : LoadingManager )

+ 82 - 26
docs/pages/Info.html

@@ -102,32 +102,32 @@ by <code>NodeFrame</code>.</p>
 	<tbody>
 		<tr>
 				<td class="name">
-					<strong>geometries</strong>
+					<strong>attributes</strong>
 						<br>
 <span class="param-type">number</span>
 				</td>
 			<td class="description last">
-				<p>The number of active geometries.</p>
+				<p>The number of active attributes.</p>
 			</td>
 		</tr>
 		<tr>
 				<td class="name">
-					<strong>textures</strong>
+					<strong>attributesSize</strong>
 						<br>
 <span class="param-type">number</span>
 				</td>
 			<td class="description last">
-				<p>The number of active textures.</p>
+				<p>The memory size of active attributes in bytes.</p>
 			</td>
 		</tr>
 		<tr>
 				<td class="name">
-					<strong>attributes</strong>
+					<strong>geometries</strong>
 						<br>
 <span class="param-type">number</span>
 				</td>
 			<td class="description last">
-				<p>The number of active attributes.</p>
+				<p>The number of active geometries.</p>
 			</td>
 		</tr>
 		<tr>
@@ -142,12 +142,12 @@ by <code>NodeFrame</code>.</p>
 		</tr>
 		<tr>
 				<td class="name">
-					<strong>storageAttributes</strong>
+					<strong>indexAttributesSize</strong>
 						<br>
 <span class="param-type">number</span>
 				</td>
 			<td class="description last">
-				<p>The number of active storage attributes.</p>
+				<p>The memory size of active index attributes in bytes.</p>
 			</td>
 		</tr>
 		<tr>
@@ -162,12 +162,12 @@ by <code>NodeFrame</code>.</p>
 		</tr>
 		<tr>
 				<td class="name">
-					<strong>readbackBuffers</strong>
+					<strong>indirectStorageAttributesSize</strong>
 						<br>
 <span class="param-type">number</span>
 				</td>
 			<td class="description last">
-				<p>The number of active readback buffers.</p>
+				<p>The memory size of active indirect storage attributes in bytes.</p>
 			</td>
 		</tr>
 		<tr>
@@ -182,52 +182,52 @@ by <code>NodeFrame</code>.</p>
 		</tr>
 		<tr>
 				<td class="name">
-					<strong>renderTargets</strong>
+					<strong>programsSize</strong>
 						<br>
 <span class="param-type">number</span>
 				</td>
 			<td class="description last">
-				<p>The number of active renderTargets.</p>
+				<p>The memory size of active programs in bytes.</p>
 			</td>
 		</tr>
 		<tr>
 				<td class="name">
-					<strong>total</strong>
+					<strong>readbackBuffers</strong>
 						<br>
 <span class="param-type">number</span>
 				</td>
 			<td class="description last">
-				<p>The total memory size in bytes.</p>
+				<p>The number of active readback buffers.</p>
 			</td>
 		</tr>
 		<tr>
 				<td class="name">
-					<strong>texturesSize</strong>
+					<strong>readbackBuffersSize</strong>
 						<br>
 <span class="param-type">number</span>
 				</td>
 			<td class="description last">
-				<p>The memory size of active textures in bytes.</p>
+				<p>The memory size of active readback buffers in bytes.</p>
 			</td>
 		</tr>
 		<tr>
 				<td class="name">
-					<strong>attributesSize</strong>
+					<strong>renderTargets</strong>
 						<br>
 <span class="param-type">number</span>
 				</td>
 			<td class="description last">
-				<p>The memory size of active attributes in bytes.</p>
+				<p>The number of active renderTargets.</p>
 			</td>
 		</tr>
 		<tr>
 				<td class="name">
-					<strong>indexAttributesSize</strong>
+					<strong>storageAttributes</strong>
 						<br>
 <span class="param-type">number</span>
 				</td>
 			<td class="description last">
-				<p>The memory size of active index attributes in bytes.</p>
+				<p>The number of active storage attributes.</p>
 			</td>
 		</tr>
 		<tr>
@@ -242,32 +242,52 @@ by <code>NodeFrame</code>.</p>
 		</tr>
 		<tr>
 				<td class="name">
-					<strong>indirectStorageAttributesSize</strong>
+					<strong>textures</strong>
 						<br>
 <span class="param-type">number</span>
 				</td>
 			<td class="description last">
-				<p>The memory size of active indirect storage attributes in bytes.</p>
+				<p>The number of active textures.</p>
 			</td>
 		</tr>
 		<tr>
 				<td class="name">
-					<strong>readbackBuffersSize</strong>
+					<strong>texturesSize</strong>
 						<br>
 <span class="param-type">number</span>
 				</td>
 			<td class="description last">
-				<p>The memory size of active readback buffers in bytes.</p>
+				<p>The memory size of active textures in bytes.</p>
 			</td>
 		</tr>
 		<tr>
 				<td class="name">
-					<strong>programsSize</strong>
+					<strong>uniformBuffers</strong>
 						<br>
 <span class="param-type">number</span>
 				</td>
 			<td class="description last">
-				<p>The memory size of active programs in bytes.</p>
+				<p>The number of active uniform buffers.</p>
+			</td>
+		</tr>
+		<tr>
+				<td class="name">
+					<strong>uniformBuffersSize</strong>
+						<br>
+<span class="param-type">number</span>
+				</td>
+			<td class="description last">
+				<p>The memory size of active uniform buffers in bytes.</p>
+			</td>
+		</tr>
+		<tr>
+				<td class="name">
+					<strong>total</strong>
+						<br>
+<span class="param-type">number</span>
+				</td>
+			<td class="description last">
+				<p>The total memory size in bytes.</p>
 			</td>
 		</tr>
 	</tbody>
@@ -479,6 +499,24 @@ by <code>NodeFrame</code>.</p>
 							</tbody>
 						</table>
 					</div>
+					<h3 class="name name-method" id="createUniformBuffer" translate="no">.<a href="#createUniformBuffer">createUniformBuffer</a><span class="signature">( uniformBuffer : <span class="param-type"><a href="UniformBuffer.html">UniformBuffer</a></span> )</span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Tracks a uniform buffer memory explicitly.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">uniformBuffer</strong>
+									</td>
+									<td class="description last">
+										<p>The uniform buffer to track.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+					</div>
 					<h3 class="name name-method" id="destroyAttribute" translate="no">.<a href="#destroyAttribute">destroyAttribute</a><span class="signature">( attribute : <span class="param-type"><a href="BufferAttribute.html">BufferAttribute</a></span> )</span> </h3>
 					<div class="method">
 						<div class="description">
@@ -549,6 +587,24 @@ by <code>NodeFrame</code>.</p>
 							</tbody>
 						</table>
 					</div>
+					<h3 class="name name-method" id="destroyUniformBuffer" translate="no">.<a href="#destroyUniformBuffer">destroyUniformBuffer</a><span class="signature">( uniformBuffer : <span class="param-type"><a href="UniformBuffer.html">UniformBuffer</a></span> )</span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Tracks a uniform buffer memory explicitly.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">uniformBuffer</strong>
+									</td>
+									<td class="description last">
+										<p>The uniform buffer to track.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+					</div>
 					<h3 class="name name-method" id="dispose" translate="no">.<a href="#dispose">dispose</a><span class="signature">()</span> </h3>
 					<div class="method">
 						<div class="description">

+ 52 - 26
docs/pages/Info.html.md

@@ -51,90 +51,100 @@ Default is `0`.
 
 Memory related metrics.
 
-**geometries**  
+**attributes**  
 number
 
-The number of active geometries.
+The number of active attributes.
 
-**textures**  
+**attributesSize**  
 number
 
-The number of active textures.
+The memory size of active attributes in bytes.
 
-**attributes**  
+**geometries**  
 number
 
-The number of active attributes.
+The number of active geometries.
 
 **indexAttributes**  
 number
 
 The number of active index attributes.
 
-**storageAttributes**  
+**indexAttributesSize**  
 number
 
-The number of active storage attributes.
+The memory size of active index attributes in bytes.
 
 **indirectStorageAttributes**  
 number
 
 The number of active indirect storage attributes.
 
-**readbackBuffers**  
+**indirectStorageAttributesSize**  
 number
 
-The number of active readback buffers.
+The memory size of active indirect storage attributes in bytes.
 
 **programs**  
 number
 
 The number of active programs.
 
-**renderTargets**  
+**programsSize**  
 number
 
-The number of active renderTargets.
+The memory size of active programs in bytes.
 
-**total**  
+**readbackBuffers**  
 number
 
-The total memory size in bytes.
+The number of active readback buffers.
 
-**texturesSize**  
+**readbackBuffersSize**  
 number
 
-The memory size of active textures in bytes.
+The memory size of active readback buffers in bytes.
 
-**attributesSize**  
+**renderTargets**  
 number
 
-The memory size of active attributes in bytes.
+The number of active renderTargets.
 
-**indexAttributesSize**  
+**storageAttributes**  
 number
 
-The memory size of active index attributes in bytes.
+The number of active storage attributes.
 
 **storageAttributesSize**  
 number
 
 The memory size of active storage attributes in bytes.
 
-**indirectStorageAttributesSize**  
+**textures**  
 number
 
-The memory size of active indirect storage attributes in bytes.
+The number of active textures.
 
-**readbackBuffersSize**  
+**texturesSize**  
 number
 
-The memory size of active readback buffers in bytes.
+The memory size of active textures in bytes.
 
-**programsSize**  
+**uniformBuffers**  
 number
 
-The memory size of active programs in bytes.
+The number of active uniform buffers.
+
+**uniformBuffersSize**  
+number
+
+The memory size of active uniform buffers in bytes.
+
+**total**  
+number
+
+The total memory size in bytes.
 
 ### .render : Object (readonly)
 
@@ -231,6 +241,14 @@ Tracks texture memory explicitly, updating counts and byte tracking.
 
 **texture**
 
+### .createUniformBuffer( uniformBuffer : UniformBuffer )
+
+Tracks a uniform buffer memory explicitly.
+
+**uniformBuffer**
+
+The uniform buffer to track.
+
 ### .destroyAttribute( attribute : BufferAttribute )
 
 Tracks attribute memory explicitly, updating counts and byte tracking.
@@ -259,6 +277,14 @@ Tracks texture memory explicitly, updating counts and byte tracking.
 
 **texture**
 
+### .destroyUniformBuffer( uniformBuffer : UniformBuffer )
+
+Tracks a uniform buffer memory explicitly.
+
+**uniformBuffer**
+
+The uniform buffer to track.
+
 ### .dispose()
 
 Performs a complete reset of the object.

+ 2 - 0
docs/pages/LightProbeGrid.html

@@ -14,6 +14,8 @@
 			<header>
 				<div class="class-description"><p>A 3D grid of L2 Spherical Harmonic irradiance probes that provides
 position-dependent diffuse global illumination.</p>
+<p>Note that this class can only be used with <a href="WebGLRenderer.html">WebGLRenderer</a>.
+A version for <a href="WebGPURenderer.html">WebGPURenderer</a> will be added at a later point.</p>
 <p>All seven packed SH sub-volumes are stored in a <strong>single</strong> RGBA
 <code>WebGL3DRenderTarget</code> using a texture-atlas layout along the Z axis.
 Each sub-volume occupies <code>( nz + 2 )</code> atlas slices: one padding slice at

+ 2 - 0
docs/pages/LightProbeGrid.html.md

@@ -2,6 +2,8 @@
 
 A 3D grid of L2 Spherical Harmonic irradiance probes that provides position-dependent diffuse global illumination.
 
+Note that this class can only be used with [WebGLRenderer](WebGLRenderer.html). A version for [WebGPURenderer](WebGPURenderer.html) will be added at a later point.
+
 All seven packed SH sub-volumes are stored in a **single** RGBA `WebGL3DRenderTarget` using a texture-atlas layout along the Z axis. Each sub-volume occupies `( nz + 2 )` atlas slices: one padding slice at each end (a copy of the nearest edge data slice) to prevent color bleeding when the hardware trilinear filter reads across a sub-volume boundary.
 
 Atlas layout (nz = resolution.z, PADDING = 1):

+ 1 - 1
docs/pages/LightProbeGridHelper.html

@@ -14,7 +14,7 @@
 		<section>
 			<header>
 				<div class="class-description"><p>Visualizes an <a href="LightProbeGrid.html">LightProbeGrid</a> by rendering a sphere at each
-probe position, shaded with the probe's L1 spherical harmonics.</p>
+probe position, shaded with the probe's L2 spherical harmonics.</p>
 <p>Uses a single <code>InstancedMesh</code> draw call for all probes.</p></div>
 				<h2>Code Example</h2>
 				<div translate="no"><pre><code class="language-js">const helper = new LightProbeGridHelper( probes );

+ 1 - 1
docs/pages/LightProbeGridHelper.html.md

@@ -2,7 +2,7 @@
 
 # LightProbeGridHelper
 
-Visualizes an [LightProbeGrid](LightProbeGrid.html) by rendering a sphere at each probe position, shaded with the probe's L1 spherical harmonics.
+Visualizes an [LightProbeGrid](LightProbeGrid.html) by rendering a sphere at each probe position, shaded with the probe's L2 spherical harmonics.
 
 Uses a single `InstancedMesh` draw call for all probes.
 

+ 3 - 4
docs/pages/LoopNode.html

@@ -14,6 +14,9 @@
 		<section>
 			<header>
 				<div class="class-description"><p>This module offers a variety of ways to implement loops in TSL. In it's basic form it's:</p>
+<pre><code class="language-js">Loop( count, ( { i } ) => {
+} );
+</code></pre>
 <p>However, it is also possible to define a start and end ranges, data types and loop conditions:</p>
 <pre><code class="language-js">Loop( { start: int( 0 ), end: int( 10 ), type: 'int', condition: '&lt;' }, ( { i } ) => {
 } );
@@ -32,10 +35,6 @@ Loop( value.lessThan( 10 ), () => {
 } );
 </code></pre>
 <p>The module also provides <code>Break()</code> and <code>Continue()</code> TSL expression for loop control.</p></div>
-				<h2>Code Example</h2>
-				<div translate="no"><pre><code class="language-js">Loop( count, ( { i } ) => {
-} );
-</code></pre></div>
 			</header>
 			<article>
 				<div class="container-overview">

+ 5 - 7
docs/pages/LoopNode.html.md

@@ -4,6 +4,11 @@
 
 This module offers a variety of ways to implement loops in TSL. In it's basic form it's:
 
+```js
+Loop( count, ( { i } ) => {
+} );
+```
+
 However, it is also possible to define a start and end ranges, data types and loop conditions:
 
 ```js
@@ -35,13 +40,6 @@ Loop( value.lessThan( 10 ), () => {
 
 The module also provides `Break()` and `Continue()` TSL expression for loop control.
 
-## Code Example
-
-```js
-Loop( count, ( { i } ) => {
-} );
-```
-
 ## Constructor
 
 ### new LoopNode( params : Array.<any> )

+ 4 - 5
docs/pages/Matrix2.html

@@ -18,6 +18,10 @@
 <a href="https://en.wikipedia.org/wiki/Row-_and_column-major_order#Column-major_order" target="_blank" rel="noopener">row-major</a>
 order, while internally they are stored in the <a href="Matrix2.html#elements">Matrix2#elements</a> array in column-major order.
 This means that calling:</p>
+<pre><code class="language-js">const m = new THREE.Matrix2();
+m.set( 11, 12,
+       21, 22 );
+</code></pre>
 <p>will result in the elements array containing:</p>
 <pre><code class="language-js">m.elements = [ 11, 21,
                12, 22 ];
@@ -28,11 +32,6 @@ most people are used to thinking about matrices in row-major order, the
 three.js documentation shows matrices in row-major order. Just bear in
 mind that if you are reading the source code, you'll have to take the
 transpose of any matrices outlined here to make sense of the calculations.</p></div>
-				<h2>Code Example</h2>
-				<div translate="no"><pre><code class="language-js">const m = new THREE.Matrix2();
-m.set( 11, 12,
-       21, 22 );
-</code></pre></div>
 			</header>
 			<article>
 				<div class="container-overview">

+ 6 - 8
docs/pages/Matrix2.html.md

@@ -6,6 +6,12 @@ A Note on Row-Major and Column-Major Ordering:
 
 The constructor and [Matrix2#set](Matrix2.html#set) method take arguments in [row-major](https://en.wikipedia.org/wiki/Row-_and_column-major_order#Column-major_order) order, while internally they are stored in the [Matrix2#elements](Matrix2.html#elements) array in column-major order. This means that calling:
 
+```js
+const m = new THREE.Matrix2();
+m.set( 11, 12,
+       21, 22 );
+```
+
 will result in the elements array containing:
 
 ```js
@@ -15,14 +21,6 @@ m.elements = [ 11, 21,
 
 and internally all calculations are performed using column-major ordering. However, as the actual ordering makes no difference mathematically and most people are used to thinking about matrices in row-major order, the three.js documentation shows matrices in row-major order. Just bear in mind that if you are reading the source code, you'll have to take the transpose of any matrices outlined here to make sense of the calculations.
 
-## Code Example
-
-```js
-const m = new THREE.Matrix2();
-m.set( 11, 12,
-       21, 22 );
-```
-
 ## Constructor
 
 ### new Matrix2( n11 : number, n12 : number, n21 : number, n22 : number )

+ 5 - 6
docs/pages/Matrix3.html

@@ -18,6 +18,11 @@
 <a href="https://en.wikipedia.org/wiki/Row-_and_column-major_order#Column-major_order" target="_blank" rel="noopener">row-major</a>
 order, while internally they are stored in the <a href="Matrix3.html#elements">Matrix3#elements</a> array in column-major order.
 This means that calling:</p>
+<pre><code class="language-js">const m = new THREE.Matrix();
+m.set( 11, 12, 13,
+       21, 22, 23,
+       31, 32, 33 );
+</code></pre>
 <p>will result in the elements array containing:</p>
 <pre><code class="language-js">m.elements = [ 11, 21, 31,
                12, 22, 32,
@@ -29,12 +34,6 @@ most people are used to thinking about matrices in row-major order, the
 three.js documentation shows matrices in row-major order. Just bear in
 mind that if you are reading the source code, you'll have to take the
 transpose of any matrices outlined here to make sense of the calculations.</p></div>
-				<h2>Code Example</h2>
-				<div translate="no"><pre><code class="language-js">const m = new THREE.Matrix();
-m.set( 11, 12, 13,
-       21, 22, 23,
-       31, 32, 33 );
-</code></pre></div>
 			</header>
 			<article>
 				<div class="container-overview">

+ 7 - 9
docs/pages/Matrix3.html.md

@@ -6,6 +6,13 @@ A Note on Row-Major and Column-Major Ordering:
 
 The constructor and [Matrix3#set](Matrix3.html#set) method take arguments in [row-major](https://en.wikipedia.org/wiki/Row-_and_column-major_order#Column-major_order) order, while internally they are stored in the [Matrix3#elements](Matrix3.html#elements) array in column-major order. This means that calling:
 
+```js
+const m = new THREE.Matrix();
+m.set( 11, 12, 13,
+       21, 22, 23,
+       31, 32, 33 );
+```
+
 will result in the elements array containing:
 
 ```js
@@ -16,15 +23,6 @@ m.elements = [ 11, 21, 31,
 
 and internally all calculations are performed using column-major ordering. However, as the actual ordering makes no difference mathematically and most people are used to thinking about matrices in row-major order, the three.js documentation shows matrices in row-major order. Just bear in mind that if you are reading the source code, you'll have to take the transpose of any matrices outlined here to make sense of the calculations.
 
-## Code Example
-
-```js
-const m = new THREE.Matrix();
-m.set( 11, 12, 13,
-       21, 22, 23,
-       31, 32, 33 );
-```
-
 ## Constructor
 
 ### new Matrix3( n11 : number, n12 : number, n13 : number, n21 : number, n22 : number, n23 : number, n31 : number, n32 : number, n33 : number )

+ 6 - 7
docs/pages/Matrix4.html

@@ -24,6 +24,12 @@ matrix. This is known as <code>applying</code> the matrix to the vector.</p>
 <a href="https://en.wikipedia.org/wiki/Row-_and_column-major_order#Column-major_order" target="_blank" rel="noopener">row-major</a>
 order, while internally they are stored in the <a href="Matrix3.html#elements">Matrix3#elements</a> array in column-major order.
 This means that calling:</p>
+<pre><code class="language-js">const m = new THREE.Matrix4();
+m.set( 11, 12, 13, 14,
+       21, 22, 23, 24,
+       31, 32, 33, 34,
+       41, 42, 43, 44 );
+</code></pre>
 <p>will result in the elements array containing:</p>
 <pre><code class="language-js">m.elements = [ 11, 21, 31, 41,
                12, 22, 32, 42,
@@ -36,13 +42,6 @@ most people are used to thinking about matrices in row-major order, the
 three.js documentation shows matrices in row-major order. Just bear in
 mind that if you are reading the source code, you'll have to take the
 transpose of any matrices outlined here to make sense of the calculations.</p></div>
-				<h2>Code Example</h2>
-				<div translate="no"><pre><code class="language-js">const m = new THREE.Matrix4();
-m.set( 11, 12, 13, 14,
-       21, 22, 23, 24,
-       31, 32, 33, 34,
-       41, 42, 43, 44 );
-</code></pre></div>
 			</header>
 			<article>
 				<div class="container-overview">

+ 8 - 10
docs/pages/Matrix4.html.md

@@ -10,6 +10,14 @@ A Note on Row-Major and Column-Major Ordering:
 
 The constructor and [Matrix3#set](Matrix3.html#set) method take arguments in [row-major](https://en.wikipedia.org/wiki/Row-_and_column-major_order#Column-major_order) order, while internally they are stored in the [Matrix3#elements](Matrix3.html#elements) array in column-major order. This means that calling:
 
+```js
+const m = new THREE.Matrix4();
+m.set( 11, 12, 13, 14,
+       21, 22, 23, 24,
+       31, 32, 33, 34,
+       41, 42, 43, 44 );
+```
+
 will result in the elements array containing:
 
 ```js
@@ -21,16 +29,6 @@ m.elements = [ 11, 21, 31, 41,
 
 and internally all calculations are performed using column-major ordering. However, as the actual ordering makes no difference mathematically and most people are used to thinking about matrices in row-major order, the three.js documentation shows matrices in row-major order. Just bear in mind that if you are reading the source code, you'll have to take the transpose of any matrices outlined here to make sense of the calculations.
 
-## Code Example
-
-```js
-const m = new THREE.Matrix4();
-m.set( 11, 12, 13, 14,
-       21, 22, 23, 24,
-       31, 32, 33, 34,
-       41, 42, 43, 44 );
-```
-
 ## Constructor
 
 ### new Matrix4( n11 : number, n12 : number, n13 : number, n14 : number, n21 : number, n22 : number, n23 : number, n24 : number, n31 : number, n32 : number, n33 : number, n34 : number, n41 : number, n42 : number, n43 : number, n44 : number )

+ 3 - 1
docs/pages/MeshLambertMaterial.html

@@ -132,7 +132,9 @@ other maps which only affect the light and shade of the material the
 displaced vertices can cast shadows, block other objects, and otherwise
 act as real geometry. The displacement texture is an image where the value
 of each pixel (white being the highest) is mapped against, and
-repositions, the vertices of the mesh.</p>
+repositions, the vertices of the mesh. For best results, pair a
+displacement map with a matching normal map, since the renderer can
+not recompute surface normals from the displaced vertices.</p>
 						<p>Default is <code>null</code>.</p>
 					</div>
 				</div>

+ 1 - 1
docs/pages/MeshLambertMaterial.html.md

@@ -74,7 +74,7 @@ Default is `0`.
 
 ### .displacementMap : Texture
 
-The displacement map affects the position of the mesh's vertices. Unlike other maps which only affect the light and shade of the material the displaced vertices can cast shadows, block other objects, and otherwise act as real geometry. The displacement texture is an image where the value of each pixel (white being the highest) is mapped against, and repositions, the vertices of the mesh.
+The displacement map affects the position of the mesh's vertices. Unlike other maps which only affect the light and shade of the material the displaced vertices can cast shadows, block other objects, and otherwise act as real geometry. The displacement texture is an image where the value of each pixel (white being the highest) is mapped against, and repositions, the vertices of the mesh. For best results, pair a displacement map with a matching normal map, since the renderer can not recompute surface normals from the displaced vertices.
 
 Default is `null`.
 

+ 3 - 1
docs/pages/MeshMatcapMaterial.html

@@ -102,7 +102,9 @@ other maps which only affect the light and shade of the material the
 displaced vertices can cast shadows, block other objects, and otherwise
 act as real geometry. The displacement texture is an image where the value
 of each pixel (white being the highest) is mapped against, and
-repositions, the vertices of the mesh.</p>
+repositions, the vertices of the mesh. For best results, pair a
+displacement map with a matching normal map, since the renderer can
+not recompute surface normals from the displaced vertices.</p>
 						<p>Default is <code>null</code>.</p>
 					</div>
 				</div>

+ 1 - 1
docs/pages/MeshMatcapMaterial.html.md

@@ -52,7 +52,7 @@ Default is `0`.
 
 ### .displacementMap : Texture
 
-The displacement map affects the position of the mesh's vertices. Unlike other maps which only affect the light and shade of the material the displaced vertices can cast shadows, block other objects, and otherwise act as real geometry. The displacement texture is an image where the value of each pixel (white being the highest) is mapped against, and repositions, the vertices of the mesh.
+The displacement map affects the position of the mesh's vertices. Unlike other maps which only affect the light and shade of the material the displaced vertices can cast shadows, block other objects, and otherwise act as real geometry. The displacement texture is an image where the value of each pixel (white being the highest) is mapped against, and repositions, the vertices of the mesh. For best results, pair a displacement map with a matching normal map, since the renderer can not recompute surface normals from the displaced vertices.
 
 Default is `null`.
 

+ 3 - 1
docs/pages/MeshNormalMaterial.html

@@ -77,7 +77,9 @@ other maps which only affect the light and shade of the material the
 displaced vertices can cast shadows, block other objects, and otherwise
 act as real geometry. The displacement texture is an image where the value
 of each pixel (white being the highest) is mapped against, and
-repositions, the vertices of the mesh.</p>
+repositions, the vertices of the mesh. For best results, pair a
+displacement map with a matching normal map, since the renderer can
+not recompute surface normals from the displaced vertices.</p>
 						<p>Default is <code>null</code>.</p>
 					</div>
 				</div>

+ 1 - 1
docs/pages/MeshNormalMaterial.html.md

@@ -36,7 +36,7 @@ Default is `0`.
 
 ### .displacementMap : Texture
 
-The displacement map affects the position of the mesh's vertices. Unlike other maps which only affect the light and shade of the material the displaced vertices can cast shadows, block other objects, and otherwise act as real geometry. The displacement texture is an image where the value of each pixel (white being the highest) is mapped against, and repositions, the vertices of the mesh.
+The displacement map affects the position of the mesh's vertices. Unlike other maps which only affect the light and shade of the material the displaced vertices can cast shadows, block other objects, and otherwise act as real geometry. The displacement texture is an image where the value of each pixel (white being the highest) is mapped against, and repositions, the vertices of the mesh. For best results, pair a displacement map with a matching normal map, since the renderer can not recompute surface normals from the displaced vertices.
 
 Default is `null`.
 

+ 3 - 1
docs/pages/MeshPhongMaterial.html

@@ -130,7 +130,9 @@ other maps which only affect the light and shade of the material the
 displaced vertices can cast shadows, block other objects, and otherwise
 act as real geometry. The displacement texture is an image where the value
 of each pixel (white being the highest) is mapped against, and
-repositions, the vertices of the mesh.</p>
+repositions, the vertices of the mesh. For best results, pair a
+displacement map with a matching normal map, since the renderer can
+not recompute surface normals from the displaced vertices.</p>
 						<p>Default is <code>null</code>.</p>
 					</div>
 				</div>

+ 1 - 1
docs/pages/MeshPhongMaterial.html.md

@@ -74,7 +74,7 @@ Default is `0`.
 
 ### .displacementMap : Texture
 
-The displacement map affects the position of the mesh's vertices. Unlike other maps which only affect the light and shade of the material the displaced vertices can cast shadows, block other objects, and otherwise act as real geometry. The displacement texture is an image where the value of each pixel (white being the highest) is mapped against, and repositions, the vertices of the mesh.
+The displacement map affects the position of the mesh's vertices. Unlike other maps which only affect the light and shade of the material the displaced vertices can cast shadows, block other objects, and otherwise act as real geometry. The displacement texture is an image where the value of each pixel (white being the highest) is mapped against, and repositions, the vertices of the mesh. For best results, pair a displacement map with a matching normal map, since the renderer can not recompute surface normals from the displaced vertices.
 
 Default is `null`.
 

+ 3 - 1
docs/pages/MeshStandardMaterial.html

@@ -137,7 +137,9 @@ other maps which only affect the light and shade of the material the
 displaced vertices can cast shadows, block other objects, and otherwise
 act as real geometry. The displacement texture is an image where the value
 of each pixel (white being the highest) is mapped against, and
-repositions, the vertices of the mesh.</p>
+repositions, the vertices of the mesh. For best results, pair a
+displacement map with a matching normal map, since the renderer can
+not recompute surface normals from the displaced vertices.</p>
 						<p>Default is <code>null</code>.</p>
 					</div>
 				</div>

+ 1 - 1
docs/pages/MeshStandardMaterial.html.md

@@ -77,7 +77,7 @@ Default is `0`.
 
 ### .displacementMap : Texture
 
-The displacement map affects the position of the mesh's vertices. Unlike other maps which only affect the light and shade of the material the displaced vertices can cast shadows, block other objects, and otherwise act as real geometry. The displacement texture is an image where the value of each pixel (white being the highest) is mapped against, and repositions, the vertices of the mesh.
+The displacement map affects the position of the mesh's vertices. Unlike other maps which only affect the light and shade of the material the displaced vertices can cast shadows, block other objects, and otherwise act as real geometry. The displacement texture is an image where the value of each pixel (white being the highest) is mapped against, and repositions, the vertices of the mesh. For best results, pair a displacement map with a matching normal map, since the renderer can not recompute surface normals from the displaced vertices.
 
 Default is `null`.
 

+ 3 - 1
docs/pages/MeshToonMaterial.html

@@ -114,7 +114,9 @@ other maps which only affect the light and shade of the material the
 displaced vertices can cast shadows, block other objects, and otherwise
 act as real geometry. The displacement texture is an image where the value
 of each pixel (white being the highest) is mapped against, and
-repositions, the vertices of the mesh.</p>
+repositions, the vertices of the mesh. For best results, pair a
+displacement map with a matching normal map, since the renderer can
+not recompute surface normals from the displaced vertices.</p>
 						<p>Default is <code>null</code>.</p>
 					</div>
 				</div>

+ 1 - 1
docs/pages/MeshToonMaterial.html.md

@@ -62,7 +62,7 @@ Default is `0`.
 
 ### .displacementMap : Texture
 
-The displacement map affects the position of the mesh's vertices. Unlike other maps which only affect the light and shade of the material the displaced vertices can cast shadows, block other objects, and otherwise act as real geometry. The displacement texture is an image where the value of each pixel (white being the highest) is mapped against, and repositions, the vertices of the mesh.
+The displacement map affects the position of the mesh's vertices. Unlike other maps which only affect the light and shade of the material the displaced vertices can cast shadows, block other objects, and otherwise act as real geometry. The displacement texture is an image where the value of each pixel (white being the highest) is mapped against, and repositions, the vertices of the mesh. For best results, pair a displacement map with a matching normal map, since the renderer can not recompute surface normals from the displaced vertices.
 
 Default is `null`.
 

+ 32 - 1
docs/pages/NodeBuilder.html

@@ -1413,7 +1413,7 @@ this method might be used to convert a simple float string <code>&quot;1.0&quot;
 							<dt class="tag-returns"><strong>Returns:</strong> The list of bindings.</dt>
 						</dl>
 					</div>
-					<h3 class="name name-method" id="getBufferAttributeFromNode" translate="no">.<a href="#getBufferAttributeFromNode">getBufferAttributeFromNode</a><span class="signature">( node : <span class="param-type"><a href="BufferAttributeNode.html">BufferAttributeNode</a></span>, type : <span class="param-type">string</span> )</span><span class="type-signature"> : <a href="NodeAttribute.html">NodeAttribute</a></span> </h3>
+					<h3 class="name name-method" id="getBufferAttributeFromNode" translate="no">.<a href="#getBufferAttributeFromNode">getBufferAttributeFromNode</a><span class="signature">( node : <span class="param-type"><a href="BufferAttributeNode.html">BufferAttributeNode</a></span>, type : <span class="param-type">string</span>, name : <span class="param-type">string</span> )</span><span class="type-signature"> : <a href="NodeAttribute.html">NodeAttribute</a></span> </h3>
 					<div class="method">
 						<div class="description">
 							<p>Returns an instance of <a href="NodeAttribute.html">NodeAttribute</a> for the given buffer attribute node.</p>
@@ -1436,6 +1436,15 @@ this method might be used to convert a simple float string <code>&quot;1.0&quot;
 										<p>The node type.</p>
 									</td>
 								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">name</strong>
+									</td>
+									<td class="description last">
+										<p>The name of the buffer attribute.</p>
+										<p>Default is <code>null</code>.</p>
+									</td>
+								</tr>
 							</tbody>
 						</table>
 						<dl class="details">
@@ -1947,6 +1956,28 @@ to the current node's properties in the setup stage and building those propertie
 							<dt class="tag-returns"><strong>Returns:</strong> The struct type attribute.</dt>
 						</dl>
 					</div>
+					<h3 class="name name-method" id="getOutputType" translate="no">.<a href="#getOutputType">getOutputType</a><span class="signature">( index : <span class="param-type">number</span> )</span><span class="type-signature"> : string</span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Returns the type of the color output based on the renderer's render target.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">index</strong>
+									</td>
+									<td class="description last">
+										<p>The index of the render target texture.</p>
+										<p>Default is <code>0</code>.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+						<dl class="details">
+							<dt class="tag-returns"><strong>Returns:</strong> The type.</dt>
+						</dl>
+					</div>
 					<h3 class="name name-method" id="getPropertyName" translate="no">.<a href="#getPropertyName">getPropertyName</a><span class="signature">( node : <span class="param-type"><a href="Node.html">Node</a></span>, shaderStage : <span class="param-type">'vertex' | 'fragment' | 'compute' | 'any'</span> )</span><span class="type-signature"> : string</span> </h3>
 					<div class="method">
 						<div class="description">

+ 19 - 1
docs/pages/NodeBuilder.html.md

@@ -766,7 +766,7 @@ Returns a list bindings of all shader stages separated by groups.
 
 **Returns:** The list of bindings.
 
-### .getBufferAttributeFromNode( node : BufferAttributeNode, type : string ) : NodeAttribute
+### .getBufferAttributeFromNode( node : BufferAttributeNode, type : string, name : string ) : NodeAttribute
 
 Returns an instance of [NodeAttribute](NodeAttribute.html) for the given buffer attribute node.
 
@@ -778,6 +778,12 @@ The buffer attribute node.
 
 The node type.
 
+**name**
+
+The name of the buffer attribute.
+
+Default is `null`.
+
 **Returns:** The node attribute.
 
 ### .getBuildStage() : 'setup' | 'analyze' | 'generate'
@@ -1042,6 +1048,18 @@ The output struct types.
 
 **Returns:** The struct type attribute.
 
+### .getOutputType( index : number ) : string
+
+Returns the type of the color output based on the renderer's render target.
+
+**index**
+
+The index of the render target texture.
+
+Default is `0`.
+
+**Returns:** The type.
+
 ### .getPropertyName( node : Node, shaderStage : 'vertex' | 'fragment' | 'compute' | 'any' ) : string
 
 Returns for the given node and shader stage the property name for the shader.

+ 6 - 4
docs/pages/PMREMGenerator.html

@@ -75,8 +75,9 @@ one of them will cause any others to also become unusable.</p>
 					<div class="method">
 						<div class="description">
 							<p>Generates a PMREM from an cubemap texture, which can be either LDR
-or HDR. The ideal input cube size is 256 x 256,
-as this matches best with the 256 x 256 cubemap output.</p>
+or HDR. The ideal input cube size is 256 x 256, as this matches best
+with the 256 x 256 cubemap output. The minimum supported input cube
+size is 16 x 16 per face.</p>
 						</div>
 						<table class="params">
 							<tbody>
@@ -107,8 +108,9 @@ as this matches best with the 256 x 256 cubemap output.</p>
 					<div class="method">
 						<div class="description">
 							<p>Generates a PMREM from an equirectangular texture, which can be either LDR
-or HDR. The ideal input image size is 1k (1024 x 512),
-as this matches best with the 256 x 256 cubemap output.</p>
+or HDR. The ideal input image size is 1k (1024 x 512), as this matches best
+with the 256 x 256 cubemap output. The minimum supported input image size
+is 64 x 32.</p>
 						</div>
 						<table class="params">
 							<tbody>

+ 2 - 2
docs/pages/PMREMGenerator.html.md

@@ -30,7 +30,7 @@ Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a
 
 ### .fromCubemap( cubemap : Texture, renderTarget : WebGLRenderTarget ) : WebGLRenderTarget
 
-Generates a PMREM from an cubemap texture, which can be either LDR or HDR. The ideal input cube size is 256 x 256, as this matches best with the 256 x 256 cubemap output.
+Generates a PMREM from an cubemap texture, which can be either LDR or HDR. The ideal input cube size is 256 x 256, as this matches best with the 256 x 256 cubemap output. The minimum supported input cube size is 16 x 16 per face.
 
 **cubemap**
 
@@ -46,7 +46,7 @@ Default is `null`.
 
 ### .fromEquirectangular( equirectangular : Texture, renderTarget : WebGLRenderTarget ) : WebGLRenderTarget
 
-Generates a PMREM from an equirectangular texture, which can be either LDR or HDR. The ideal input image size is 1k (1024 x 512), as this matches best with the 256 x 256 cubemap output.
+Generates a PMREM from an equirectangular texture, which can be either LDR or HDR. The ideal input image size is 1k (1024 x 512), as this matches best with the 256 x 256 cubemap output. The minimum supported input image size is 64 x 32.
 
 **equirectangular**
 

+ 2 - 3
docs/pages/PointsNodeMaterial.html

@@ -19,14 +19,13 @@
 <li>By rendering point primitives with <a href="Points.html">Points</a>. Since WebGPU only supports point primitives
 with a pixel size of <code>1</code>, it's not possible to define a size.</li>
 </ul>
+<pre><code class="language-js">const pointCloud = new THREE.Points( geometry, new THREE.PointsNodeMaterial() );
+</code></pre>
 <ul>
 <li>By rendering point primitives with Sprites. In this case, size is honored,
 see <a href="PointsNodeMaterial.html#sizeNode">PointsNodeMaterial#sizeNode</a>.</li>
 </ul>
 <pre><code class="language-js">const instancedPoints = new THREE.Sprite( new THREE.PointsNodeMaterial( { positionNode: instancedBufferAttribute( positionAttribute ) } ) );
-</code></pre></div>
-				<h2>Code Example</h2>
-				<div translate="no"><pre><code class="language-js">const pointCloud = new THREE.Points( geometry, new THREE.PointsNodeMaterial() );
 </code></pre></div>
 			</header>
 			<article>

+ 3 - 5
docs/pages/PointsNodeMaterial.html.md

@@ -8,16 +8,14 @@ This material can be used in two ways:
 
 *   By rendering point primitives with [Points](Points.html). Since WebGPU only supports point primitives with a pixel size of `1`, it's not possible to define a size.
 
-*   By rendering point primitives with Sprites. In this case, size is honored, see [PointsNodeMaterial#sizeNode](PointsNodeMaterial.html#sizeNode).
-
 ```js
-const instancedPoints = new THREE.Sprite( new THREE.PointsNodeMaterial( { positionNode: instancedBufferAttribute( positionAttribute ) } ) );
+const pointCloud = new THREE.Points( geometry, new THREE.PointsNodeMaterial() );
 ```
 
-## Code Example
+*   By rendering point primitives with Sprites. In this case, size is honored, see [PointsNodeMaterial#sizeNode](PointsNodeMaterial.html#sizeNode).
 
 ```js
-const pointCloud = new THREE.Points( geometry, new THREE.PointsNodeMaterial() );
+const instancedPoints = new THREE.Sprite( new THREE.PointsNodeMaterial( { positionNode: instancedBufferAttribute( positionAttribute ) } ) );
 ```
 
 ## Constructor

+ 35 - 0
docs/pages/RapierPhysics.html

@@ -168,6 +168,41 @@ The object can be used to store the mass and restitution of the mesh. E.g.:</p>
 							</tbody>
 						</table>
 					</div>
+					<h3 class="name name-method" id="applyImpulse" translate="no">.<a href="#applyImpulse">applyImpulse</a><span class="signature">( mesh : <span class="param-type"><a href="Mesh.html">Mesh</a></span>, impulse : <span class="param-type"><a href="Vector3.html">Vector3</a></span>, index : <span class="param-type">number</span> )</span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Applies an impulse to the given mesh which is part of the physics simulation.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">mesh</strong>
+									</td>
+									<td class="description last">
+										<p>The mesh to apply the impulse to.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">impulse</strong>
+									</td>
+									<td class="description last">
+										<p>The impulse to apply.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">index</strong>
+									</td>
+									<td class="description last">
+										<p>If the mesh is instanced, the index represents the instanced ID.</p>
+										<p>Default is <code>0</code>.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+					</div>
 					<h3 class="name name-method" id="removeMesh" translate="no">.<a href="#removeMesh">removeMesh</a><span class="signature">( mesh : <span class="param-type"><a href="Mesh.html">Mesh</a></span> )</span> </h3>
 					<div class="method">
 						<div class="description">

+ 18 - 0
docs/pages/RapierPhysics.html.md

@@ -90,6 +90,24 @@ box.userData.physics = { mass: 1, restitution: 0 };
 
 The scene or any type of 3D object to add.
 
+### .applyImpulse( mesh : Mesh, impulse : Vector3, index : number )
+
+Applies an impulse to the given mesh which is part of the physics simulation.
+
+**mesh**
+
+The mesh to apply the impulse to.
+
+**impulse**
+
+The impulse to apply.
+
+**index**
+
+If the mesh is instanced, the index represents the instanced ID.
+
+Default is `0`.
+
 ### .removeMesh( mesh : Mesh )
 
 Removes the given mesh from this physics simulation.

+ 22 - 0
docs/pages/Reflector.html

@@ -84,6 +84,28 @@ is in view or not.</p>
 method whenever this instance is no longer used in your app.</p>
 						</div>
 					</div>
+					<h3 class="name name-method" id="getReflectionCamera" translate="no">.<a href="#getReflectionCamera">getReflectionCamera</a><span class="signature">( camera : <span class="param-type"><a href="Camera.html">Camera</a></span> )</span><span class="type-signature"> : <a href="Camera.html">Camera</a></span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Returns a reflection camera for the given camera. The reflection camera is used to
+render the scene from the reflector's view so correct reflections can be produced.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">camera</strong>
+									</td>
+									<td class="description last">
+										<p>The scene's camera.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+						<dl class="details">
+							<dt class="tag-returns"><strong>Returns:</strong> The corresponding reflection camera.</dt>
+						</dl>
+					</div>
 					<h3 class="name name-method" id="getRenderTarget" translate="no">.<a href="#getRenderTarget">getRenderTarget</a><span class="signature">()</span><span class="type-signature"> : <a href="WebGLRenderTarget.html">WebGLRenderTarget</a></span> </h3>
 					<div class="method">
 						<div class="description">

+ 10 - 0
docs/pages/Reflector.html.md

@@ -61,6 +61,16 @@ Default is `true`.
 
 Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app.
 
+### .getReflectionCamera( camera : Camera ) : Camera
+
+Returns a reflection camera for the given camera. The reflection camera is used to render the scene from the reflector's view so correct reflections can be produced.
+
+**camera**
+
+The scene's camera.
+
+**Returns:** The corresponding reflection camera.
+
 ### .getRenderTarget() : WebGLRenderTarget
 
 Returns the reflector's internal render target.

+ 21 - 1
docs/pages/RenderTarget.html

@@ -161,6 +161,15 @@ this render target or not.</p>
 Has at least a single entry for the default color attachment.</p>
 					</div>
 				</div>
+				<div class="member">
+					<h3 class="name" id="useArrayDepthTexture" translate="no">.<a href="#useArrayDepthTexture">useArrayDepthTexture</a><span class="type-signature"> : boolean</span> </h3>
+					<div class="description">
+						<p>Whether to create the depth texture as an array texture for per-layer depth testing.
+This is separate from multiview so layered render targets can use array depth without
+the multiview extension.</p>
+						<p>Default is <code>false</code>.</p>
+					</div>
+				</div>
 				<div class="member">
 					<h3 class="name" id="viewport" translate="no">.<a href="#viewport">viewport</a><span class="type-signature"> : <a href="Vector4.html">Vector4</a></span> </h3>
 					<div class="description">
@@ -467,7 +476,18 @@ method whenever this instance is no longer used in your app.</p>
 <span class="param-type">boolean</span>
 				</td>
 			<td class="description last">
-				<p>Whether this target is used for multiview rendering.</p>
+				<p>Whether this target is used for multiview rendering (WebGL OVR_multiview2 extension).</p>
+						<p>Default is <code>false</code>.</p>
+			</td>
+		</tr>
+		<tr>
+				<td class="name">
+					<strong>useArrayDepthTexture</strong>
+						<br>
+<span class="param-type">boolean</span>
+				</td>
+			<td class="description last">
+				<p>Whether to create the depth texture as an array texture for per-layer depth testing. This is separate from multiview so layered render targets can use array depth without the multiview extension.</p>
 						<p>Default is <code>false</code>.</p>
 			</td>
 		</tr>

+ 14 - 1
docs/pages/RenderTarget.html.md

@@ -110,6 +110,12 @@ The texture representing the default color attachment.
 
 An array of textures. Each color attachment is represented as a separate texture. Has at least a single entry for the default color attachment.
 
+### .useArrayDepthTexture : boolean
+
+Whether to create the depth texture as an array texture for per-layer depth testing. This is separate from multiview so layered render targets can use array depth without the multiview extension.
+
+Default is `false`.
+
 ### .viewport : Vector4
 
 A rectangular area representing the render target's viewport.
@@ -301,7 +307,14 @@ Default is `1`.
 **multiview**  
 boolean
 
-Whether this target is used for multiview rendering.
+Whether this target is used for multiview rendering (WebGL OVR\_multiview2 extension).
+
+Default is `false`.
+
+**useArrayDepthTexture**  
+boolean
+
+Whether to create the depth texture as an array texture for per-layer depth testing. This is separate from multiview so layered render targets can use array depth without the multiview extension.
 
 Default is `false`.
 

+ 10 - 0
docs/pages/Renderer.html

@@ -246,6 +246,16 @@ If this is the case, the renderer allocates an internal render target for that p
 						<p>A callback function that defines what should happen when a device/context lost occurs.</p>
 					</div>
 				</div>
+				<div class="member">
+					<h3 class="name" id="onError" translate="no">.<a href="#onError">onError</a><span class="type-signature"> : function</span> </h3>
+					<div class="description">
+						<p>A callback function that defines what should happen when an uncaptured
+backend error is reported (e.g. a WebGPU validation/out-of-memory/internal
+error raised outside an error scope). Applications can override this to
+surface errors in their own UI without letting them escalate to a device
+loss. The default implementation logs to the console.</p>
+					</div>
+				</div>
 				<div class="member">
 					<h3 class="name" id="opaque" translate="no">.<a href="#opaque">opaque</a><span class="type-signature"> : boolean</span> </h3>
 					<div class="description">

+ 4 - 0
docs/pages/Renderer.html.md

@@ -147,6 +147,10 @@ Returns `true` if a framebuffer target is needed to perform tone mapping or colo
 
 A callback function that defines what should happen when a device/context lost occurs.
 
+### .onError : function
+
+A callback function that defines what should happen when an uncaptured backend error is reported (e.g. a WebGPU validation/out-of-memory/internal error raised outside an error scope). Applications can override this to surface errors in their own UI without letting them escalate to a device loss. The default implementation logs to the console.
+
 ### .opaque : boolean
 
 Whether the renderer should render opaque render objects or not.

+ 0 - 14
docs/pages/SSAAPassNode.html

@@ -53,20 +53,6 @@ its brute-force approach of re-rendering the entire scene multiple times.</p>
 					</div>
 				</div>
 				<h2 class="subsection-title">Properties</h2>
-				<div class="member">
-					<h3 class="name" id="clearAlpha" translate="no">.<a href="#clearAlpha">clearAlpha</a><span class="type-signature"> : number</span> </h3>
-					<div class="description">
-						<p>The clear alpha of the pass.</p>
-						<p>Default is <code>0</code>.</p>
-					</div>
-				</div>
-				<div class="member">
-					<h3 class="name" id="clearColor" translate="no">.<a href="#clearColor">clearColor</a><span class="type-signature"> : <a href="Color.html">Color</a></span> </h3>
-					<div class="description">
-						<p>The clear color of the pass.</p>
-						<p>Default is <code>0x000000</code>.</p>
-					</div>
-				</div>
 				<div class="member">
 					<h3 class="name" id="isSSAAPassNode" translate="no">.<a href="#isSSAAPassNode">isSSAAPassNode</a><span class="type-signature"> : boolean</span> <span class="type-signature">(readonly) </span></h3>
 					<div class="description">

+ 0 - 12
docs/pages/SSAAPassNode.html.md

@@ -32,18 +32,6 @@ The camera to render the scene with.
 
 ## Properties
 
-### .clearAlpha : number
-
-The clear alpha of the pass.
-
-Default is `0`.
-
-### .clearColor : Color
-
-The clear color of the pass.
-
-Default is `0x000000`.
-
 ### .isSSAAPassNode : boolean (readonly)
 
 This flag can be used for type testing.

+ 4 - 5
docs/pages/STLLoader.html

@@ -21,6 +21,10 @@
 <li>There is perhaps some question as to how valid it is to always assume little-endian-ness.</li>
 <li>ASCII decoding assumes file is UTF-8.</li>
 </ul>
+<pre><code class="language-js">const loader = new STLLoader();
+const geometry = await loader.loadAsync( './models/stl/slotted_disk.stl' )
+scene.add( new THREE.Mesh( geometry ) );
+</code></pre>
 <p>For binary STLs geometry might contain colors for vertices. To use it:</p>
 <pre><code class="language-js">// use the same code to load STL as above
 if ( geometry.hasColors ) {
@@ -38,11 +42,6 @@ for ( let i = 0; i &lt; nGeometryGroups; i ++ ) {
 	materials.push( material );
 }
 const mesh = new THREE.Mesh(geometry, materials);
-</code></pre></div>
-				<h2>Code Example</h2>
-				<div translate="no"><pre><code class="language-js">const loader = new STLLoader();
-const geometry = await loader.loadAsync( './models/stl/slotted_disk.stl' )
-scene.add( new THREE.Mesh( geometry ) );
 </code></pre></div>
 			</header>
 			<article>

+ 6 - 8
docs/pages/STLLoader.html.md

@@ -12,6 +12,12 @@ Limitations:
 *   There is perhaps some question as to how valid it is to always assume little-endian-ness.
 *   ASCII decoding assumes file is UTF-8.
 
+```js
+const loader = new STLLoader();
+const geometry = await loader.loadAsync( './models/stl/slotted_disk.stl' )
+scene.add( new THREE.Mesh( geometry ) );
+```
+
 For binary STLs geometry might contain colors for vertices. To use it:
 
 ```js
@@ -34,14 +40,6 @@ for ( let i = 0; i < nGeometryGroups; i ++ ) {
 const mesh = new THREE.Mesh(geometry, materials);
 ```
 
-## Code Example
-
-```js
-const loader = new STLLoader();
-const geometry = await loader.loadAsync( './models/stl/slotted_disk.stl' )
-scene.add( new THREE.Mesh( geometry ) );
-```
-
 ## Import
 
 STLLoader is an addon, and must be imported explicitly, see [Installation#Addons](https://threejs.org/manual/#en/installation).

+ 45 - 0
docs/pages/SVGLoader.html

@@ -152,6 +152,27 @@ SVG XML document.</dt>
 						</dl>
 					</div>
 				<h2 class="subsection-title">Static Methods</h2>
+					<h3 class="name name-method" id=".createFillMaterial" translate="no">.<a href="#.createFillMaterial">createFillMaterial</a><span class="signature">( shapePath : <span class="param-type"><a href="ShapePath.html">ShapePath</a></span> )</span><span class="type-signature"> : <a href="MeshBasicMaterial.html">MeshBasicMaterial</a></span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Creates a material for rendering the fill of the given path.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">shapePath</strong>
+									</td>
+									<td class="description last">
+										<p>The shape path.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+						<dl class="details">
+							<dt class="tag-returns"><strong>Returns:</strong> The fill material. <code>null</code> if the path has no fill.</dt>
+						</dl>
+					</div>
 					<h3 class="name name-method" id=".createShapes" translate="no">.<a href="#.createShapes">createShapes</a><span class="signature">( shapePath : <span class="param-type"><a href="ShapePath.html">ShapePath</a></span> )</span><span class="type-signature"> : Array.&lt;<a href="Shape.html">Shape</a>></span> </h3>
 					<div class="method">
 						<div class="description">
@@ -169,10 +190,34 @@ SVG XML document.</dt>
 								</tr>
 							</tbody>
 						</table>
+						<dl class="details">
+							<dt class="important tag-deprecated"><strong>Deprecated:</strong> since 185.</dt>
+						</dl>
 						<dl class="details">
 							<dt class="tag-returns"><strong>Returns:</strong> An array of shapes.</dt>
 						</dl>
 					</div>
+					<h3 class="name name-method" id=".createStrokeMaterial" translate="no">.<a href="#.createStrokeMaterial">createStrokeMaterial</a><span class="signature">( shapePath : <span class="param-type"><a href="ShapePath.html">ShapePath</a></span> )</span><span class="type-signature"> : <a href="MeshBasicMaterial.html">MeshBasicMaterial</a></span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Creates a material for rendering the stroke of the given path.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">shapePath</strong>
+									</td>
+									<td class="description last">
+										<p>The shape path.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+						<dl class="details">
+							<dt class="tag-returns"><strong>Returns:</strong> The stroke material. <code>null</code> if the path has no stroke.</dt>
+						</dl>
+					</div>
 					<h3 class="name name-method" id=".getStrokeStyle" translate="no">.<a href="#.getStrokeStyle">getStrokeStyle</a><span class="signature">( width : <span class="param-type">number</span>, color : <span class="param-type">string</span>, lineJoin : <span class="param-type">'round' | 'bevel' | 'miter' | 'miter-limit'</span>, lineCap : <span class="param-type">'round' | 'square' | 'butt'</span>, miterLimit : <span class="param-type">number</span> )</span><span class="type-signature"> : Object</span> </h3>
 					<div class="method">
 						<div class="description">

+ 22 - 0
docs/pages/SVGLoader.html.md

@@ -101,6 +101,16 @@ The raw SVG data as a string.
 
 ## Static Methods
 
+### .createFillMaterial( shapePath : ShapePath ) : MeshBasicMaterial
+
+Creates a material for rendering the fill of the given path.
+
+**shapePath**
+
+The shape path.
+
+**Returns:** The fill material. `null` if the path has no fill.
+
 ### .createShapes( shapePath : ShapePath ) : Array.<Shape>
 
 Creates from the given shape path and array of shapes.
@@ -109,8 +119,20 @@ Creates from the given shape path and array of shapes.
 
 The shape path.
 
+**Deprecated:** since 185.
+
 **Returns:** An array of shapes.
 
+### .createStrokeMaterial( shapePath : ShapePath ) : MeshBasicMaterial
+
+Creates a material for rendering the stroke of the given path.
+
+**shapePath**
+
+The shape path.
+
+**Returns:** The stroke material. `null` if the path has no stroke.
+
 ### .getStrokeStyle( width : number, color : string, lineJoin : 'round' | 'bevel' | 'miter' | 'miter-limit', lineCap : 'round' | 'square' | 'butt', miterLimit : number ) : Object
 
 Returns a stroke style object from the given parameters.

+ 8 - 14
docs/pages/ShapePath.html

@@ -46,6 +46,13 @@ shapes. It is specifically used in context of fonts and SVG.</p></div>
 						<p>Default is <code>null</code>.</p>
 					</div>
 				</div>
+				<div class="member">
+					<h3 class="name" id="userData" translate="no">.<a href="#userData">userData</a><span class="type-signature"> : Object</span> </h3>
+					<div class="description">
+						<p>An object that can be used to store custom data about the shape path.
+Mainly used by SVGLoader to store style information.</p>
+					</div>
+				</div>
 				<h2 class="subsection-title">Methods</h2>
 					<h3 class="name name-method" id="bezierCurveTo" translate="no">.<a href="#bezierCurveTo">bezierCurveTo</a><span class="signature">( aCP1x : <span class="param-type">number</span>, aCP1y : <span class="param-type">number</span>, aCP2x : <span class="param-type">number</span>, aCP2y : <span class="param-type">number</span>, aX : <span class="param-type">number</span>, aY : <span class="param-type">number</span> )</span><span class="type-signature"> : <a href="ShapePath.html">ShapePath</a></span> </h3>
 					<div class="method">
@@ -236,24 +243,11 @@ the current point with the given list of points.</p>
 							<dt class="tag-returns"><strong>Returns:</strong> A reference to this shape path.</dt>
 						</dl>
 					</div>
-					<h3 class="name name-method" id="toShapes" translate="no">.<a href="#toShapes">toShapes</a><span class="signature">( isCCW : <span class="param-type">boolean</span> )</span><span class="type-signature"> : Array.&lt;<a href="Shape.html">Shape</a>></span> </h3>
+					<h3 class="name name-method" id="toShapes" translate="no">.<a href="#toShapes">toShapes</a><span class="signature">()</span><span class="type-signature"> : Array.&lt;<a href="Shape.html">Shape</a>></span> </h3>
 					<div class="method">
 						<div class="description">
 							<p>Converts the paths into an array of shapes.</p>
 						</div>
-						<table class="params">
-							<tbody>
-								<tr>
-									<td class="name">
-										<strong translate="no">isCCW</strong>
-									</td>
-									<td class="description last">
-										<p>By default solid shapes are  defined clockwise (CW) and holes are defined counterclockwise (CCW).
-If this flag is set to <code>true</code>, then those are flipped.</p>
-									</td>
-								</tr>
-							</tbody>
-						</table>
 						<dl class="details">
 							<dt class="tag-returns"><strong>Returns:</strong> An array of shapes.</dt>
 						</dl>

+ 5 - 5
docs/pages/ShapePath.html.md

@@ -26,6 +26,10 @@ The paths that have been generated for this shape.
 
 Default is `null`.
 
+### .userData : Object
+
+An object that can be used to store custom data about the shape path. Mainly used by SVGLoader to store style information.
+
 ## Methods
 
 ### .bezierCurveTo( aCP1x : number, aCP1y : number, aCP2x : number, aCP2y : number, aX : number, aY : number ) : ShapePath
@@ -118,14 +122,10 @@ An array of points in 2D space.
 
 **Returns:** A reference to this shape path.
 
-### .toShapes( isCCW : boolean ) : Array.<Shape>
+### .toShapes() : Array.<Shape>
 
 Converts the paths into an array of shapes.
 
-**isCCW**
-
-By default solid shapes are defined clockwise (CW) and holes are defined counterclockwise (CCW). If this flag is set to `true`, then those are flipped.
-
 **Returns:** An array of shapes.
 
 ## Source

+ 4 - 5
docs/pages/Sky.html

@@ -22,17 +22,16 @@ When using <a href="WebGPURenderer.html">WebGPURenderer</a>, use <a href="SkyMes
 <li><a href="http://simonwallner.at/project/atmospheric-scattering/" target="_blank" rel="noopener">http://simonwallner.at/project/atmospheric-scattering/</a></li>
 <li><a href="http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR" target="_blank" rel="noopener">http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR</a></li>
 </ul>
+<pre><code class="language-js">const sky = new Sky();
+sky.scale.setScalar( 10000 );
+scene.add( sky );
+</code></pre>
 <p>It can be useful to hide the sun disc when generating an environment map to avoid artifacts</p>
 <pre><code class="language-js">// disable before rendering environment map
 sky.material.uniforms.showSunDisc.value = false;
 // ...
 // re-enable before scene sky box rendering
 sky.material.uniforms.showSunDisc.value = true;
-</code></pre></div>
-				<h2>Code Example</h2>
-				<div translate="no"><pre><code class="language-js">const sky = new Sky();
-sky.scale.setScalar( 10000 );
-scene.add( sky );
 </code></pre></div>
 			</header>
 			<article>

+ 6 - 8
docs/pages/Sky.html.md

@@ -11,6 +11,12 @@ More references:
 *   [http://simonwallner.at/project/atmospheric-scattering/](http://simonwallner.at/project/atmospheric-scattering/)
 *   [http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR](http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR)
 
+```js
+const sky = new Sky();
+sky.scale.setScalar( 10000 );
+scene.add( sky );
+```
+
 It can be useful to hide the sun disc when generating an environment map to avoid artifacts
 
 ```js
@@ -21,14 +27,6 @@ sky.material.uniforms.showSunDisc.value = false;
 sky.material.uniforms.showSunDisc.value = true;
 ```
 
-## Code Example
-
-```js
-const sky = new Sky();
-sky.scale.setScalar( 10000 );
-scene.add( sky );
-```
-
 ## Import
 
 Sky is an addon, and must be imported explicitly, see [Installation#Addons](https://threejs.org/manual/#en/installation).

+ 4 - 5
docs/pages/SkyMesh.html

@@ -22,17 +22,16 @@ When using <a href="WebGLRenderer.html">WebGLRenderer</a>, use <a href="Sky.html
 <li><a href="http://simonwallner.at/project/atmospheric-scattering/" target="_blank" rel="noopener">http://simonwallner.at/project/atmospheric-scattering/</a></li>
 <li><a href="http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR" target="_blank" rel="noopener">http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR</a></li>
 </ul>
+<pre><code class="language-js">const sky = new SkyMesh();
+sky.scale.setScalar( 10000 );
+scene.add( sky );
+</code></pre>
 <p>It can be useful to hide the sun disc when generating an environment map to avoid artifacts</p>
 <pre><code class="language-js">// disable before rendering environment map
 sky.showSunDisc.value = false;
 // ...
 // re-enable before scene sky box rendering
 sky.showSunDisc.value = true;
-</code></pre></div>
-				<h2>Code Example</h2>
-				<div translate="no"><pre><code class="language-js">const sky = new SkyMesh();
-sky.scale.setScalar( 10000 );
-scene.add( sky );
 </code></pre></div>
 			</header>
 			<article>

+ 6 - 8
docs/pages/SkyMesh.html.md

@@ -11,6 +11,12 @@ More references:
 *   [http://simonwallner.at/project/atmospheric-scattering/](http://simonwallner.at/project/atmospheric-scattering/)
 *   [http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR](http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR)
 
+```js
+const sky = new SkyMesh();
+sky.scale.setScalar( 10000 );
+scene.add( sky );
+```
+
 It can be useful to hide the sun disc when generating an environment map to avoid artifacts
 
 ```js
@@ -21,14 +27,6 @@ sky.showSunDisc.value = false;
 sky.showSunDisc.value = true;
 ```
 
-## Code Example
-
-```js
-const sky = new SkyMesh();
-sky.scale.setScalar( 10000 );
-scene.add( sky );
-```
-
 ## Import
 
 SkyMesh is an addon, and must be imported explicitly, see [Installation#Addons](https://threejs.org/manual/#en/installation).

+ 2 - 2
docs/pages/StackNode.html

@@ -239,8 +239,8 @@ The last parameter must be the callback method that should be executed in the <c
 										<strong translate="no">index</strong>
 									</td>
 									<td class="description last">
-										<p>The index where the node should be added.</p>
-										<p>Default is <code>this.nodes.length</code>.</p>
+										<p>The index of the node. If not specified, the node will be added to the end of the stack.</p>
+										<p>Default is <code>-1</code>.</p>
 									</td>
 								</tr>
 							</tbody>

+ 2 - 2
docs/pages/StackNode.html.md

@@ -124,9 +124,9 @@ The node to add.
 
 **index**
 
-The index where the node should be added.
+The index of the node. If not specified, the node will be added to the end of the stack.
 
-Default is `this.nodes.length`.
+Default is `-1`.
 
 **Returns:** A reference to this stack node.
 

+ 175 - 0
docs/pages/StorageTexture3DNode.html

@@ -0,0 +1,175 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+	<meta charset="utf-8">
+	<title>StorageTexture3DNode - Three.js Docs</title>
+	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+	<script src="../scripts/highlight.min.js"></script>
+	<link type="text/css" rel="stylesheet" href="../styles/highlight-three.css">
+	<link type="text/css" rel="stylesheet" href="../styles/page.css">
+</head>
+<body>
+		<p class="inheritance" translate="no"><a href="EventDispatcher.html">EventDispatcher</a> → <a href="Node.html">Node</a> → <a href="InputNode.html">InputNode</a> → <a href="UniformNode.html">UniformNode</a> → <a href="TextureNode.html">TextureNode</a> → <a href="StorageTextureNode.html">StorageTextureNode</a> → </p>
+	<h1 translate="no">StorageTexture3DNode</h1>
+		<section>
+			<header>
+				<div class="class-description"><p>This special version of a texture node can be used to
+write data into a 3D storage texture with a compute shader.</p></div>
+			</header>
+			<article>
+				<div class="container-overview">
+					<h2>Constructor</h2>
+					<h3 class="name name-method" id="StorageTexture3DNode" translate="no">new <a href="#StorageTexture3DNode">StorageTexture3DNode</a><span class="signature">( value : <span class="param-type"><a href="Storage3DTexture.html">Storage3DTexture</a></span>, uvNode : <span class="param-type"><a href="Node.html">Node</a>.&lt;vec3></span>, storeNode : <span class="param-type"><a href="Node.html">Node</a></span> )</span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Constructs a new 3D storage texture node.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">value</strong>
+									</td>
+									<td class="description last">
+										<p>The 3D storage texture.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">uvNode</strong>
+									</td>
+									<td class="description last">
+										<p>The uv node.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">storeNode</strong>
+									</td>
+									<td class="description last">
+										<p>The value node that should be stored in the texture.</p>
+										<p>Default is <code>null</code>.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+					</div>
+				</div>
+				<h2 class="subsection-title">Properties</h2>
+				<div class="member">
+					<h3 class="name" id="isStorageTexture3DNode" translate="no">.<a href="#isStorageTexture3DNode">isStorageTexture3DNode</a><span class="type-signature"> : boolean</span> <span class="type-signature">(readonly) </span></h3>
+					<div class="description">
+						<p>This flag can be used for type testing.</p>
+						<p>Default is <code>true</code>.</p>
+					</div>
+				</div>
+				<h2 class="subsection-title">Methods</h2>
+					<h3 class="name name-method" id="generateOffset" translate="no">.<a href="#generateOffset">generateOffset</a><span class="signature">( builder : <span class="param-type"><a href="NodeBuilder.html">NodeBuilder</a></span>, offsetNode : <span class="param-type"><a href="Node.html">Node</a></span> )</span><span class="type-signature"> : string</span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Generates the offset code snippet.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">builder</strong>
+									</td>
+									<td class="description last">
+										<p>The current node builder.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">offsetNode</strong>
+									</td>
+									<td class="description last">
+										<p>The offset node to generate code for.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+						<dl class="details">
+							<dt class="tag-overrides"><strong>Overrides:</strong> <a href="StorageTextureNode.html#generateOffset">StorageTextureNode#generateOffset</a></dt>
+						</dl>
+						<dl class="details">
+							<dt class="tag-returns"><strong>Returns:</strong> The generated code snippet.</dt>
+						</dl>
+					</div>
+					<h3 class="name name-method" id="generateUV" translate="no">.<a href="#generateUV">generateUV</a><span class="signature">( builder : <span class="param-type"><a href="NodeBuilder.html">NodeBuilder</a></span>, uvNode : <span class="param-type"><a href="Node.html">Node</a></span> )</span><span class="type-signature"> : string</span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Generates the uv code snippet.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">builder</strong>
+									</td>
+									<td class="description last">
+										<p>The current node builder.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">uvNode</strong>
+									</td>
+									<td class="description last">
+										<p>The uv node to generate code for.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+						<dl class="details">
+							<dt class="tag-overrides"><strong>Overrides:</strong> <a href="StorageTextureNode.html#generateUV">StorageTextureNode#generateUV</a></dt>
+						</dl>
+						<dl class="details">
+							<dt class="tag-returns"><strong>Returns:</strong> The generated code snippet.</dt>
+						</dl>
+					</div>
+					<h3 class="name name-method" id="getDefaultUV" translate="no">.<a href="#getDefaultUV">getDefaultUV</a><span class="signature">()</span><span class="type-signature"> : <a href="Node.html">Node</a>.&lt;vec3></span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Returns a default uv node which is in context of 3D textures a three-dimensional
+uv node.</p>
+						</div>
+						<dl class="details">
+							<dt class="tag-overrides"><strong>Overrides:</strong> <a href="StorageTextureNode.html#getDefaultUV">StorageTextureNode#getDefaultUV</a></dt>
+						</dl>
+						<dl class="details">
+							<dt class="tag-returns"><strong>Returns:</strong> The default uv node.</dt>
+						</dl>
+					</div>
+					<h3 class="name name-method" id="setUpdateMatrix" translate="no">.<a href="#setUpdateMatrix">setUpdateMatrix</a><span class="signature">( value : <span class="param-type">boolean</span> )</span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Overwritten with an empty implementation since the <code>updateMatrix</code> flag is ignored
+for 3D textures. The uv transformation matrix is not applied to 3D textures.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">value</strong>
+									</td>
+									<td class="description last">
+										<p>The update toggle.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+						<dl class="details">
+							<dt class="tag-overrides"><strong>Overrides:</strong> <a href="StorageTextureNode.html#setUpdateMatrix">StorageTextureNode#setUpdateMatrix</a></dt>
+						</dl>
+					</div>
+				<h2 class="subsection-title">Source</h2>
+				<p>
+					<a href="https://github.com/mrdoob/three.js/blob/master/src/nodes/accessors/StorageTexture3DNode.js" translate="no" target="_blank" rel="noopener">src/nodes/accessors/StorageTexture3DNode.js</a>
+				</p>
+			</article>
+		</section>
+<script src="../scripts/linenumber.js"></script>
+<script src="../scripts/page.js"></script>
+</body>
+</html>

+ 89 - 0
docs/pages/StorageTexture3DNode.html.md

@@ -0,0 +1,89 @@
+*Inheritance: EventDispatcher → Node → InputNode → UniformNode → TextureNode → StorageTextureNode →*
+
+# StorageTexture3DNode
+
+This special version of a texture node can be used to write data into a 3D storage texture with a compute shader.
+
+## Constructor
+
+### new StorageTexture3DNode( value : Storage3DTexture, uvNode : Node.<vec3>, storeNode : Node )
+
+Constructs a new 3D storage texture node.
+
+**value**
+
+The 3D storage texture.
+
+**uvNode**
+
+The uv node.
+
+**storeNode**
+
+The value node that should be stored in the texture.
+
+Default is `null`.
+
+## Properties
+
+### .isStorageTexture3DNode : boolean (readonly)
+
+This flag can be used for type testing.
+
+Default is `true`.
+
+## Methods
+
+### .generateOffset( builder : NodeBuilder, offsetNode : Node ) : string
+
+Generates the offset code snippet.
+
+**builder**
+
+The current node builder.
+
+**offsetNode**
+
+The offset node to generate code for.
+
+**Overrides:** [StorageTextureNode#generateOffset](StorageTextureNode.html#generateOffset)
+
+**Returns:** The generated code snippet.
+
+### .generateUV( builder : NodeBuilder, uvNode : Node ) : string
+
+Generates the uv code snippet.
+
+**builder**
+
+The current node builder.
+
+**uvNode**
+
+The uv node to generate code for.
+
+**Overrides:** [StorageTextureNode#generateUV](StorageTextureNode.html#generateUV)
+
+**Returns:** The generated code snippet.
+
+### .getDefaultUV() : Node.<vec3>
+
+Returns a default uv node which is in context of 3D textures a three-dimensional uv node.
+
+**Overrides:** [StorageTextureNode#getDefaultUV](StorageTextureNode.html#getDefaultUV)
+
+**Returns:** The default uv node.
+
+### .setUpdateMatrix( value : boolean )
+
+Overwritten with an empty implementation since the `updateMatrix` flag is ignored for 3D textures. The uv transformation matrix is not applied to 3D textures.
+
+**value**
+
+The update toggle.
+
+**Overrides:** [StorageTextureNode#setUpdateMatrix](StorageTextureNode.html#setUpdateMatrix)
+
+## Source
+
+[src/nodes/accessors/StorageTexture3DNode.js](https://github.com/mrdoob/three.js/blob/master/src/nodes/accessors/StorageTexture3DNode.js)

+ 56 - 0
docs/pages/StorageTextureNode.html

@@ -264,6 +264,32 @@ is defined, the texture node is generated as normal texture.</p>
 							<dt class="tag-returns"><strong>Returns:</strong> The input type.</dt>
 						</dl>
 					</div>
+					<h3 class="name name-method" id="getTransformedUV" translate="no">.<a href="#getTransformedUV">getTransformedUV</a><span class="signature">( uvNode : <span class="param-type"><a href="Node.html">Node</a></span> )</span><span class="type-signature"> : <a href="Node.html">Node</a></span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Overwrites the default implementation since storage texture
+coordinates are texel coordinates and should not be transformed
+by the texture uv matrix.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">uvNode</strong>
+									</td>
+									<td class="description last">
+										<p>The uv node.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+						<dl class="details">
+							<dt class="tag-overrides"><strong>Overrides:</strong> <a href="TextureNode.html#getTransformedUV">TextureNode#getTransformedUV</a></dt>
+						</dl>
+						<dl class="details">
+							<dt class="tag-returns"><strong>Returns:</strong> The unmodified uv node.</dt>
+						</dl>
+					</div>
 					<h3 class="name name-method" id="setAccess" translate="no">.<a href="#setAccess">setAccess</a><span class="signature">( value : <span class="param-type">string</span> )</span><span class="type-signature"> : <a href="StorageTextureNode.html">StorageTextureNode</a></span> </h3>
 					<div class="method">
 						<div class="description">
@@ -306,6 +332,36 @@ is defined, the texture node is generated as normal texture.</p>
 							<dt class="tag-returns"><strong>Returns:</strong> A reference to this node.</dt>
 						</dl>
 					</div>
+					<h3 class="name name-method" id="store" translate="no">.<a href="#store">store</a><span class="signature">( uvNode : <span class="param-type"><a href="Node.html">Node</a>.&lt;(vec2|vec3)></span>, storeNode : <span class="param-type"><a href="Node.html">Node</a></span> )</span><span class="type-signature"> : <a href="StorageTextureNode.html">StorageTextureNode</a></span> </h3>
+					<div class="method">
+						<div class="description">
+							<p>Stores a value in this storage texture at the given coordinates.</p>
+						</div>
+						<table class="params">
+							<tbody>
+								<tr>
+									<td class="name">
+										<strong translate="no">uvNode</strong>
+									</td>
+									<td class="description last">
+										<p>The storage texture coordinates.</p>
+									</td>
+								</tr>
+								<tr>
+									<td class="name">
+										<strong translate="no">storeNode</strong>
+									</td>
+									<td class="description last">
+										<p>The value node that should be stored in the texture.</p>
+										<p>Default is <code>null</code>.</p>
+									</td>
+								</tr>
+							</tbody>
+						</table>
+						<dl class="details">
+							<dt class="tag-returns"><strong>Returns:</strong> A storage texture node representing the store operation.</dt>
+						</dl>
+					</div>
 					<h3 class="name name-method" id="toReadOnly" translate="no">.<a href="#toReadOnly">toReadOnly</a><span class="signature">()</span><span class="type-signature"> : <a href="StorageTextureNode.html">StorageTextureNode</a></span> </h3>
 					<div class="method">
 						<div class="description">

+ 28 - 0
docs/pages/StorageTextureNode.html.md

@@ -152,6 +152,18 @@ The current node builder.
 
 **Returns:** The input type.
 
+### .getTransformedUV( uvNode : Node ) : Node
+
+Overwrites the default implementation since storage texture coordinates are texel coordinates and should not be transformed by the texture uv matrix.
+
+**uvNode**
+
+The uv node.
+
+**Overrides:** [TextureNode#getTransformedUV](TextureNode.html#getTransformedUV)
+
+**Returns:** The unmodified uv node.
+
 ### .setAccess( value : string ) : StorageTextureNode
 
 Defines the node access.
@@ -172,6 +184,22 @@ The mip level.
 
 **Returns:** A reference to this node.
 
+### .store( uvNode : Node.<(vec2|vec3)>, storeNode : Node ) : StorageTextureNode
+
+Stores a value in this storage texture at the given coordinates.
+
+**uvNode**
+
+The storage texture coordinates.
+
+**storeNode**
+
+The value node that should be stored in the texture.
+
+Default is `null`.
+
+**Returns:** A storage texture node representing the store operation.
+
 ### .toReadOnly() : StorageTextureNode
 
 Convenience method for configuring a read-only node access.

+ 5 - 4
docs/pages/StructTypeNode.html

@@ -51,7 +51,7 @@ retrieve member types, and generate the struct type for a builder.</p></div>
 				</div>
 				<h2 class="subsection-title">Properties</h2>
 				<div class="member">
-					<h3 class="name" id="isStructLayoutNode" translate="no">.<a href="#isStructLayoutNode">isStructLayoutNode</a><span class="type-signature"> : boolean</span> <span class="type-signature">(readonly) </span></h3>
+					<h3 class="name" id="isStructTypeNode" translate="no">.<a href="#isStructTypeNode">isStructTypeNode</a><span class="type-signature"> : boolean</span> <span class="type-signature">(readonly) </span></h3>
 					<div class="description">
 						<p>This flag can be used for type testing.</p>
 						<p>Default is <code>true</code>.</p>
@@ -77,11 +77,12 @@ retrieve member types, and generate the struct type for a builder.</p></div>
 					<h3 class="name name-method" id="getLength" translate="no">.<a href="#getLength">getLength</a><span class="signature">()</span><span class="type-signature"> : number</span> </h3>
 					<div class="method">
 						<div class="description">
-							<p>Returns the length of the struct.
-The length is calculated by summing the lengths of the struct's members.</p>
+							<p>Returns the length of the struct in 4-byte elements (e.g. float or int components).
+The length is calculated by summing the lengths of the struct's members, accounting for memory alignment.
+To get the size in bytes, multiply the returned value by 4.</p>
 						</div>
 						<dl class="details">
-							<dt class="tag-returns"><strong>Returns:</strong> The length of the struct.</dt>
+							<dt class="tag-returns"><strong>Returns:</strong> The length of the struct in 4-byte elements.</dt>
 						</dl>
 					</div>
 				<h2 class="subsection-title">Source</h2>

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff

粤ICP备19079148号