Explorar el Código

Updated builds.

Mugen87 hace 8 meses
padre
commit
980d7cab64

+ 178 - 6
build/three.cjs

@@ -7139,6 +7139,14 @@ class Texture extends EventDispatcher {
 		 */
 		 */
 		this.userData = {};
 		this.userData = {};
 
 
+		/**
+		 * This can be used to only update a subregion or specific rows of the texture (for example, just the
+		 * first 3 rows). Use the `addUpdateRange()` function to add ranges to this array.
+		 *
+		 * @type {Array<Object>}
+		 */
+		this.updateRanges = [];
+
 		/**
 		/**
 		 * This starts at `0` and counts how many times {@link Texture#needsUpdate} is set to `true`.
 		 * This starts at `0` and counts how many times {@link Texture#needsUpdate} is set to `true`.
 		 *
 		 *
@@ -7249,6 +7257,27 @@ class Texture extends EventDispatcher {
 
 
 	}
 	}
 
 
+	/**
+	 * Adds a range of data in the data texture to be updated on the GPU.
+	 *
+	 * @param {number} start - Position at which to start update.
+	 * @param {number} count - The number of components to update.
+	 */
+	addUpdateRange( start, count ) {
+
+		this.updateRanges.push( { start, count } );
+
+	}
+
+	/**
+	 * Clears the update ranges.
+	 */
+	clearUpdateRanges() {
+
+		this.updateRanges.length = 0;
+
+	}
+
 	/**
 	/**
 	 * Returns a new texture with copied values from this instance.
 	 * Returns a new texture with copied values from this instance.
 	 *
 	 *
@@ -20120,6 +20149,15 @@ class Mesh extends Object3D {
 		 */
 		 */
 		this.morphTargetInfluences = undefined;
 		this.morphTargetInfluences = undefined;
 
 
+		/**
+		 * The number of instances of this mesh.
+		 * Can only be used with {@link WebGPURenderer}.
+		 *
+		 * @type {number}
+		 * @default 1
+		 */
+		this.count = 1;
+
 		this.updateMorphTargets();
 		this.updateMorphTargets();
 
 
 	}
 	}
