@@ -8180,9 +8180,19 @@ class VarNode extends Node {
81808180
81818181 build( ...params ) {
81828182
8183- if ( this.intent === true ) {
8183+ const builder = params[ 0 ];
8184+
8185+ if ( this._hasStack( builder ) === false && builder.buildStage === 'setup' ) {
8186+
8187+ if ( builder.context.nodeLoop || builder.context.nodeBlock ) {
8188+
8189+ builder.getBaseStack().addToStack( this );
81848190
8185- const builder = params[ 0 ];
8191+ }
8192+
8193+ }
8194+
8195+ if ( this.intent === true ) {
81868196
81878197 if ( this.isAssign( builder ) !== true ) {
81888198
@@ -8263,6 +8273,14 @@ class VarNode extends Node {
82638273
82648274 }
82658275
8276+ _hasStack( builder ) {
8277+
8278+ const nodeData = builder.getDataFromNode( this );
8279+
8280+ return nodeData.stack !== undefined;
8281+
8282+ }
8283+
82668284}
82678285
82688286/**
@@ -8312,12 +8330,6 @@ const Const = ( node, name = null ) => createVar( node, name, true ).toStack();
83128330 */
83138331const VarIntent = ( node ) => {
83148332
8315- if ( getCurrentStack() === null ) {
8316-
8317- return node;
8318-
8319- }
8320-
83218333 return createVar( node ).setIntent( true ).toStack();
83228334
83238335};
@@ -17551,7 +17563,7 @@ class LoopNode extends Node {
1755117563 */
1755217564 constructor( params = [] ) {
1755317565
17554- super();
17566+ super( 'void' );
1755517567
1755617568 this.params = params;
1755717569
@@ -17597,16 +17609,20 @@ class LoopNode extends Node {
1759717609
1759817610 }
1759917611
17600- const stack = builder.addStack(); // TODO: cache() it
17612+ const stack = builder.addStack();
17613+
17614+ const fnCall = this.params[ this.params.length - 1 ]( inputs );
1760117615
17602- properties.returnsNode = this.params[ this.params.length - 1 ]( inputs, builder );
17616+ properties.returnsNode = fnCall.context( { nodeLoop: fnCall } );
1760317617 properties.stackNode = stack;
1760417618
1760517619 const baseParam = this.params[ 0 ];
1760617620
1760717621 if ( baseParam.isNode !== true && typeof baseParam.update === 'function' ) {
1760817622
17609- properties.updateNode = Fn( this.params[ 0 ].update )( inputs );
17623+ const fnUpdateCall = Fn( this.params[ 0 ].update )( inputs );
17624+
17625+ properties.updateNode = fnUpdateCall.context( { nodeLoop: fnUpdateCall } );
1761017626
1761117627 }
1761217628
@@ -17616,20 +17632,6 @@ class LoopNode extends Node {
1761617632
1761717633 }
1761817634
17619- /**
17620- * This method is overwritten since the node type is inferred based on the loop configuration.
17621- *
17622- * @param {NodeBuilder} builder - The current node builder.
17623- * @return {string} The node type.
17624- */
17625- getNodeType( builder ) {
17626-
17627- const { returnsNode } = this.getProperties( builder );
17628-
17629- return returnsNode ? returnsNode.getNodeType( builder ) : 'void';
17630-
17631- }
17632-
1763317635 setup( builder ) {
1763417636
1763517637 // setup properties
@@ -17809,7 +17811,7 @@ class LoopNode extends Node {
1780917811
1781017812 const stackSnippet = stackNode.build( builder, 'void' );
1781117813
17812- const returnsSnippet = properties.returnsNode ? properties.returnsNode. build( builder ) : '' ;
17814+ properties.returnsNode. build( builder, 'void' ) ;
1781317815
1781417816 builder.removeFlowTab().addFlowCode( '\n' + builder.tab + stackSnippet );
1781517817
@@ -17821,8 +17823,6 @@ class LoopNode extends Node {
1782117823
1782217824 builder.addFlowTab();
1782317825
17824- return returnsSnippet;
17825-
1782617826 }
1782717827
1782817828}
@@ -27510,7 +27510,7 @@ class VolumetricLightingModel extends LightingModel {
2751027510
2751127511 start( builder ) {
2751227512
27513- const { material, context } = builder;
27513+ const { material } = builder;
2751427514
2751527515 const startPos = property( 'vec3' );
2751627516 const endPos = property( 'vec3' );
@@ -27559,13 +27559,13 @@ class VolumetricLightingModel extends LightingModel {
2755927559
2756027560 linearDepthRay.assign( linearDepth( viewZToPerspectiveDepth( positionViewRay.z, cameraNear, cameraFar ) ) );
2756127561
27562- context.sceneDepthNode = linearDepth( material.depthNode ).toVar();
27562+ builder. context.sceneDepthNode = linearDepth( material.depthNode ).toVar();
2756327563
2756427564 }
2756527565
27566- context.positionWorld = positionRay;
27567- context.shadowPositionWorld = positionRay;
27568- context.positionView = positionViewRay;
27566+ builder. context.positionWorld = positionRay;
27567+ builder. context.shadowPositionWorld = positionRay;
27568+ builder. context.positionView = positionViewRay;
2756927569
2757027570 scatteringDensity.assign( 0 );
2757127571
@@ -32683,12 +32683,11 @@ class StackNode extends Node {
3268332683
3268432684 build( builder, ...params ) {
3268532685
32686- const previousBuildStack = builder.currentStack;
3268732686 const previousStack = getCurrentStack();
3268832687
3268932688 setCurrentStack( this );
3269032689
32691- builder.currentStack = this;
32690+ builder.setActiveStack( this ) ;
3269232691
3269332692 const buildStage = builder.buildStage;
3269432693
@@ -32706,6 +32705,9 @@ class StackNode extends Node {
3270632705
3270732706 if ( buildStage === 'setup' ) {
3270832707
32708+ const nodeData = builder.getDataFromNode( node );
32709+ nodeData.stack = this;
32710+
3270932711 node.build( builder );
3271032712
3271132713 } else if ( buildStage === 'analyze' ) {
@@ -32745,7 +32747,7 @@ class StackNode extends Node {
3274532747
3274632748 setCurrentStack( previousStack );
3274732749
32748- builder.currentStack = previousBuildStack ;
32750+ builder.removeActiveStack( this ) ;
3274932751
3275032752 return result;
3275132753
@@ -39445,8 +39447,11 @@ class RangeNode extends Node {
3944539447 */
3944639448 getVectorLength( builder ) {
3944739449
39448- const minLength = builder.getTypeLength( getValueType( this.minNode.value ) );
39449- const maxLength = builder.getTypeLength( getValueType( this.maxNode.value ) );
39450+ const minNode = this.getConstNode( this.minNode );
39451+ const maxNode = this.getConstNode( this.maxNode );
39452+
39453+ const minLength = builder.getTypeLength( getValueType( minNode.value ) );
39454+ const maxLength = builder.getTypeLength( getValueType( maxNode.value ) );
3945039455
3945139456 return minLength > maxLength ? minLength : maxLength;
3945239457
@@ -39464,6 +39469,36 @@ class RangeNode extends Node {
3946439469
3946539470 }
3946639471
39472+ /**
39473+ * Returns a constant node from the given node by traversing it.
39474+ *
39475+ * @param {Node} node - The node to traverse.
39476+ * @returns {Node} The constant node, if found.
39477+ */
39478+ getConstNode( node ) {
39479+
39480+ let output = null;
39481+
39482+ node.traverse( n => {
39483+
39484+ if ( n.isConstNode === true ) {
39485+
39486+ output = n;
39487+
39488+ }
39489+
39490+ } );
39491+
39492+ if ( output === null ) {
39493+
39494+ throw new Error( 'THREE.TSL: No "ConstNode" found in node graph.' );
39495+
39496+ }
39497+
39498+ return output;
39499+
39500+ }
39501+
3946739502 setup( builder ) {
3946839503
3946939504 const object = builder.object;
@@ -39472,8 +39507,11 @@ class RangeNode extends Node {
3947239507
3947339508 if ( object.count > 1 ) {
3947439509
39475- const minValue = this.minNode.value;
39476- const maxValue = this.maxNode.value;
39510+ const minNode = this.getConstNode( this.minNode );
39511+ const maxNode = this.getConstNode( this.maxNode );
39512+
39513+ const minValue = minNode.value;
39514+ const maxValue = maxNode.value;
3947739515
3947839516 const minLength = builder.getTypeLength( getValueType( minValue ) );
3947939517 const maxLength = builder.getTypeLength( getValueType( maxValue ) );
@@ -47895,13 +47933,13 @@ class NodeBuilder {
4789547933 */
4789647934 this.subBuildLayers = [];
4789747935
47936+
4789847937 /**
47899- * The current stack of nodes.
47938+ * The active stack nodes.
4790047939 *
47901- * @type {?StackNode}
47902- * @default null
47940+ * @type {Array<StackNode>}
4790347941 */
47904- this.currentStack = null ;
47942+ this.activeStacks = [] ;
4790547943
4790647944 /**
4790747945 * The current sub-build TSL function(Fn).
@@ -49063,6 +49101,58 @@ class NodeBuilder {
4906349101
4906449102 }
4906549103
49104+ /**
49105+ * Adds an active stack to the internal stack.
49106+ *
49107+ * @param {StackNode} stack - The stack node to add.
49108+ */
49109+ setActiveStack( stack ) {
49110+
49111+ this.activeStacks.push( stack );
49112+
49113+ }
49114+
49115+ /**
49116+ * Removes the active stack from the internal stack.
49117+ *
49118+ * @param {StackNode} stack - The stack node to remove.
49119+ */
49120+ removeActiveStack( stack ) {
49121+
49122+ if ( this.activeStacks[ this.activeStacks.length - 1 ] === stack ) {
49123+
49124+ this.activeStacks.pop();
49125+
49126+ } else {
49127+
49128+ throw new Error( 'NodeBuilder: Invalid active stack removal.' );
49129+
49130+ }
49131+
49132+ }
49133+
49134+ /**
49135+ * Returns the active stack.
49136+ *
49137+ * @return {StackNode} The active stack.
49138+ */
49139+ getActiveStack() {
49140+
49141+ return this.activeStacks[ this.activeStacks.length - 1 ];
49142+
49143+ }
49144+
49145+ /**
49146+ * Returns the base stack.
49147+ *
49148+ * @return {StackNode} The base stack.
49149+ */
49150+ getBaseStack() {
49151+
49152+ return this.activeStacks[ 0 ];
49153+
49154+ }
49155+
4906649156 /**
4906749157 * Adds a stack node to the internal stack.
4906849158 *
@@ -57617,10 +57707,10 @@ class Renderer {
5761757707 * if the renderer has been initialized.
5761857708 *
5761957709 * @param {Node|Array<Node>} computeNodes - The compute node(s).
57620- * @param {number|Array<number>|GPUBuffer } [dispatchSize=null]
57710+ * @param {number|Array<number>|IndirectStorageBufferAttribute } [dispatchSize=null]
5762157711 * - A single number representing count, or
5762257712 * - An array [x, y, z] representing dispatch size, or
57623- * - A GPUBuffer for indirect dispatch size.
57713+ * - A IndirectStorageBufferAttribute for indirect dispatch size.
5762457714 * @return {Promise|undefined} A Promise that resolve when the compute has finished. Only returned when the renderer has not been initialized.
5762557715 */
5762657716 compute( computeNodes, dispatchSize = null ) {
@@ -57631,7 +57721,7 @@ class Renderer {
5763157721
5763257722 warn( 'Renderer: .compute() called before the backend is initialized. Try using .computeAsync() instead.' );
5763357723
57634- return this.computeAsync( computeNodes );
57724+ return this.computeAsync( computeNodes, dispatchSize );
5763557725
5763657726 }
5763757727
@@ -57729,10 +57819,10 @@ class Renderer {
5772957819 *
5773057820 * @async
5773157821 * @param {Node|Array<Node>} computeNodes - The compute node(s).
57732- * @param {number|Array<number>|GPUBuffer } [dispatchSize=null]
57822+ * @param {number|Array<number>|IndirectStorageBufferAttribute } [dispatchSize=null]
5773357823 * - A single number representing count, or
5773457824 * - An array [x, y, z] representing dispatch size, or
57735- * - A GPUBuffer for indirect dispatch size.
57825+ * - A IndirectStorageBufferAttribute for indirect dispatch size.
5773657826 * @return {Promise} A Promise that resolve when the compute has finished.
5773757827 */
5773857828 async computeAsync( computeNodes, dispatchSize = null ) {
@@ -66657,6 +66747,12 @@ class WebGLBackend extends Backend {
6665766747
6665866748 count = count[ 0 ];
6665966749
66750+ } else if ( count && typeof count === 'object' && count.isIndirectStorageBufferAttribute ) {
66751+
66752+ warnOnce( 'WebGLBackend.compute(): The count parameter must be a single number, not IndirectStorageBufferAttribute' );
66753+
66754+ count = computeNode.count;
66755+
6666066756 }
6666166757
6666266758 if ( attributes[ 0 ].isStorageInstancedBufferAttribute ) {
@@ -76857,10 +76953,10 @@ class WebGPUBackend extends Backend {
7685776953 * @param {Node} computeNode - The compute node.
7685876954 * @param {Array<BindGroup>} bindings - The bindings.
7685976955 * @param {ComputePipeline} pipeline - The compute pipeline.
76860- * @param {number|Array<number>|GPUBuffer } [dispatchSize=null]
76956+ * @param {number|Array<number>|IndirectStorageBufferAttribute } [dispatchSize=null]
7686176957 * - A single number representing count, or
7686276958 * - An array [x, y, z] representing dispatch size, or
76863- * - A GPUBuffer for indirect dispatch size.
76959+ * - A IndirectStorageBufferAttribute for indirect dispatch size.
7686476960 */
7686576961 compute( computeGroup, computeNode, bindings, pipeline, dispatchSize = null ) {
7686676962
0 commit comments