瀏覽代碼

TSL: Sync stack and new syntax (#26911)

* TSL: Sync stack

* update examples

* cleanup
sunag 1 年之前
父節點
當前提交
e7a9554960

+ 3 - 3
examples/jsm/nodes/accessors/InstanceNode.js

@@ -17,7 +17,7 @@ class InstanceNode extends Node {
 
 	}
 
-	setup( builder ) {
+	setup( /*builder*/ ) {
 
 		let instanceMatrixNode = this.instanceMatrixNode;
 
@@ -57,8 +57,8 @@ class InstanceNode extends Node {
 
 		// ASSIGNS
 
-		builder.stack.assign( positionLocal, instancePosition );
-		builder.stack.assign( normalLocal, instanceNormal );
+		positionLocal.assign( instancePosition );
+		normalLocal.assign( instanceNormal );
 
 	}
 

+ 5 - 5
examples/jsm/nodes/accessors/MorphNode.js

@@ -19,12 +19,12 @@ class MorphNode extends Node {
 
 	}
 
-	setupAttribute( builder, name, assignNode = positionLocal ) {
+	setupAttribute( name, assignNode = positionLocal ) {
 
 		const mesh = this.mesh;
 		const attributes = mesh.geometry.morphAttributes[ name ];
 
-		builder.stack.assign( assignNode, assignNode.mul( this.morphBaseInfluence ) );
+		assignNode.mulAssign( this.morphBaseInfluence );
 
 		for ( let i = 0; i < attributes.length; i ++ ) {
 
@@ -33,15 +33,15 @@ class MorphNode extends Node {
 			const bufferAttrib = bufferAttribute( attribute.array, 'vec3' );
 			const influence = reference( i, 'float', mesh.morphTargetInfluences );
 
-			builder.stack.assign( assignNode, assignNode.add( bufferAttrib.mul( influence ) ) );
+			assignNode.addAssign( bufferAttrib.mul( influence ) );
 
 		}
 
 	}
 
-	setup( builder ) {
+	setup( /*builder*/ ) {
 
-		this.setupAttribute( builder, 'position' );
+		this.setupAttribute( 'position' );
 
 	}
 

+ 3 - 3
examples/jsm/nodes/accessors/SkinningNode.js

@@ -67,12 +67,12 @@ class SkinningNode extends Node {
 
 		// ASSIGNS
 
-		builder.stack.assign( positionLocal, skinPosition );
-		builder.stack.assign( normalLocal, skinNormal );
+		positionLocal.assign( skinPosition );
+		normalLocal.assign( skinNormal );
 
 		if ( builder.hasGeometryAttribute( 'tangent' ) ) {
 
-			builder.stack.assign( tangentLocal, skinNormal );
+			tangentLocal.assign( skinNormal );
 
 		}
 

+ 10 - 3
examples/jsm/nodes/core/NodeBuilder.js

@@ -17,6 +17,8 @@ import {
 import { REVISION, RenderTarget, NoColorSpace, LinearEncoding, sRGBEncoding, SRGBColorSpace, Color, Vector2, Vector3, Vector4, Float16BufferAttribute } from 'three';
 
 import { stack } from './StackNode.js';
+import { getCurrentStack, setCurrentStack } from '../shadernode/ShaderNode.js';
+
 import { maxMipLevel } from '../utils/MaxMipLevelNode.js';
 
 import CubeRenderTarget from '../../renderers/common/CubeRenderTarget.js';
@@ -89,6 +91,7 @@ class NodeBuilder {
 		this.flow = { code: '' };
 		this.chaining = [];
 		this.stack = stack();
+		this.stacks = [];
 		this.tab = '\t';
 
 		this.context = {
@@ -570,17 +573,21 @@ class NodeBuilder {
 
 		this.stack = stack( this.stack );
 
+		this.stacks.push( getCurrentStack() || this.stack );
+		setCurrentStack( this.stack );
+
 		return this.stack;
 
 	}
 
 	removeStack() {
 
-		const currentStack = this.stack;
+		const lastStack = this.stack;
+		this.stack = lastStack.parent;
 
-		this.stack = currentStack.parent;
+		setCurrentStack( this.stacks.pop() );
 
-		return currentStack;
+		return lastStack;
 
 	}
 

+ 7 - 1
examples/jsm/nodes/core/StackNode.js

@@ -2,7 +2,7 @@ import Node, { addNodeClass } from './Node.js';
 import { bypass } from '../core/BypassNode.js';
 import { expression } from '../code/ExpressionNode.js';
 import { cond } from '../math/CondNode.js';
-import { ShaderNode, nodeProxy } from '../shadernode/ShaderNode.js';
+import { ShaderNode, nodeProxy, getCurrentStack, setCurrentStack } from '../shadernode/ShaderNode.js';
 
 class StackNode extends Node {
 
@@ -66,12 +66,18 @@ class StackNode extends Node {
 
 	build( builder, ...params ) {
 
+		const previousStack = getCurrentStack();
+
+		setCurrentStack( this );
+
 		for ( const node of this.nodes ) {
 
 			node.build( builder, 'void' );
 
 		}
 
+		setCurrentStack( previousStack );
+
 		return this.outputNode ? this.outputNode.build( builder, ...params ) : super.build( builder, ...params );
 
 	}

+ 5 - 5
examples/jsm/nodes/functions/PhongLightingModel.js

@@ -41,24 +41,24 @@ class PhongLightingModel extends LightingModel {
 
 	}
 
-	direct( { lightDirection, lightColor, reflectedLight }, stack ) {
+	direct( { lightDirection, lightColor, reflectedLight } ) {
 
 		const dotNL = transformedNormalView.dot( lightDirection ).clamp();
 		const irradiance = dotNL.mul( lightColor );
 
-		stack.addAssign( reflectedLight.directDiffuse, irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) );
+		reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) );
 
 		if ( this.specular === true ) {
 
-			stack.addAssign( reflectedLight.directSpecular, irradiance.mul( BRDF_BlinnPhong( { lightDirection } ) ).mul( materialSpecularStrength ) );
+			reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_BlinnPhong( { lightDirection } ) ).mul( materialSpecularStrength ) );
 
 		}
 
 	}
 
-	indirectDiffuse( { irradiance, reflectedLight }, stack ) {
+	indirectDiffuse( { irradiance, reflectedLight } ) {
 
-		stack.addAssign( reflectedLight.indirectDiffuse, irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) );
+		reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) );
 
 	}
 

+ 23 - 23
examples/jsm/nodes/functions/PhysicalLightingModel.js

@@ -225,7 +225,7 @@ class PhysicalLightingModel extends LightingModel {
 	// Approximates multiscattering in order to preserve energy.
 	// http://www.jcgt.org/published/0008/01/03/
 
-	computeMultiscattering( stack, singleScatter, multiScatter, specularF90 = float( 1 ) ) {
+	computeMultiscattering( singleScatter, multiScatter, specularF90 = float( 1 ) ) {
 
 		const dotNV = transformedNormalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV
 
@@ -241,19 +241,19 @@ class PhysicalLightingModel extends LightingModel {
 		const Favg = specularColor.add( specularColor.oneMinus().mul( 0.047619 ) ); // 1/21
 		const Fms = FssEss.mul( Favg ).div( Ems.mul( Favg ).oneMinus() );
 
-		stack.addAssign( singleScatter, FssEss );
-		stack.addAssign( multiScatter, Fms.mul( Ems ) );
+		singleScatter.addAssign( FssEss );
+		multiScatter.addAssign( Fms.mul( Ems ) );
 
 	}
 
-	direct( { lightDirection, lightColor, reflectedLight }, stack ) {
+	direct( { lightDirection, lightColor, reflectedLight } ) {
 
 		const dotNL = transformedNormalView.dot( lightDirection ).clamp();
 		const irradiance = dotNL.mul( lightColor );
 
 		if ( this.sheen === true ) {
 
-			stack.addAssign( this.sheenSpecular, irradiance.mul( BRDF_Sheen( { lightDirection } ) ) );
+			this.sheenSpecular.addAssign( irradiance.mul( BRDF_Sheen( { lightDirection } ) ) );
 
 		}
 
@@ -262,27 +262,27 @@ class PhysicalLightingModel extends LightingModel {
 			const dotNLcc = transformedClearcoatNormalView.dot( lightDirection ).clamp();
 			const ccIrradiance = dotNLcc.mul( lightColor );
 
-			stack.addAssign( this.clearcoatSpecular, ccIrradiance.mul( BRDF_GGX( { lightDirection, f0: clearcoatF0, f90: clearcoatF90, roughness: clearcoatRoughness, normalView: transformedClearcoatNormalView } ) ) );
+			this.clearcoatSpecular.addAssign( ccIrradiance.mul( BRDF_GGX( { lightDirection, f0: clearcoatF0, f90: clearcoatF90, roughness: clearcoatRoughness, normalView: transformedClearcoatNormalView } ) ) );
 
 		}
 
-		stack.addAssign( reflectedLight.directDiffuse, irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) );
+		reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) );
 
-		stack.addAssign( reflectedLight.directSpecular, irradiance.mul( BRDF_GGX( { lightDirection, f0: specularColor, f90: 1, roughness, iridescence: this.iridescence, iridescenceFresnel: this.iridescenceFresnel } ) ) );
+		reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_GGX( { lightDirection, f0: specularColor, f90: 1, roughness, iridescence: this.iridescence, iridescenceFresnel: this.iridescenceFresnel } ) ) );
 
 	}
 
-	indirectDiffuse( { irradiance, reflectedLight }, stack ) {
+	indirectDiffuse( { irradiance, reflectedLight } ) {
 
-		stack.addAssign( reflectedLight.indirectDiffuse, irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) );
+		reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) );
 
 	}
 
-	indirectSpecular( { radiance, iblIrradiance, reflectedLight }, stack ) {
+	indirectSpecular( { radiance, iblIrradiance, reflectedLight } ) {
 
 		if ( this.sheen === true ) {
 
-			stack.addAssign( this.sheenSpecular, iblIrradiance.mul(
+			this.sheenSpecular.addAssign( iblIrradiance.mul(
 				sheen,
 				IBLSheenBRDF( {
 					normal: transformedNormalView,
@@ -304,7 +304,7 @@ class PhysicalLightingModel extends LightingModel {
 				roughness: clearcoatRoughness
 			} );
 
-			stack.addAssign( this.clearcoatSpecular, this.clearcoatRadiance.mul( clearcoatEnv ) );
+			this.clearcoatSpecular.addAssign( this.clearcoatRadiance.mul( clearcoatEnv ) );
 
 		}
 
@@ -314,20 +314,20 @@ class PhysicalLightingModel extends LightingModel {
 		const multiScattering = vec3().temp( 'multiScattering' );
 		const cosineWeightedIrradiance = iblIrradiance.mul( 1 / Math.PI );
 
-		this.computeMultiscattering( stack, singleScattering, multiScattering );
+		this.computeMultiscattering( singleScattering, multiScattering );
 
 		const totalScattering = singleScattering.add( multiScattering );
 
 		const diffuse = diffuseColor.mul( totalScattering.r.max( totalScattering.g ).max( totalScattering.b ).oneMinus() );
 
-		stack.addAssign( reflectedLight.indirectSpecular, radiance.mul( singleScattering ) );
-		stack.addAssign( reflectedLight.indirectSpecular, multiScattering.mul( cosineWeightedIrradiance ) );
+		reflectedLight.indirectSpecular.addAssign( radiance.mul( singleScattering ) );
+		reflectedLight.indirectSpecular.addAssign( multiScattering.mul( cosineWeightedIrradiance ) );
 
-		stack.addAssign( reflectedLight.indirectDiffuse, diffuse.mul( cosineWeightedIrradiance ) );
+		reflectedLight.indirectDiffuse.addAssign( diffuse.mul( cosineWeightedIrradiance ) );
 
 	}
 
-	ambientOcclusion( { ambientOcclusion, reflectedLight }, stack ) {
+	ambientOcclusion( { ambientOcclusion, reflectedLight } ) {
 
 		const dotNV = transformedNormalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV
 
@@ -336,12 +336,12 @@ class PhysicalLightingModel extends LightingModel {
 
 		const aoNode = ambientOcclusion.sub( aoNV.pow( aoExp ).oneMinus() ).clamp();
 
-		stack.mulAssign( reflectedLight.indirectDiffuse, ambientOcclusion );
-		stack.mulAssign( reflectedLight.indirectSpecular, aoNode );
+		reflectedLight.indirectDiffuse.mulAssign( ambientOcclusion );
+		reflectedLight.indirectSpecular.mulAssign( aoNode );
 
 	}
 
-	finish( context, stack ) {
+	finish( context ) {
 
 		const { outgoingLight } = context;
 
@@ -357,7 +357,7 @@ class PhysicalLightingModel extends LightingModel {
 
 			const clearcoatLight = outgoingLight.mul( clearcoat.mul( Fcc ).oneMinus() ).add( this.clearcoatSpecular.mul( clearcoat ) );
 
-			stack.assign( outgoingLight, clearcoatLight );
+			outgoingLight.assign( clearcoatLight );
 
 		}
 
@@ -366,7 +366,7 @@ class PhysicalLightingModel extends LightingModel {
 			const sheenEnergyComp = sheen.r.max( sheen.g ).max( sheen.b ).mul( 0.157 ).oneMinus();
 			const sheenLight = outgoingLight.mul( sheenEnergyComp ).add( this.sheenSpecular );
 
-			stack.assign( outgoingLight, sheenLight );
+			outgoingLight.assign( sheenLight );
 
 		}
 

+ 1 - 1
examples/jsm/nodes/lighting/AONode.js

@@ -16,7 +16,7 @@ class AONode extends LightingNode {
 		const aoIntensity = 1;
 		const aoNode = this.aoNode.x.sub( 1.0 ).mul( aoIntensity ).add( 1.0 );
 
-		builder.stack.mulAssign( builder.context.ambientOcclusion, aoNode );
+		builder.context.ambientOcclusion.mulAssign( aoNode );
 
 	}
 

+ 2 - 2
examples/jsm/nodes/lighting/AmbientLightNode.js

@@ -12,9 +12,9 @@ class AmbientLightNode extends AnalyticLightNode {
 
 	}
 
-	setup( builder ) {
+	setup( { context } ) {
 
-		builder.stack.addAssign( builder.context.irradiance, this.colorNode );
+		context.irradiance.addAssign(this.colorNode );
 
 	}
 

+ 3 - 5
examples/jsm/nodes/lighting/EnvironmentNode.js

@@ -61,11 +61,9 @@ class EnvironmentNode extends LightingNode {
 
 		//
 
-		const { stack } = builder;
+		builder.context.radiance.addAssign( isolateRadiance );
 
-		stack.addAssign( builder.context.radiance, isolateRadiance );
-
-		stack.addAssign( builder.context.iblIrradiance, irradiance );
+		builder.context.iblIrradiance.addAssign( irradiance );
 
 		//
 
@@ -76,7 +74,7 @@ class EnvironmentNode extends LightingNode {
 			const clearcoatRadianceContext = context( envNode, createRadianceContext( clearcoatRoughness, transformedClearcoatNormalView ) ).mul( intensity );
 			const isolateClearcoatRadiance = cache( clearcoatRadianceContext );
 
-			stack.addAssign( clearcoatRadiance, isolateClearcoatRadiance );
+			clearcoatRadiance.addAssign( isolateClearcoatRadiance );
 
 		}
 

+ 1 - 1
examples/jsm/nodes/lighting/HemisphereLightNode.js

@@ -42,7 +42,7 @@ class HemisphereLightNode extends AnalyticLightNode {
 
 		const irradiance = mix( groundColorNode, colorNode, hemiDiffuseWeight );
 
-		builder.stack.addAssign( builder.context.irradiance, irradiance );
+		builder.context.irradiance.addAssign( irradiance );
 
 	}
 

+ 3 - 3
examples/jsm/nodes/lighting/LightsNode.js

@@ -79,10 +79,10 @@ class LightsNode extends Node {
 	
 			}
 
-			stack.assign( totalDiffuseNode, totalDiffuse );
-			stack.assign( totalSpecularNode, directSpecular.add( indirectSpecular ) );
+			totalDiffuseNode.assign( totalDiffuse );
+			totalSpecularNode.assign( directSpecular.add( indirectSpecular ) );
 
-			stack.assign( outgoingLightNode, totalDiffuseNode.add( totalSpecularNode ) );
+			outgoingLightNode.assign( totalDiffuseNode.add( totalSpecularNode ) );
 
 			//
 

+ 57 - 58
examples/jsm/nodes/materials/Line2NodeMaterial.js

@@ -8,7 +8,7 @@ import { materialColor } from '../accessors/MaterialNode.js';
 import { modelViewMatrix } from '../accessors/ModelNode.js';
 import { positionGeometry } from '../accessors/PositionNode.js';
 import { abs, mix, mod, dot, clamp, smoothstep } from '../math/MathNode.js';
-import { tslFn, ShaderNode, float, vec2, vec3, vec4 } from '../shadernode/ShaderNode.js';
+import { tslFn, float, vec2, vec3, vec4, If } from '../shadernode/ShaderNode.js';
 import { uv } from '../accessors/UVNode.js';
 import { materialLineScale, materialLineDashSize, materialLineGapSize, materialLineDashOffset, materialLineWidth } from '../accessors/LineMaterialNode.js';
 import { viewport } from '../display/ViewportNode.js';
@@ -69,9 +69,9 @@ class Line2NodeMaterial extends NodeMaterial {
 
 		} );
 
-		this.vertexNode = new ShaderNode( ( stack ) => {
+		this.vertexNode = tslFn( () => {
 
-			stack.assign( varying( vec2(), 'vUv' ), uv() );
+			varying( vec2(), 'vUv' ).assign( uv() ); // @TODO: Analyze other way to do this
 
 			const instanceStart = attribute( 'instanceStart' );
 			const instanceEnd = attribute( 'instanceEnd' );
@@ -81,13 +81,13 @@ class Line2NodeMaterial extends NodeMaterial {
 			const start = property( 'vec4', 'start' );
 			const end = property( 'vec4', 'end' );
 
-			stack.assign( start, modelViewMatrix.mul( vec4( instanceStart, 1.0 ) ) ); // force assignment into correct place in flow
-			stack.assign( end, modelViewMatrix.mul( vec4( instanceEnd, 1.0 ) ) );
+			start.assign( modelViewMatrix.mul( vec4( instanceStart, 1.0 ) ) ); // force assignment into correct place in flow
+			end.assign( modelViewMatrix.mul( vec4( instanceEnd, 1.0 ) ) );
 
 			if ( useWorldUnits ) {
 
-				stack.assign( varying( vec3(), 'worldStart' ), start.xyz );
-				stack.assign( varying( vec3(), 'worldEnd' ), end.xyz );
+				varying( vec3(), 'worldStart' ).assign( start.xyz );
+				varying( vec3(), 'worldEnd' ).assign( end.xyz );
 
 			}
 
@@ -100,15 +100,15 @@ class Line2NodeMaterial extends NodeMaterial {
 
 			const perspective = cameraProjectionMatrix.element( 2 ).element( 3 ).equal( -1.0 ); // 4th entry in the 3rd column
 
-			stack.if( perspective, ( stack ) => {
+			If( perspective, () => {
 
-				stack.if( start.z.lessThan( 0.0 ).and( end.z.greaterThan( 0.0 ) ), ( stack ) => {
+				If( start.z.lessThan( 0.0 ).and( end.z.greaterThan( 0.0 ) ), () => {
 
-					stack.assign( end, trimSegment( { start: start, end: end } ) );
+					end.assign( trimSegment( { start: start, end: end } ) );
 
-				} ).elseif( end.z.lessThan( 0.0 ).and( start.z.greaterThanEqual( 0.0 ) ), ( stack ) => {
+				} ).elseif( end.z.lessThan( 0.0 ).and( start.z.greaterThanEqual( 0.0 ) ), () => {
 
-					stack.assign( start, trimSegment( { start: end, end: start } ) );
+					start.assign( trimSegment( { start: end, end: start } ) );
 
 			 	} );
 
@@ -126,8 +126,8 @@ class Line2NodeMaterial extends NodeMaterial {
 			const dir = ndcEnd.xy.sub( ndcStart.xy ).temp();
 
 			// account for clip-space aspect ratio
-			stack.assign( dir.x, dir.x.mul( aspect ) );
-			stack.assign( dir, dir.normalize() );
+			dir.x.assign( dir.x.mul( aspect ) );
+			dir.assign( dir.normalize() );
 
 			const clip = temp( vec4() );
 
@@ -143,7 +143,7 @@ class Line2NodeMaterial extends NodeMaterial {
 				);
 
 				// sign flip
-				stack.assign( offset, positionGeometry.x.lessThan( 0.0 ).cond( offset.negate(), offset ) );
+				offset.assign( positionGeometry.x.lessThan( 0.0 ).cond( offset.negate(), offset ) );
 
 				const forwardOffset = worldDir.dot( vec3( 0.0, 0.0, 1.0 ) );
 
@@ -152,86 +152,86 @@ class Line2NodeMaterial extends NodeMaterial {
 				if ( ! useDash ) {
 
 					// extend the line bounds to encompass endcaps
-					stack.assign( start, start.sub( vec4( worldDir.mul( materialLineWidth ).mul( 0.5 ), 0 ) ) );
-					stack.assign( end, end.add( vec4( worldDir.mul( materialLineWidth ).mul( 0.5 ), 0 ) ) );
+					start.assign( start.sub( vec4( worldDir.mul( materialLineWidth ).mul( 0.5 ), 0 ) ) );
+					end.assign( end.add( vec4( worldDir.mul( materialLineWidth ).mul( 0.5 ), 0 ) ) );
 
 					// shift the position of the quad so it hugs the forward edge of the line
-					stack.assign( offset, offset.sub( vec3( dir.mul( forwardOffset ), 0 ) ) );
-					stack.assign( offset.z, offset.z.add( 0.5 ) );
+					offset.assign( offset.sub( vec3( dir.mul( forwardOffset ), 0 ) ) );
+					offset.z.assign( offset.z.add( 0.5 ) );
 
 				}
 
 				// endcaps
 
-				stack.if( positionGeometry.y.greaterThan( 1.0 ).or( positionGeometry.y.lessThan( 0.0 ) ), ( stack ) => {
+				If( positionGeometry.y.greaterThan( 1.0 ).or( positionGeometry.y.lessThan( 0.0 ) ), () => {
 
-					stack.assign( offset, offset.add( vec3( dir.mul( 2.0 ).mul( forwardOffset ), 0 ) ) );
+					offset.assign( offset.add( vec3( dir.mul( 2.0 ).mul( forwardOffset ), 0 ) ) );
 
 				} );
 
 				// adjust for linewidth
-				stack.assign( offset, offset.mul( materialLineWidth ).mul( 0.5 ) );
+				offset.assign( offset.mul( materialLineWidth ).mul( 0.5 ) );
 
 				// set the world position
 
 				const worldPos = varying( vec4(), 'worldPos' );
 
-				stack.assign( worldPos, positionGeometry.y.lessThan( 0.5 ).cond( start, end ) );
-				stack.assign( worldPos, worldPos.add( vec4( offset, 0 ) ) );
+				worldPos.assign( positionGeometry.y.lessThan( 0.5 ).cond( start, end ) );
+				worldPos.assign( worldPos.add( vec4( offset, 0 ) ) );
 
 				// project the worldpos
-				stack.assign( clip, cameraProjectionMatrix.mul( worldPos ) );
+				clip.assign( cameraProjectionMatrix.mul( worldPos ) );
 
 				// shift the depth of the projected points so the line
 				// segments overlap neatly
 				const clipPose = temp( vec3() );
 
-				stack.assign( clipPose, positionGeometry.y.lessThan( 0.5 ).cond( ndcStart, ndcEnd ) );
-				stack.assign( clip.z, clipPose.z.mul( clip.w ) );
+				clipPose.assign( positionGeometry.y.lessThan( 0.5 ).cond( ndcStart, ndcEnd ) );
+				clip.z.assign( clipPose.z.mul( clip.w ) );
 
 			} else {
 
 				const offset = property( 'vec2', 'offset' );
 
-				stack.assign( offset, vec2( dir.y, dir.x.negate() ) );
+				offset.assign( vec2( dir.y, dir.x.negate() ) );
 
 				// undo aspect ratio adjustment
-				stack.assign( dir.x, dir.x.div( aspect ) );
-				stack.assign( offset.x, offset.x.div( aspect ) );
+				dir.x.assign( dir.x.div( aspect ) );
+				offset.x.assign( offset.x.div( aspect ) );
 
 				// sign flip
-				stack.assign( offset, positionGeometry.x.lessThan( 0.0 ).cond( offset.negate(), offset ) );
+				offset.assign( positionGeometry.x.lessThan( 0.0 ).cond( offset.negate(), offset ) );
 
 				// endcaps
-				stack.if( positionGeometry.y.lessThan( 0.0 ), ( stack ) => {
+				If( positionGeometry.y.lessThan( 0.0 ), () => {
 
-					stack.assign( offset, offset.sub( dir ) );
+					offset.assign( offset.sub( dir ) );
 
-				} ).elseif( positionGeometry.y.greaterThan( 1.0 ), ( stack ) => {
+				} ).elseif( positionGeometry.y.greaterThan( 1.0 ), () => {
 
-					stack.assign( offset, offset.add( dir ) );
+					offset.assign( offset.add( dir ) );
 
 				} );
 
 				// adjust for linewidth
-				stack.assign( offset, offset.mul( materialLineWidth ) );
+				offset.assign( offset.mul( materialLineWidth ) );
 
 				// adjust for clip-space to screen-space conversion // maybe resolution should be based on viewport ...
-				stack.assign( offset, offset.div( viewport.w ) );
+				offset.assign( offset.div( viewport.w ) );
 
 				// select end
-				stack.assign( clip, positionGeometry.y.lessThan( 0.5 ).cond( clipStart, clipEnd ) );
+				clip.assign( positionGeometry.y.lessThan( 0.5 ).cond( clipStart, clipEnd ) );
 
 				// back to clip space
-				stack.assign( offset, offset.mul( clip.w ) );
+				offset.assign( offset.mul( clip.w ) );
 
-				stack.assign( clip, clip.add( vec4( offset, 0, 0 ) ) );
+				clip.assign( clip.add( vec4( offset, 0, 0 ) ) );
 
 			}
 
 			return clip;
 
-		} );
+		} )();
 
 		const closestLineToLine = tslFn( ( { p1, p2, p3, p4 } ) => {
 
@@ -256,7 +256,7 @@ class Line2NodeMaterial extends NodeMaterial {
 
 		} );
 
-		this.colorNode = new ShaderNode( ( stack ) => {
+		this.colorNode = tslFn( () => {
 
 			const vUv = varying( vec2(), 'vUv' );
 
@@ -267,8 +267,8 @@ class Line2NodeMaterial extends NodeMaterial {
 				const dashSizeNode = this.dashSizeNode ? float( this.dashSizeNode ) : materialLineDashSize;
 				const gapSizeNode = this.dashSizeNode ? float( this.dashGapNode ) : materialLineGapSize;
 
-				stack.assign( dashSize, dashSizeNode );
-				stack.assign( gapSize, gapSizeNode );
+				dashSize.assign( dashSizeNode );
+				gapSize.assign( gapSizeNode );
 
 				const instanceDistanceStart = attribute( 'instanceDistanceStart' );
 				const instanceDistanceEnd = attribute( 'instanceDistanceEnd' );
@@ -278,20 +278,19 @@ class Line2NodeMaterial extends NodeMaterial {
 				const vLineDistance = varying( lineDistance.add( materialLineDashOffset ) );
 				const vLineDistanceOffset = offsetNode ? vLineDistance.add( offsetNode ) : vLineDistance;
 
-				stack.add( vUv.y.lessThan( - 1.0 ).or( vUv.y.greaterThan( 1.0 ) ).discard() ); // discard endcaps
-				stack.add( mod( vLineDistanceOffset, dashSize.add( gapSize ) ).greaterThan( dashSize ).discard() ); // todo - FIX
+				vUv.y.lessThan( - 1.0 ).or( vUv.y.greaterThan( 1.0 ) ).discard(); // discard endcaps
+				mod( vLineDistanceOffset, dashSize.add( gapSize ) ).greaterThan( dashSize ).discard(); // todo - FIX
 
 			}
 
 			 // force assignment into correct place in flow
 			const alpha = property( 'float', 'alpha' );
-			stack.assign( alpha, 1 );
+			alpha.assign( 1 );
 
 			if ( useWorldUnits ) {
 
-
-				let worldStart = varying( vec3(), 'worldStart' );
-				let worldEnd = varying( vec3(), 'worldEnd' );
+				const worldStart = varying( vec3(), 'worldStart' );
+				const worldEnd = varying( vec3(), 'worldEnd' );
 
 				// Find the closest points on the view ray and the line segment
 				const rayEnd = varying( vec4(), 'worldPos' ).xyz.normalize().mul( 1e5 );
@@ -309,11 +308,11 @@ class Line2NodeMaterial extends NodeMaterial {
 					if ( useAlphaToCoverage ) {
 
 						const dnorm = norm.fwidth();
-						stack.assign( alpha, smoothstep( dnorm.negate().add( 0.5 ), dnorm.add( 0.5 ), norm ).oneMinus() );
+						alpha.assign( smoothstep( dnorm.negate().add( 0.5 ), dnorm.add( 0.5 ), norm ).oneMinus() );
 
 					} else {
 
-						stack.add( norm.greaterThan( 0.5 ).discard() );
+						norm.greaterThan( 0.5 ).discard();
 
 					}
 
@@ -332,23 +331,23 @@ class Line2NodeMaterial extends NodeMaterial {
 
 					// force assignment out of following 'if' statement - to avoid uniform control flow errors
 					const dlen = property( 'float', 'dlen' );
-					stack.assign( dlen, len2.fwidth() );
+					dlen.assign( len2.fwidth() );
 
-					stack.if( abs( vUv.y ).greaterThan( 1.0 ), ( stack ) => {
+					If( abs( vUv.y ).greaterThan( 1.0 ), () => {
 
-						stack.assign( alpha, smoothstep( dlen.oneMinus(), dlen.add( 1 ), len2 ).oneMinus() );
+						alpha.assign( smoothstep( dlen.oneMinus(), dlen.add( 1 ), len2 ).oneMinus() );
 
 					} );
 
 				} else {
 
-					stack.if( abs( vUv.y ).greaterThan( 1.0 ), ( stack ) => {
+					If( abs( vUv.y ).greaterThan( 1.0 ), () => {
 
 						const a = vUv.x;
 						const b = vUv.y.greaterThan( 0.0 ).cond( vUv.y.sub( 1.0 ), vUv.y.add( 1.0 ) );
 						const len2 = a.mul( a ).add( b.mul( b ) );
 
-						stack.add( len2.greaterThan( 1.0 ).discard() );
+						len2.greaterThan( 1.0 ).discard();
 
 					} );
 
@@ -381,7 +380,7 @@ class Line2NodeMaterial extends NodeMaterial {
 
 			return vec4( lineColorNode, alpha );
 
-		} );
+		} )();
 
 		this.needsUpdate = true;
 

+ 4 - 4
examples/jsm/nodes/materials/LineDashedNodeMaterial.js

@@ -30,20 +30,20 @@ class LineDashedNodeMaterial extends NodeMaterial {
 
 	}
 
-	setupVariants( { stack } ) {
+	setupVariants() {
 
 		const offsetNode = this.offsetNode;
 		const dashScaleNode = this.dashScaleNode ? float( this.dashScaleNode ) : materialLineScale;
 		const dashSizeNode = this.dashSizeNode ? float( this.dashSizeNode ) : materialLineDashSize;
 		const gapSizeNode = this.dashSizeNode ? float( this.dashGapNode ) : materialLineGapSize;
 
-		stack.assign( dashSize, dashSizeNode );
-		stack.assign( gapSize, gapSizeNode );
+		dashSize.assign( dashSizeNode );
+		gapSize.assign( gapSizeNode );
 
 		const vLineDistance = varying( attribute( 'lineDistance' ).mul( dashScaleNode ) );
 		const vLineDistanceOffset = offsetNode ? vLineDistance.add( offsetNode ) : vLineDistance;
 
-		stack.add( vLineDistanceOffset.mod( dashSize.add( gapSize ) ).greaterThan( dashSize ).discard() );
+		vLineDistanceOffset.mod( dashSize.add( gapSize ) ).greaterThan( dashSize ).discard();
 
 	}
 

+ 2 - 2
examples/jsm/nodes/materials/MeshNormalNodeMaterial.js

@@ -25,11 +25,11 @@ class MeshNormalNodeMaterial extends NodeMaterial {
 
 	}
 
-	setupDiffuseColor( { stack } ) {
+	setupDiffuseColor() {
 
 		const opacityNode = this.opacityNode ? float( this.opacityNode ) : materialOpacity;
 
-		stack.assign( diffuseColor, vec4( directionToColor( transformedNormalView ), opacityNode ) );
+		diffuseColor.assign( vec4( directionToColor( transformedNormalView ), opacityNode ) );
 
 	}
 

+ 3 - 3
examples/jsm/nodes/materials/MeshPhongNodeMaterial.js

@@ -33,19 +33,19 @@ class MeshPhongNodeMaterial extends NodeMaterial {
 
 	}
 
-	setupVariants( { stack } ) {
+	setupVariants() {
 
 		// SHININESS
 
 		const shininessNode = ( this.shininessNode ? float( this.shininessNode ) : materialShininess ).max( 1e-4 ); // to prevent pow( 0.0, 0.0 )
 
-		stack.assign( shininess, shininessNode );
+		shininess.assign( shininessNode );
 
 		// SPECULAR COLOR
 
 		const specularNode = this.specularNode || materialSpecularColor;
 
-		stack.assign( specularColor, specularNode );
+		specularColor.assign( specularNode );
 
 	}
 

+ 8 - 10
examples/jsm/nodes/materials/MeshPhysicalNodeMaterial.js

@@ -72,8 +72,6 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial {
 
 		super.setupVariants( builder );
 
-		const { stack } = builder;
-
 		// CLEARCOAT
 
 		if ( this.useClearcoat ) {
@@ -81,8 +79,8 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial {
 			const clearcoatNode = this.clearcoatNode ? float( this.clearcoatNode ) : materialClearcoat;
 			const clearcoatRoughnessNode = this.clearcoatRoughnessNode ? float( this.clearcoatRoughnessNode ) : materialClearcoatRoughness;
 
-			stack.assign( clearcoat, clearcoatNode );
-			stack.assign( clearcoatRoughness, clearcoatRoughnessNode );
+			clearcoat.assign( clearcoatNode );
+			clearcoatRoughness.assign( clearcoatRoughnessNode );
 
 		}
 
@@ -93,8 +91,8 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial {
 			const sheenNode = this.sheenNode ? vec3( this.sheenNode ) : materialSheen;
 			const sheenRoughnessNode = this.sheenRoughnessNode ? float( this.sheenRoughnessNode ) : materialSheenRoughness;
 
-			stack.assign( sheen, sheenNode );
-			stack.assign( sheenRoughness, sheenRoughnessNode );
+			sheen.assign( sheenNode );
+			sheenRoughness.assign( sheenRoughnessNode );
 
 		}
 
@@ -106,9 +104,9 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial {
 			const iridescenceIORNode = this.iridescenceIORNode ? float( this.iridescenceIORNode ) : materialIridescenceIOR;
 			const iridescenceThicknessNode = this.iridescenceThicknessNode ? float( this.iridescenceThicknessNode ) : materialIridescenceThickness;
 
-			stack.assign( iridescence, iridescenceNode );
-			stack.assign( iridescenceIOR, iridescenceIORNode );
-			stack.assign( iridescenceThickness, iridescenceThicknessNode );
+			iridescence.assign( iridescenceNode );
+			iridescenceIOR.assign( iridescenceIORNode );
+			iridescenceThickness.assign( iridescenceThicknessNode );
 
 		}
 
@@ -122,7 +120,7 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial {
 
 		const clearcoatNormalNode = this.clearcoatNormalNode ? vec3( this.clearcoatNormalNode ) : materialClearcoatNormal;
 
-		builder.stack.assign( transformedClearcoatNormalView, clearcoatNormalNode );
+		transformedClearcoatNormalView.assign( clearcoatNormalNode );
 
 	}
 

+ 5 - 5
examples/jsm/nodes/materials/MeshStandardNodeMaterial.js

@@ -35,30 +35,30 @@ class MeshStandardNodeMaterial extends NodeMaterial {
 
 	}
 
-	setupVariants( { stack } ) {
+	setupVariants() {
 
 		// METALNESS
 
 		const metalnessNode = this.metalnessNode ? float( this.metalnessNode ) : materialMetalness;
 
-		stack.assign( metalness, metalnessNode );
+		metalness.assign( metalnessNode );
 
 		// ROUGHNESS
 
 		let roughnessNode = this.roughnessNode ? float( this.roughnessNode ) : materialRoughness;
 		roughnessNode = getRoughness( { roughness: roughnessNode } );
 
-		stack.assign( roughness, roughnessNode );
+		roughness.assign( roughnessNode );
 
 		// SPECULAR COLOR
 
 		const specularColorNode = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessNode );
 
-		stack.assign( specularColor, specularColorNode );
+		specularColor.assign( specularColorNode );
 
 		// DIFFUSE COLOR
 
-		stack.assign( diffuseColor, vec4( diffuseColor.rgb.mul( metalnessNode.oneMinus() ), diffuseColor.a ) );
+		diffuseColor.assign( vec4( diffuseColor.rgb.mul( metalnessNode.oneMinus() ), diffuseColor.a ) );
 
 	}
 

+ 12 - 12
examples/jsm/nodes/materials/NodeMaterial.js

@@ -98,7 +98,7 @@ class NodeMaterial extends ShaderMaterial {
 
 			// OUTPUT NODE
 
-			builder.stack.assign( output, outputNode );
+			output.assign( outputNode );
 
 			//
 
@@ -125,25 +125,25 @@ class NodeMaterial extends ShaderMaterial {
 
 		if ( geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color ) {
 
-			builder.stack.add( morph( object ) );
+			morph( object ).append();
 
 		}
 
 		if ( object.isSkinnedMesh === true ) {
 
-			builder.stack.add( skinning( object ) );
+			skinning( object ).append();
 
 		}
 
 		if ( ( object.instanceMatrix && object.instanceMatrix.isInstancedBufferAttribute === true ) && builder.isAvailable( 'instance' ) === true ) {
 
-			builder.stack.add( instance( object ) );
+			instance( object ).append();
 
 		}
 
 		if ( this.positionNode !== null ) {
 
-			builder.stack.assign( positionLocal, this.positionNode );
+			positionLocal.assign( this.positionNode );
 
 		}
 
@@ -153,7 +153,7 @@ class NodeMaterial extends ShaderMaterial {
 
 	}
 
-	setupDiffuseColor( { stack, geometry } ) {
+	setupDiffuseColor( { geometry } ) {
 
 		let colorNode = this.colorNode ? vec4( this.colorNode ) : materialColor;
 
@@ -167,12 +167,12 @@ class NodeMaterial extends ShaderMaterial {
 
 		// COLOR
 
-		stack.assign( diffuseColor, colorNode );
+		diffuseColor.assign( colorNode );
 
 		// OPACITY
 
 		const opacityNode = this.opacityNode ? float( this.opacityNode ) : materialOpacity;
-		stack.assign( diffuseColor.a, diffuseColor.a.mul( opacityNode ) );
+		diffuseColor.a.assign( diffuseColor.a.mul( opacityNode ) );
 
 		// ALPHA TEST
 
@@ -180,7 +180,7 @@ class NodeMaterial extends ShaderMaterial {
 
 			const alphaTestNode = this.alphaTestNode !== null ? float( this.alphaTestNode ) : materialAlphaTest;
 
-			stack.add( diffuseColor.a.lessThanEqual( alphaTestNode ).discard() );
+			diffuseColor.a.lessThanEqual( alphaTestNode ).discard();
 
 		}
 
@@ -192,7 +192,7 @@ class NodeMaterial extends ShaderMaterial {
 
 	}
 
-	setupNormal( { stack } ) {
+	setupNormal() {
 
 		// NORMAL VIEW
 
@@ -202,13 +202,13 @@ class NodeMaterial extends ShaderMaterial {
 			const fdy = dFdy( positionView );
 			const normalNode = fdx.cross( fdy ).normalize();
 
-			stack.assign( transformedNormalView, normalNode );
+			transformedNormalView.assign( normalNode );
 
 		} else {
 
 			const normalNode = this.normalNode ? vec3( this.normalNode ) : materialNormal;
 
-			stack.assign( transformedNormalView, normalNode );
+			transformedNormalView.assign( normalNode );
 
 		}
 

+ 21 - 1
examples/jsm/nodes/shadernode/ShaderNode.js

@@ -7,6 +7,10 @@ import SetNode from '../utils/SetNode.js';
 import ConstNode from '../core/ConstNode.js';
 import { getValueFromType, getValueType } from '../core/NodeUtils.js';
 
+//
+
+let currentStack = null;
+
 const NodeElements = new Map(); // @TODO: Currently only a few nodes are added, probably also add others
 
 export function addNodeElement( name, nodeElement ) {
@@ -34,7 +38,11 @@ const shaderNodeHandler = {
 
 		if ( typeof prop === 'string' && node[ prop ] === undefined ) {
 
-			if ( NodeElements.has( prop ) ) {
+			if ( node.isStackNode !== true && prop === 'assign' ) {
+
+				return ( ...params ) => assign( node, ...params );
+
+			} else if ( NodeElements.has( prop ) ) {
 
 				const nodeElement = NodeElements.get( prop );
 
@@ -449,6 +457,18 @@ export const tslFn = ( jsFunc ) => {
 
 addNodeClass( 'ShaderNode', ShaderNode );
 
+//
+
+export const setCurrentStack = stack => currentStack = stack;
+export const getCurrentStack = () => currentStack;
+
+export const If = ( ...params ) => currentStack.if( ...params );
+export const append = ( ...params ) => currentStack.add( ...params );
+
+const assign = ( ...params ) => currentStack.assign( ...params );
+
+addNodeElement( 'append', append );
+
 // types
 // @TODO: Maybe export from ConstNode.js?
 

+ 3 - 2
examples/jsm/nodes/utils/DiscardNode.js

@@ -19,8 +19,9 @@ class DiscardNode extends CondNode {
 
 export default DiscardNode;
 
-export const discard = nodeProxy( DiscardNode );
+export const inlineDiscard = nodeProxy( DiscardNode );
+export const discard = ( condNode ) => inlineDiscard( condNode ).append();
 
-addNodeElement( 'discard', discard );
+addNodeElement( 'discard', discard ); // @TODO: Check... this cause a little confusing using in chaining
 
 addNodeClass( 'DiscardNode', DiscardNode );

+ 2 - 2
examples/webgpu_compute_audio.html

@@ -134,7 +134,7 @@
 
 				// compute (shader-node)
 
-				const computeShaderFn = tslFn( ( stack ) => {
+				const computeShaderFn = tslFn( () => {
 
 					const index = float( instanceIndex );
 
@@ -161,7 +161,7 @@
 
 					const waveStorageElementNode = waveStorageNode.element( instanceIndex );
 
-					stack.assign( waveStorageElementNode, wave );
+					waveStorageElementNode.assign( wave );
 
 				} );
 

+ 17 - 17
examples/webgpu_compute_particles.html

@@ -24,7 +24,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { tslFn, uniform, texture, instanceIndex, float, vec3, storage, SpriteNodeMaterial } from 'three/nodes';
+			import { tslFn, uniform, texture, instanceIndex, float, vec3, storage, SpriteNodeMaterial, If } from 'three/nodes';
 
 			import WebGPU from 'three/addons/capabilities/WebGPU.js';
 			import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js';
@@ -81,7 +81,7 @@
 
 				// compute
 
-				const computeInit = tslFn( ( stack ) => {
+				const computeInit = tslFn( () => {
 
 					const position = positionBuffer.element( instanceIndex );
 					const color = colorBuffer.element( instanceIndex );
@@ -90,37 +90,37 @@
 					const randY = instanceIndex.add( 2 ).hash();
 					const randZ = instanceIndex.add( 3 ).hash();
 
-					stack.assign( position.x, randX.mul( 60 ).add( - 30 ) );
-					stack.assign( position.y, randY.mul( 10 ) );
-					stack.assign( position.z, randZ.mul( 60 ).add( - 30 ) );
+					position.x.assign( randX.mul( 60 ).add( - 30 ) );
+					position.y.assign( randY.mul( 10 ) );
+					position.z.assign( randZ.mul( 60 ).add( - 30 ) );
 
-					stack.assign( color, vec3( randX, randY, randZ ) );
+					color.assign( vec3( randX, randY, randZ ) );
 
 				} )().compute( particleCount );
 
 				//
 
-				const computeUpdate = tslFn( ( stack ) => {
+				const computeUpdate = tslFn( () => {
 
 					const position = positionBuffer.element( instanceIndex );
 					const velocity = velocityBuffer.element( instanceIndex );
 
-					stack.assign( velocity, velocity.add( vec3( 0.00, gravity, 0.00 ) ) );
-					stack.assign( position, position.add( velocity ) );
+					velocity.assign( velocity.add( vec3( 0.00, gravity, 0.00 ) ) );
+					position.assign( position, position.add( velocity ) );
 
-					stack.assign( velocity, velocity.mul( friction ) );
+					velocity.assign( velocity.mul( friction ) );
 
 					// floor
 
-					stack.if( position.y.lessThan( 0 ), ( stack ) => {
+					If( position.y.lessThan( 0 ), () => {
 
-						stack.assign( position.y, 0 );
-						stack.assign( velocity.y, velocity.y.negate().mul( bounce ) );
+						position.y.assign( 0 );
+						velocity.y.assign( velocity.y.negate().mul( bounce ) );
 
 						// floor friction
 
-						stack.assign( velocity.x, velocity.x.mul( .9 ) );
-						stack.assign( velocity.z, velocity.z.mul( .9 ) );
+						velocity.x.assign( velocity.x.mul( .9 ) );
+						velocity.z.assign( velocity.z.mul( .9 ) );
 
 					} );
 
@@ -177,7 +177,7 @@
 
 				// click event
 
-				const computeHit = tslFn( ( stack ) => {
+				const computeHit = tslFn( () => {
 
 					const position = positionBuffer.element( instanceIndex );
 					const velocity = velocityBuffer.element( instanceIndex );
@@ -189,7 +189,7 @@
 					const power = distArea.mul( .1 );
 					const relativePower = power.mul( instanceIndex.hash().mul( .5 ).add( .5 ) );
 
-					stack.assign( velocity, velocity.add( direction.mul( relativePower ) ) );
+					velocity.assign( velocity.add( direction.mul( relativePower ) ) );
 
 				} )().compute( particleCount );
 

+ 7 - 7
examples/webgpu_compute_points.html

@@ -72,7 +72,7 @@
 
 				// create function
 
-				const computeShaderFn = tslFn( ( stack ) => {
+				const computeShaderFn = tslFn( () => {
 
 					const particle = particleBufferNode.element( instanceIndex );
 					const velocity = velocityBufferNode.element( instanceIndex );
@@ -82,15 +82,15 @@
 
 					const position = particle.add( velocity ).temp();
 
-					stack.assign( velocity.x, position.x.abs().greaterThanEqual( limit.x ).cond( velocity.x.negate(), velocity.x ) );
-					stack.assign( velocity.y, position.y.abs().greaterThanEqual( limit.y ).cond( velocity.y.negate(), velocity.y ) );
+					velocity.x.assign( position.x.abs().greaterThanEqual( limit.x ).cond( velocity.x.negate(), velocity.x ) );
+					velocity.y.assign( position.y.abs().greaterThanEqual( limit.y ).cond( velocity.y.negate(), velocity.y ) );
 
-					stack.assign( position, position.min( limit ).max( limit.negate() ) );
+					position.assign( position.min( limit ).max( limit.negate() ) );
 
 					const pointerSize = 0.1;
 					const distanceFromPointer = pointer.sub( position ).length();
 
-					stack.assign( particle, distanceFromPointer.lessThanEqual( pointerSize ).cond( vec3(), position ) );
+					particle.assign( distanceFromPointer.lessThanEqual( pointerSize ).cond( vec3(), position ) );
 
 				} );
 
@@ -99,7 +99,7 @@
 				computeNode = computeShaderFn().compute( particleNum );
 				computeNode.onInit = ( { renderer } ) => {
 
-					const precomputeShaderNode = tslFn( ( stack ) => {
+					const precomputeShaderNode = tslFn( () => {
 
 						const particleIndex = float( instanceIndex );
 
@@ -111,7 +111,7 @@
 
 						const velocity = velocityBufferNode.element( instanceIndex );
 
-						stack.assign( velocity.xy, vec2( velX, velY ) );
+						velocity.xy.assign( vec2( velX, velY ) );
 
 					} );
 

+ 1 - 1
examples/webgpu_lights_custom.html

@@ -37,7 +37,7 @@
 
 				direct( { lightColor, reflectedLight }, stack ) {
 
-					stack.addAssign( reflectedLight.directDiffuse, lightColor );
+					reflectedLight.directDiffuse.addAssign( lightColor );
 
 				}
 

+ 4 - 4
examples/webgpu_materials.html

@@ -235,10 +235,10 @@
 					const topUV = uv().add( vec2( 0, scaleI ) );
 					const bottomUV = uv().add( vec2( 0, scaleINeg ) );
 
-					stack.assign( output, output.add( texture( uvTexture, leftUV ) ) );
-					stack.assign( output, output.add( texture( uvTexture, rightUV ) ) );
-					stack.assign( output, output.add( texture( uvTexture, topUV ) ) );
-					stack.assign( output, output.add( texture( uvTexture, bottomUV ) ) );
+					output.assign( output.add( texture( uvTexture, leftUV ) ) );
+					output.assign( output.add( texture( uvTexture, rightUV ) ) );
+					output.assign( output.add( texture( uvTexture, topUV ) ) );
+					output.assign( output.add( texture( uvTexture, bottomUV ) ) );
 
 					return output.div( loopCount * 4 );