@@ -24069,6 +24107,15 @@ class Sprite extends Object3D {
 		 */
 		 */
 		this.center = new Vector2( 0.5, 0.5 );
 		this.center = new Vector2( 0.5, 0.5 );
 
 
+		/**
+		 * The number of instances of this sprite.
+		 * Can only be used with {@link WebGPURenderer}.
+		 *
+		 * @type {number}
+		 * @default 1
+		 */
+		this.count = 1;
+
 	}
 	}
 
 
 	/**
 	/**
@@ -48399,6 +48446,8 @@ const TEXTURE_FILTER = {
 	LinearMipmapLinearFilter: LinearMipmapLinearFilter
 	LinearMipmapLinearFilter: LinearMipmapLinearFilter
 };
 };
 
 
+const _errorMap = new WeakMap();
+
 /**
 /**
  * A loader for loading images as an [ImageBitmap]{@link https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap}.
  * A loader for loading images as an [ImageBitmap]{@link https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap}.
  * An `ImageBitmap` provides an asynchronous and resource efficient pathway to prepare
  * An `ImageBitmap` provides an asynchronous and resource efficient pathway to prepare
@@ -48409,7 +48458,7 @@ const TEXTURE_FILTER = {
  *
  *
  * You need to set the equivalent options via {@link ImageBitmapLoader#setOptions} instead.
  * You need to set the equivalent options via {@link ImageBitmapLoader#setOptions} instead.
  *
  *
- * Also note that unlike {@link FileLoader}, this loader does not avoid multiple concurrent requests to the same URL.
+ * Also note that unlike {@link FileLoader}, this loader avoids multiple concurrent requests to the same URL only if `Cache` is enabled.
  *
  *
  * ```js
  * ```js
  * const loader = new THREE.ImageBitmapLoader();
  * const loader = new THREE.ImageBitmapLoader();
@@ -48509,15 +48558,27 @@ class ImageBitmapLoader extends Loader {
 
 
 				cached.then( imageBitmap => {
 				cached.then( imageBitmap => {
 
 
-					if ( onLoad ) onLoad( imageBitmap );
+					// check if there is an error for the cached promise
+
+					if ( _errorMap.has( cached ) === true ) {
+
+						if ( onError ) onError( _errorMap.get( cached ) );
 
 
-					scope.manager.itemEnd( url );
+						scope.manager.itemError( url );
+						scope.manager.itemEnd( url );
 
 
-				} ).catch( e => {
+					} else {
+
+						if ( onLoad ) onLoad( imageBitmap );
+
+						scope.manager.itemEnd( url );
+
+						return imageBitmap;
 
 
-					if ( onError ) onError( e );
+					}
 
 
 				} );
 				} );
+
 				return;
 				return;
 
 
 			}
 			}
@@ -48561,6 +48622,8 @@ class ImageBitmapLoader extends Loader {
 
 
 			if ( onError ) onError( e );
 			if ( onError ) onError( e );
 
 
+			_errorMap.set( promise, e );
+
 			Cache.remove( url );
 			Cache.remove( url );
 
 
 			scope.manager.itemError( url );
 			scope.manager.itemError( url );
@@ -68784,6 +68847,115 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 
 	}
 	}
 
 
+	function getRow( index, rowLength, componentStride ) {
+
+		return Math.floor( Math.floor( index / componentStride ) / rowLength );
+
+	}
+
+	function updateTexture( texture, image, glFormat, glType ) {
+
+		const componentStride = 4; // only RGBA supported
+
+		const updateRanges = texture.updateRanges;
+
+		if ( updateRanges.length === 0 ) {
+
+			state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, image.width, image.height, glFormat, glType, image.data );
+
+		} else {
+
+			// Before applying update ranges, we merge any adjacent / overlapping
+			// ranges to reduce load on `gl.texSubImage2D`. Empirically, this has led
+			// to performance improvements for applications which make heavy use of
+			// update ranges. Likely due to GPU command overhead.
+			//
+			// Note that to reduce garbage collection between frames, we merge the
+			// update ranges in-place. This is safe because this method will clear the
+			// update ranges once updated.
+
+			updateRanges.sort( ( a, b ) => a.start - b.start );
+
+			// To merge the update ranges in-place, we work from left to right in the
+			// existing updateRanges array, merging ranges. This may result in a final
+			// array which is smaller than the original. This index tracks the last
+			// index representing a merged range, any data after this index can be
+			// trimmed once the merge algorithm is completed.
+			let mergeIndex = 0;
+
+			for ( let i = 1; i < updateRanges.length; i ++ ) {
+
+				const previousRange = updateRanges[ mergeIndex ];
+				const range = updateRanges[ i ];
+
+				// Only merge if in the same row and overlapping/adjacent
+				const previousEnd = previousRange.start + previousRange.count;
+				const currentRow = getRow( range.start, image.width, componentStride );
+				const previousRow = getRow( previousRange.start, image.width, componentStride );
+
+				// We add one here to merge adjacent ranges. This is safe because ranges
+				// operate over positive integers.
+				if (
+					range.start <= previousEnd + 1 &&
+					currentRow === previousRow &&
+					getRow( range.start + range.count - 1, image.width, componentStride ) === currentRow // ensure range doesn't spill
+				) {
+
+					previousRange.count = Math.max(
+						previousRange.count,
+						range.start + range.count - previousRange.start
+					);
+
+				} else {
+
+					++ mergeIndex;
+					updateRanges[ mergeIndex ] = range;
+
+				}
+
+
+			}
+
+			// Trim the array to only contain the merged ranges.
+			updateRanges.length = mergeIndex + 1;
+
+			const currentUnpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH );
+			const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS );
+			const currentUnpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS );
+
+			_gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width );
+
+			for ( let i = 0, l = updateRanges.length; i < l; i ++ ) {
+
+				const range = updateRanges[ i ];
+
+				const pixelStart = Math.floor( range.start / componentStride );
+				const pixelCount = Math.ceil( range.count / componentStride );
+
+				const x = pixelStart % image.width;
+				const y = Math.floor( pixelStart / image.width );
+
+				// Assumes update ranges refer to contiguous memory
+				const width = pixelCount;
+				const height = 1;
+
+				_gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, x );
+				_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, y );
+
+				state.texSubImage2D( _gl.TEXTURE_2D, 0, x, y, width, height, glFormat, glType, image.data );
+
+			}
+
+			texture.clearUpdateRanges();
+
+			_gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen );
+			_gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels );
+			_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows );
+
+		}
+
+	}
+
 	function uploadTexture( textureProperties, texture, slot ) {
 	function uploadTexture( textureProperties, texture, slot ) {
 
 
 		let textureType = _gl.TEXTURE_2D;
 		let textureType = _gl.TEXTURE_2D;
@@ -68897,7 +69069,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 
 						if ( dataReady ) {
 						if ( dataReady ) {
 
 
-							state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, image.width, image.height, glFormat, glType, image.data );
+							updateTexture( texture, image, glFormat, glType );
 
 
 						}
 						}
 
 

+ 68 - 5
build/three.core.js

@@ -7137,6 +7137,14 @@ class Texture extends EventDispatcher {
 		 */
 		 */
 		this.userData = {};
 		this.userData = {};
 
 
+		/**
+		 * This can be used to only update a subregion or specific rows of the texture (for example, just the
+		 * first 3 rows). Use the `addUpdateRange()` function to add ranges to this array.
+		 *
+		 * @type {Array<Object>}
+		 */
+		this.updateRanges = [];
+
 		/**
 		/**
 		 * This starts at `0` and counts how many times {@link Texture#needsUpdate} is set to `true`.
 		 * This starts at `0` and counts how many times {@link Texture#needsUpdate} is set to `true`.
 		 *
 		 *
@@ -7247,6 +7255,27 @@ class Texture extends EventDispatcher {
 
 
 	}
 	}
 
 
+	/**
+	 * Adds a range of data in the data texture to be updated on the GPU.
+	 *
+	 * @param {number} start - Position at which to start update.
+	 * @param {number} count - The number of components to update.
+	 */
+	addUpdateRange( start, count ) {
+
+		this.updateRanges.push( { start, count } );
+
+	}
+
+	/**
+	 * Clears the update ranges.
+	 */
+	clearUpdateRanges() {
+
+		this.updateRanges.length = 0;
+
+	}
+
 	/**
 	/**
 	 * Returns a new texture with copied values from this instance.
 	 * Returns a new texture with copied values from this instance.
 	 *
 	 *
@@ -20118,6 +20147,15 @@ class Mesh extends Object3D {
 		 */
 		 */
 		this.morphTargetInfluences = undefined;
 		this.morphTargetInfluences = undefined;
 
 
+		/**
+		 * The number of instances of this mesh.
+		 * Can only be used with {@link WebGPURenderer}.
+		 *
+		 * @type {number}
+		 * @default 1
+		 */
+		this.count = 1;
+
 		this.updateMorphTargets();
 		this.updateMorphTargets();
 
 
 	}
 	}
@@ -24067,6 +24105,15 @@ class Sprite extends Object3D {
 		 */
 		 */
 		this.center = new Vector2( 0.5, 0.5 );
 		this.center = new Vector2( 0.5, 0.5 );
 
 
+		/**
+		 * The number of instances of this sprite.
+		 * Can only be used with {@link WebGPURenderer}.
+		 *
+		 * @type {number}
+		 * @default 1
+		 */
+		this.count = 1;
+
 	}
 	}
 
 
 	/**
 	/**
@@ -48397,6 +48444,8 @@ const TEXTURE_FILTER = {
 	LinearMipmapLinearFilter: LinearMipmapLinearFilter
 	LinearMipmapLinearFilter: LinearMipmapLinearFilter
 };
 };
 
 
+const _errorMap = new WeakMap();
+
 /**
 /**
  * A loader for loading images as an [ImageBitmap]{@link https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap}.
  * A loader for loading images as an [ImageBitmap]{@link https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap}.
  * An `ImageBitmap` provides an asynchronous and resource efficient pathway to prepare
  * An `ImageBitmap` provides an asynchronous and resource efficient pathway to prepare
@@ -48407,7 +48456,7 @@ const TEXTURE_FILTER = {
  *
  *
  * You need to set the equivalent options via {@link ImageBitmapLoader#setOptions} instead.
  * You need to set the equivalent options via {@link ImageBitmapLoader#setOptions} instead.
  *
  *
- * Also note that unlike {@link FileLoader}, this loader does not avoid multiple concurrent requests to the same URL.
+ * Also note that unlike {@link FileLoader}, this loader avoids multiple concurrent requests to the same URL only if `Cache` is enabled.
  *
  *
  * ```js
  * ```js
  * const loader = new THREE.ImageBitmapLoader();
  * const loader = new THREE.ImageBitmapLoader();
@@ -48507,15 +48556,27 @@ class ImageBitmapLoader extends Loader {
 
 
 				cached.then( imageBitmap => {
 				cached.then( imageBitmap => {
 
 
-					if ( onLoad ) onLoad( imageBitmap );
+					// check if there is an error for the cached promise
+
+					if ( _errorMap.has( cached ) === true ) {
+
+						if ( onError ) onError( _errorMap.get( cached ) );
+
+						scope.manager.itemError( url );
+						scope.manager.itemEnd( url );
 
 
-					scope.manager.itemEnd( url );
+					} else {
+
+						if ( onLoad ) onLoad( imageBitmap );
+
+						scope.manager.itemEnd( url );
 
 
-				} ).catch( e => {
+						return imageBitmap;
 
 
-					if ( onError ) onError( e );
+					}
 
 
 				} );
 				} );
+
 				return;
 				return;
 
 
 			}
 			}
@@ -48559,6 +48620,8 @@ class ImageBitmapLoader extends Loader {
 
 
 			if ( onError ) onError( e );
 			if ( onError ) onError( e );
 
 
+			_errorMap.set( promise, e );
+
 			Cache.remove( url );
 			Cache.remove( url );
 
 
 			scope.manager.itemError( url );
 			scope.manager.itemError( url );

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
build/three.core.min.js


+ 110 - 1
build/three.module.js

@@ -10848,6 +10848,115 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 
 	}
 	}
 
 
+	function getRow( index, rowLength, componentStride ) {
+
+		return Math.floor( Math.floor( index / componentStride ) / rowLength );
+
+	}
+
+	function updateTexture( texture, image, glFormat, glType ) {
+
+		const componentStride = 4; // only RGBA supported
+
+		const updateRanges = texture.updateRanges;
+
+		if ( updateRanges.length === 0 ) {
+
+			state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, image.width, image.height, glFormat, glType, image.data );
+
+		} else {
+
+			// Before applying update ranges, we merge any adjacent / overlapping
+			// ranges to reduce load on `gl.texSubImage2D`. Empirically, this has led
+			// to performance improvements for applications which make heavy use of
+			// update ranges. Likely due to GPU command overhead.
+			//
+			// Note that to reduce garbage collection between frames, we merge the
+			// update ranges in-place. This is safe because this method will clear the
+			// update ranges once updated.
+
+			updateRanges.sort( ( a, b ) => a.start - b.start );
+
+			// To merge the update ranges in-place, we work from left to right in the
+			// existing updateRanges array, merging ranges. This may result in a final
+			// array which is smaller than the original. This index tracks the last
+			// index representing a merged range, any data after this index can be
+			// trimmed once the merge algorithm is completed.
+			let mergeIndex = 0;
+
+			for ( let i = 1; i < updateRanges.length; i ++ ) {
+
+				const previousRange = updateRanges[ mergeIndex ];
+				const range = updateRanges[ i ];
+
+				// Only merge if in the same row and overlapping/adjacent
+				const previousEnd = previousRange.start + previousRange.count;
+				const currentRow = getRow( range.start, image.width, componentStride );
+				const previousRow = getRow( previousRange.start, image.width, componentStride );
+
+				// We add one here to merge adjacent ranges. This is safe because ranges
+				// operate over positive integers.
+				if (
+					range.start <= previousEnd + 1 &&
+					currentRow === previousRow &&
+					getRow( range.start + range.count - 1, image.width, componentStride ) === currentRow // ensure range doesn't spill
+				) {
+
+					previousRange.count = Math.max(
+						previousRange.count,
+						range.start + range.count - previousRange.start
+					);
+
+				} else {
+
+					++ mergeIndex;
+					updateRanges[ mergeIndex ] = range;
+
+				}
+
+
+			}
+
+			// Trim the array to only contain the merged ranges.
+			updateRanges.length = mergeIndex + 1;
+
+			const currentUnpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH );
+			const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS );
+			const currentUnpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS );
+
+			_gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width );
+
+			for ( let i = 0, l = updateRanges.length; i < l; i ++ ) {
+
+				const range = updateRanges[ i ];
+
+				const pixelStart = Math.floor( range.start / componentStride );
+				const pixelCount = Math.ceil( range.count / componentStride );
+
+				const x = pixelStart % image.width;
+				const y = Math.floor( pixelStart / image.width );
+
+				// Assumes update ranges refer to contiguous memory
+				const width = pixelCount;
+				const height = 1;
+
+				_gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, x );
+				_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, y );
+
+				state.texSubImage2D( _gl.TEXTURE_2D, 0, x, y, width, height, glFormat, glType, image.data );
+
+			}
+
+			texture.clearUpdateRanges();
+
+			_gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen );
+			_gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels );
+			_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows );
+
+		}
+
+	}
+
 	function uploadTexture( textureProperties, texture, slot ) {
 	function uploadTexture( textureProperties, texture, slot ) {
 
 
 		let textureType = _gl.TEXTURE_2D;
 		let textureType = _gl.TEXTURE_2D;
@@ -10961,7 +11070,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 
 						if ( dataReady ) {
 						if ( dataReady ) {
 
 
-							state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, image.width, image.height, glFormat, glType, image.data );
+							updateTexture( texture, image, glFormat, glType );
 
 
 						}
 						}
 
 

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
build/three.module.min.js


+ 119 - 19
build/three.webgpu.js

@@ -1544,11 +1544,21 @@ class Node extends EventDispatcher {
 	 * This stage analyzes the node hierarchy and ensures descendent nodes are built.
 	 * This stage analyzes the node hierarchy and ensures descendent nodes are built.
 	 *
 	 *
 	 * @param {NodeBuilder} builder - The current node builder.
 	 * @param {NodeBuilder} builder - The current node builder.
+	 * @param {?Node} output - The target output node.
 	 */
 	 */
-	analyze( builder ) {
+	analyze( builder, output = null ) {
 
 
 		const usageCount = builder.increaseUsage( this );
 		const usageCount = builder.increaseUsage( this );
 
 
+		if ( this.parents === true ) {
+
+			const nodeData = builder.getDataFromNode( this, 'any' );
+			nodeData.stages = nodeData.stages || {};
+			nodeData.stages[ builder.shaderStage ] = nodeData.stages[ builder.shaderStage ] || [];
+			nodeData.stages[ builder.shaderStage ].push( output );
+
+		}
+
 		if ( usageCount === 1 ) {
 		if ( usageCount === 1 ) {
 
 
 			// node flow children
 			// node flow children
@@ -1559,7 +1569,7 @@ class Node extends EventDispatcher {
 
 
 				if ( childNode && childNode.isNode === true ) {
 				if ( childNode && childNode.isNode === true ) {
 
 
-					childNode.build( builder );
+					childNode.build( builder, this );
 
 
 				}
 				}
 
 
@@ -1638,7 +1648,7 @@ class Node extends EventDispatcher {
 	 * - **generate**: Generates the shader code for the node. Returns the generated shader string.
 	 * - **generate**: Generates the shader code for the node. Returns the generated shader string.
 	 *
 	 *
 	 * @param {NodeBuilder} builder - The current node builder.
 	 * @param {NodeBuilder} builder - The current node builder.
-	 * @param {?string} [output=null] - Can be used to define the output type.
+	 * @param {string|Node|null} [output=null] - Can be used to define the output type.
 	 * @return {Node|string|null} The result of the build process, depending on the build stage.
 	 * @return {Node|string|null} The result of the build process, depending on the build stage.
 	 */
 	 */
 	build( builder, output = null ) {
 	build( builder, output = null ) {
@@ -1707,7 +1717,7 @@ class Node extends EventDispatcher {
 
 
 		} else if ( buildStage === 'analyze' ) {
 		} else if ( buildStage === 'analyze' ) {
 
 
-			this.analyze( builder );
+			this.analyze( builder, output );
 
 
 		} else if ( buildStage === 'generate' ) {
 		} else if ( buildStage === 'generate' ) {
 
 
@@ -4600,6 +4610,15 @@ class AssignNode extends TempNode {
 		 */
 		 */
 		this.sourceNode = sourceNode;
 		this.sourceNode = sourceNode;
 
 
+		/**
+		 * This flag can be used for type testing.
+		 *
+		 * @type {boolean}
+		 * @readonly
+		 * @default true
+		 */
+		this.isAssignNode = true;
+
 	}
 	}
 
 
 	/**
 	/**
@@ -7201,6 +7220,15 @@ class VarNode extends Node {
 		 */
 		 */
 		this.readOnly = readOnly;
 		this.readOnly = readOnly;
 
 
+		/**
+		 *
+		 * Add this flag to the node system to indicate that this node require parents.
+		 *
+		 * @type {boolean}
+		 * @default true
+		 */
+		this.parents = true;
+
 	}
 	}
 
 
 	getMemberType( builder, name ) {
 	getMemberType( builder, name ) {
@@ -7427,6 +7455,7 @@ class VaryingNode extends Node {
 
 
 		this.interpolationType = type;
 		this.interpolationType = type;
 		this.interpolationSampling = sampling;
 		this.interpolationSampling = sampling;
+
 		return this;
 		return this;
 
 
 	}
 	}
@@ -7480,13 +7509,15 @@ class VaryingNode extends Node {
 
 
 		this.setupVarying( builder );
 		this.setupVarying( builder );
 
 
+		builder.flowNodeFromShaderStage( NodeShaderStage.VERTEX, this.node );
+
 	}
 	}
 
 
 	analyze( builder ) {
 	analyze( builder ) {
 
 
 		this.setupVarying( builder );
 		this.setupVarying( builder );
 
 
-		return this.node.analyze( builder );
+		builder.flowNodeFromShaderStage( NodeShaderStage.VERTEX, this.node );
 
 
 	}
 	}
 
 
@@ -24938,7 +24969,11 @@ class ShadowMaskModel extends LightingModel {
 	 */
 	 */
 	direct( { lightNode } ) {
 	direct( { lightNode } ) {
 
 
-		this.shadowNode.mulAssign( lightNode.shadowNode );
+		if ( lightNode.shadowNode !== null ) {
+
+			this.shadowNode.mulAssign( lightNode.shadowNode );
+
+		}
 
 
 	}
 	}
 
 
@@ -29141,6 +29176,7 @@ class Textures extends DataMap {
 			depthTexture.image.width = mipWidth;
 			depthTexture.image.width = mipWidth;
 			depthTexture.image.height = mipHeight;
 			depthTexture.image.height = mipHeight;
 			depthTexture.image.depth = size.depth;
 			depthTexture.image.depth = size.depth;
+			depthTexture.isArrayTexture = renderTarget.multiview === true && size.depth > 1;
 
 
 			depthTextureMips[ activeMipmapLevel ] = depthTexture;
 			depthTextureMips[ activeMipmapLevel ] = depthTexture;
 
 
@@ -29888,9 +29924,32 @@ class StackNode extends Node {
 
 
 		setCurrentStack( this );
 		setCurrentStack( this );
 
 
+		const buildStage = builder.buildStage;
+
 		for ( const node of this.nodes ) {
 		for ( const node of this.nodes ) {
 
 
-			node.build( builder, 'void' );
+			if ( buildStage === 'setup' ) {
+
+				node.build( builder );
+
+			} else if ( buildStage === 'analyze' ) {
+
+				node.build( builder, this );
+
+			} else if ( buildStage === 'generate' ) {
+
+				const stages = builder.getDataFromNode( node, 'any' ).stages;
+				const parents = stages && stages[ builder.shaderStage ];
+
+				if ( node.isVarNode && parents && parents.length === 1 && parents[ 0 ] && parents[ 0 ].isStackNode ) {
+
+					continue; // skip var nodes that are only used in .toVarying()
+
+				}
+
+				node.build( builder, 'void' );
+
+			}
 
 
 		}
 		}
 
 
@@ -45572,27 +45631,53 @@ class NodeBuilder {
 	 * @param {Node} node - The node to execute.
 	 * @param {Node} node - The node to execute.
 	 * @param {?string} output - Expected output type. For example 'vec3'.
 	 * @param {?string} output - Expected output type. For example 'vec3'.
 	 * @param {?string} propertyName - The property name to assign the result.
 	 * @param {?string} propertyName - The property name to assign the result.
-	 * @return {Object}
+	 * @return {Object|Node|null} The code flow or node.build() result.
 	 */
 	 */
 	flowNodeFromShaderStage( shaderStage, node, output = null, propertyName = null ) {
 	flowNodeFromShaderStage( shaderStage, node, output = null, propertyName = null ) {
 
 
+		const previousTab = this.tab;
+		const previousCache = this.cache;
 		const previousShaderStage = this.shaderStage;
 		const previousShaderStage = this.shaderStage;
+		const previousContext = this.context;
 
 
 		this.setShaderStage( shaderStage );
 		this.setShaderStage( shaderStage );
 
 
-		const flowData = this.flowChildNode( node, output );
+		const context = { ...this.context };
+		delete context.nodeBlock;
+
+		this.cache = this.globalCache;
+		this.tab = '\t';
+		this.context = context;
 
 
-		if ( propertyName !== null ) {
+		let result = null;
 
 
-			flowData.code += `${ this.tab + propertyName } = ${ flowData.result };\n`;
+		if ( this.buildStage === 'generate' ) {
 
 
-		}
+			const flowData = this.flowChildNode( node, output );
+
+			if ( propertyName !== null ) {
+
+				flowData.code += `${ this.tab + propertyName } = ${ flowData.result };\n`;
+
+			}
+
+			this.flowCode[ shaderStage ] = this.flowCode[ shaderStage ] + flowData.code;
+
+			result = flowData;
+
+		} else {
+
+			result = node.build( this );
 
 
-		this.flowCode[ shaderStage ] = this.flowCode[ shaderStage ] + flowData.code;
+		}
 
 
 		this.setShaderStage( previousShaderStage );
 		this.setShaderStage( previousShaderStage );
 
 
-		return flowData;
+		this.cache = previousCache;
+		this.tab = previousTab;
+		this.context = previousContext;
+
+		return result;
 
 
 	}
 	}
 
 
@@ -47440,7 +47525,7 @@ class Nodes extends DataMap {
 				nodeBuilder.environmentNode = this.getEnvironmentNode( renderObject.scene );
 				nodeBuilder.environmentNode = this.getEnvironmentNode( renderObject.scene );
 				nodeBuilder.fogNode = this.getFogNode( renderObject.scene );
 				nodeBuilder.fogNode = this.getFogNode( renderObject.scene );
 				nodeBuilder.clippingContext = renderObject.clippingContext;
 				nodeBuilder.clippingContext = renderObject.clippingContext;
-				if ( this.renderer.getRenderTarget() ? this.renderer.getRenderTarget().multiview : false ) {
+				if ( this.renderer.getOutputRenderTarget() ? this.renderer.getOutputRenderTarget().multiview : false ) {
 
 
 					nodeBuilder.enableMultiview();
 					nodeBuilder.enableMultiview();
 
 
@@ -47648,6 +47733,7 @@ class Nodes extends DataMap {
 			if ( environmentNode ) _cacheKeyValues.push( environmentNode.getCacheKey() );
 			if ( environmentNode ) _cacheKeyValues.push( environmentNode.getCacheKey() );
 			if ( fogNode ) _cacheKeyValues.push( fogNode.getCacheKey() );
 			if ( fogNode ) _cacheKeyValues.push( fogNode.getCacheKey() );
 
 
+			_cacheKeyValues.push( this.renderer.getOutputRenderTarget() && this.renderer.getOutputRenderTarget().multiview ? 1 : 0 );
 			_cacheKeyValues.push( this.renderer.shadowMap.enabled ? 1 : 0 );
 			_cacheKeyValues.push( this.renderer.shadowMap.enabled ? 1 : 0 );
 
 
 			cacheKeyData.callId = callId;
 			cacheKeyData.callId = callId;
@@ -49973,9 +50059,7 @@ function onSessionEnd() {
 
 
 	// restore framebuffer/rendering state
 	// restore framebuffer/rendering state
 
 
-	renderer.backend.setXRTarget( null );
-	renderer.setOutputRenderTarget( null );
-	renderer.setRenderTarget( null );
+	renderer.XRResetState();
 
 
 	this._session = null;
 	this._session = null;
 	this._xrRenderTarget = null;
 	this._xrRenderTarget = null;
@@ -50013,6 +50097,8 @@ function onSessionEnd() {
 
 
 			layer.plane.material = layer.material;
 			layer.plane.material = layer.material;
 			layer.material.map = layer.renderTarget.texture;
 			layer.material.map = layer.renderTarget.texture;
+			layer.material.map.offset.y = 1;
+			layer.material.map.repeat.y = -1;
 			delete layer.xrlayer;
 			delete layer.xrlayer;
 
 
 		}
 		}
@@ -50025,7 +50111,6 @@ function onSessionEnd() {
 	this._useMultiview = false;
 	this._useMultiview = false;
 
 
 	renderer._animation.stop();
 	renderer._animation.stop();
-
 	renderer._animation.setAnimationLoop( this._currentAnimationLoop );
 	renderer._animation.setAnimationLoop( this._currentAnimationLoop );
 	renderer._animation.setContext( this._currentAnimationContext );
 	renderer._animation.setContext( this._currentAnimationContext );
 	renderer._animation.start();
 	renderer._animation.start();
@@ -52461,6 +52546,21 @@ class Renderer {
 
 
 	}
 	}
 
 
+	/**
+	 * Resets the renderer to the initial state before WebXR started.
+	 *
+	 */
+	XRResetState() {
+
+		this.backend.setXRTarget( null );
+		this.setOutputRenderTarget( null );
+		this.setRenderTarget( null );
+
+		this._frameBufferTarget.dispose();
+		this._frameBufferTarget = null;
+
+	}
+
 	/**
 	/**
 	 * Callback for {@link Renderer#setRenderObjectFunction}.
 	 * Callback for {@link Renderer#setRenderObjectFunction}.
 	 *
 	 *

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
build/three.webgpu.min.js


+ 119 - 19
build/three.webgpu.nodes.js

@@ -1544,11 +1544,21 @@ class Node extends EventDispatcher {
 	 * This stage analyzes the node hierarchy and ensures descendent nodes are built.
 	 * This stage analyzes the node hierarchy and ensures descendent nodes are built.
 	 *
 	 *
 	 * @param {NodeBuilder} builder - The current node builder.
 	 * @param {NodeBuilder} builder - The current node builder.
+	 * @param {?Node} output - The target output node.
 	 */
 	 */
-	analyze( builder ) {
+	analyze( builder, output = null ) {
 
 
 		const usageCount = builder.increaseUsage( this );
 		const usageCount = builder.increaseUsage( this );
 
 
+		if ( this.parents === true ) {
+
+			const nodeData = builder.getDataFromNode( this, 'any' );
+			nodeData.stages = nodeData.stages || {};
+			nodeData.stages[ builder.shaderStage ] = nodeData.stages[ builder.shaderStage ] || [];
+			nodeData.stages[ builder.shaderStage ].push( output );
+
+		}
+
 		if ( usageCount === 1 ) {
 		if ( usageCount === 1 ) {
 
 
 			// node flow children
 			// node flow children
@@ -1559,7 +1569,7 @@ class Node extends EventDispatcher {
 
 
 				if ( childNode && childNode.isNode === true ) {
 				if ( childNode && childNode.isNode === true ) {
 
 
-					childNode.build( builder );
+					childNode.build( builder, this );
 
 
 				}
 				}
 
 
@@ -1638,7 +1648,7 @@ class Node extends EventDispatcher {
 	 * - **generate**: Generates the shader code for the node. Returns the generated shader string.
 	 * - **generate**: Generates the shader code for the node. Returns the generated shader string.
 	 *
 	 *
 	 * @param {NodeBuilder} builder - The current node builder.
 	 * @param {NodeBuilder} builder - The current node builder.
-	 * @param {?string} [output=null] - Can be used to define the output type.
+	 * @param {string|Node|null} [output=null] - Can be used to define the output type.
 	 * @return {Node|string|null} The result of the build process, depending on the build stage.
 	 * @return {Node|string|null} The result of the build process, depending on the build stage.
 	 */
 	 */
 	build( builder, output = null ) {
 	build( builder, output = null ) {
@@ -1707,7 +1717,7 @@ class Node extends EventDispatcher {
 
 
 		} else if ( buildStage === 'analyze' ) {
 		} else if ( buildStage === 'analyze' ) {
 
 
-			this.analyze( builder );
+			this.analyze( builder, output );
 
 
 		} else if ( buildStage === 'generate' ) {
 		} else if ( buildStage === 'generate' ) {
 
 
@@ -4600,6 +4610,15 @@ class AssignNode extends TempNode {
 		 */
 		 */
 		this.sourceNode = sourceNode;
 		this.sourceNode = sourceNode;
 
 
+		/**
+		 * This flag can be used for type testing.
+		 *
+		 * @type {boolean}
+		 * @readonly
+		 * @default true
+		 */
+		this.isAssignNode = true;
+
 	}
 	}
 
 
 	/**
 	/**
@@ -7201,6 +7220,15 @@ class VarNode extends Node {
 		 */
 		 */
 		this.readOnly = readOnly;
 		this.readOnly = readOnly;
 
 
+		/**
+		 *
+		 * Add this flag to the node system to indicate that this node require parents.
+		 *
+		 * @type {boolean}
+		 * @default true
+		 */
+		this.parents = true;
+
 	}
 	}
 
 
 	getMemberType( builder, name ) {
 	getMemberType( builder, name ) {
@@ -7427,6 +7455,7 @@ class VaryingNode extends Node {
 
 
 		this.interpolationType = type;
 		this.interpolationType = type;
 		this.interpolationSampling = sampling;
 		this.interpolationSampling = sampling;
+
 		return this;
 		return this;
 
 
 	}
 	}
@@ -7480,13 +7509,15 @@ class VaryingNode extends Node {
 
 
 		this.setupVarying( builder );
 		this.setupVarying( builder );
 
 
+		builder.flowNodeFromShaderStage( NodeShaderStage.VERTEX, this.node );
+
 	}
 	}
 
 
 	analyze( builder ) {
 	analyze( builder ) {
 
 
 		this.setupVarying( builder );
 		this.setupVarying( builder );
 
 
-		return this.node.analyze( builder );
+		builder.flowNodeFromShaderStage( NodeShaderStage.VERTEX, this.node );
 
 
 	}
 	}
 
 
@@ -24938,7 +24969,11 @@ class ShadowMaskModel extends LightingModel {
 	 */
 	 */
 	direct( { lightNode } ) {
 	direct( { lightNode } ) {
 
 
-		this.shadowNode.mulAssign( lightNode.shadowNode );
+		if ( lightNode.shadowNode !== null ) {
+
+			this.shadowNode.mulAssign( lightNode.shadowNode );
+
+		}
 
 
 	}
 	}
 
 
@@ -29141,6 +29176,7 @@ class Textures extends DataMap {
 			depthTexture.image.width = mipWidth;
 			depthTexture.image.width = mipWidth;
 			depthTexture.image.height = mipHeight;
 			depthTexture.image.height = mipHeight;
 			depthTexture.image.depth = size.depth;
 			depthTexture.image.depth = size.depth;
+			depthTexture.isArrayTexture = renderTarget.multiview === true && size.depth > 1;
 
 
 			depthTextureMips[ activeMipmapLevel ] = depthTexture;
 			depthTextureMips[ activeMipmapLevel ] = depthTexture;
 
 
@@ -29888,9 +29924,32 @@ class StackNode extends Node {
 
 
 		setCurrentStack( this );
 		setCurrentStack( this );
 
 
+		const buildStage = builder.buildStage;
+
 		for ( const node of this.nodes ) {
 		for ( const node of this.nodes ) {
 
 
-			node.build( builder, 'void' );
+			if ( buildStage === 'setup' ) {
+
+				node.build( builder );
+
+			} else if ( buildStage === 'analyze' ) {
+
+				node.build( builder, this );
+
+			} else if ( buildStage === 'generate' ) {
+
+				const stages = builder.getDataFromNode( node, 'any' ).stages;
+				const parents = stages && stages[ builder.shaderStage ];
+
+				if ( node.isVarNode && parents && parents.length === 1 && parents[ 0 ] && parents[ 0 ].isStackNode ) {
+
+					continue; // skip var nodes that are only used in .toVarying()
+
+				}
+
+				node.build( builder, 'void' );
+
+			}
 
 
 		}
 		}
 
 
@@ -45572,27 +45631,53 @@ class NodeBuilder {
 	 * @param {Node} node - The node to execute.
 	 * @param {Node} node - The node to execute.
 	 * @param {?string} output - Expected output type. For example 'vec3'.
 	 * @param {?string} output - Expected output type. For example 'vec3'.
 	 * @param {?string} propertyName - The property name to assign the result.
 	 * @param {?string} propertyName - The property name to assign the result.
-	 * @return {Object}
+	 * @return {Object|Node|null} The code flow or node.build() result.
 	 */
 	 */
 	flowNodeFromShaderStage( shaderStage, node, output = null, propertyName = null ) {
 	flowNodeFromShaderStage( shaderStage, node, output = null, propertyName = null ) {
 
 
+		const previousTab = this.tab;
+		const previousCache = this.cache;
 		const previousShaderStage = this.shaderStage;
 		const previousShaderStage = this.shaderStage;
+		const previousContext = this.context;
 
 
 		this.setShaderStage( shaderStage );
 		this.setShaderStage( shaderStage );
 
 
-		const flowData = this.flowChildNode( node, output );
+		const context = { ...this.context };
+		delete context.nodeBlock;
+
+		this.cache = this.globalCache;
+		this.tab = '\t';
+		this.context = context;
 
 
-		if ( propertyName !== null ) {
+		let result = null;
 
 
-			flowData.code += `${ this.tab + propertyName } = ${ flowData.result };\n`;
+		if ( this.buildStage === 'generate' ) {
 
 
-		}
+			const flowData = this.flowChildNode( node, output );
+
+			if ( propertyName !== null ) {
+
+				flowData.code += `${ this.tab + propertyName } = ${ flowData.result };\n`;
+
+			}
+
+			this.flowCode[ shaderStage ] = this.flowCode[ shaderStage ] + flowData.code;
+
+			result = flowData;
+
+		} else {
+
+			result = node.build( this );
 
 
-		this.flowCode[ shaderStage ] = this.flowCode[ shaderStage ] + flowData.code;
+		}
 
 
 		this.setShaderStage( previousShaderStage );
 		this.setShaderStage( previousShaderStage );
 
 
-		return flowData;
+		this.cache = previousCache;
+		this.tab = previousTab;
+		this.context = previousContext;
+
+		return result;
 
 
 	}
 	}
 
 
@@ -47440,7 +47525,7 @@ class Nodes extends DataMap {
 				nodeBuilder.environmentNode = this.getEnvironmentNode( renderObject.scene );
 				nodeBuilder.environmentNode = this.getEnvironmentNode( renderObject.scene );
 				nodeBuilder.fogNode = this.getFogNode( renderObject.scene );
 				nodeBuilder.fogNode = this.getFogNode( renderObject.scene );
 				nodeBuilder.clippingContext = renderObject.clippingContext;
 				nodeBuilder.clippingContext = renderObject.clippingContext;
-				if ( this.renderer.getRenderTarget() ? this.renderer.getRenderTarget().multiview : false ) {
+				if ( this.renderer.getOutputRenderTarget() ? this.renderer.getOutputRenderTarget().multiview : false ) {
 
 
 					nodeBuilder.enableMultiview();
 					nodeBuilder.enableMultiview();
 
 
@@ -47648,6 +47733,7 @@ class Nodes extends DataMap {
 			if ( environmentNode ) _cacheKeyValues.push( environmentNode.getCacheKey() );
 			if ( environmentNode ) _cacheKeyValues.push( environmentNode.getCacheKey() );
 			if ( fogNode ) _cacheKeyValues.push( fogNode.getCacheKey() );
 			if ( fogNode ) _cacheKeyValues.push( fogNode.getCacheKey() );
 
 
+			_cacheKeyValues.push( this.renderer.getOutputRenderTarget() && this.renderer.getOutputRenderTarget().multiview ? 1 : 0 );
 			_cacheKeyValues.push( this.renderer.shadowMap.enabled ? 1 : 0 );
 			_cacheKeyValues.push( this.renderer.shadowMap.enabled ? 1 : 0 );
 
 
 			cacheKeyData.callId = callId;
 			cacheKeyData.callId = callId;
@@ -49973,9 +50059,7 @@ function onSessionEnd() {
 
 
 	// restore framebuffer/rendering state
 	// restore framebuffer/rendering state
 
 
-	renderer.backend.setXRTarget( null );
-	renderer.setOutputRenderTarget( null );
-	renderer.setRenderTarget( null );
+	renderer.XRResetState();
 
 
 	this._session = null;
 	this._session = null;
 	this._xrRenderTarget = null;
 	this._xrRenderTarget = null;
@@ -50013,6 +50097,8 @@ function onSessionEnd() {
 
 
 			layer.plane.material = layer.material;
 			layer.plane.material = layer.material;
 			layer.material.map = layer.renderTarget.texture;
 			layer.material.map = layer.renderTarget.texture;
+			layer.material.map.offset.y = 1;
+			layer.material.map.repeat.y = -1;
 			delete layer.xrlayer;
 			delete layer.xrlayer;
 
 
 		}
 		}
@@ -50025,7 +50111,6 @@ function onSessionEnd() {
 	this._useMultiview = false;
 	this._useMultiview = false;
 
 
 	renderer._animation.stop();
 	renderer._animation.stop();
-
 	renderer._animation.setAnimationLoop( this._currentAnimationLoop );
 	renderer._animation.setAnimationLoop( this._currentAnimationLoop );
 	renderer._animation.setContext( this._currentAnimationContext );
 	renderer._animation.setContext( this._currentAnimationContext );
 	renderer._animation.start();
 	renderer._animation.start();
@@ -52461,6 +52546,21 @@ class Renderer {
 
 
 	}
 	}
 
 
+	/**
+	 * Resets the renderer to the initial state before WebXR started.
+	 *
+	 */
+	XRResetState() {
+
+		this.backend.setXRTarget( null );
+		this.setOutputRenderTarget( null );
+		this.setRenderTarget( null );
+
+		this._frameBufferTarget.dispose();
+		this._frameBufferTarget = null;
+
+	}
+
 	/**
 	/**
 	 * Callback for {@link Renderer#setRenderObjectFunction}.
 	 * Callback for {@link Renderer#setRenderObjectFunction}.
 	 *
 	 *

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
build/three.webgpu.nodes.min.js


Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio

粤ICP备19079148号