2
0
Эх сурвалжийг харах

TSL: if, elseif, else syntax (#25653)

* WebGLNodeBuilder: Remove redundant code.

* Nodes: Added if/else
sunag 2 жил өмнө
parent
commit
fb2db55c9b

+ 1 - 1
examples/jsm/nodes/accessors/CubeTextureNode.js

@@ -77,7 +77,7 @@ class CubeTextureNode extends TextureNode {
 
 				}
 
-				builder.addFlowCode( `${propertyName} = ${snippet}` );
+				builder.addLineFlowCode( `${propertyName} = ${snippet}` );
 
 				nodeData.snippet = snippet;
 				nodeData.propertyName = propertyName;

+ 1 - 1
examples/jsm/nodes/accessors/TextureNode.js

@@ -118,7 +118,7 @@ class TextureNode extends UniformNode {
 
 				}
 
-				builder.addFlowCode( `${propertyName} = ${snippet}` );
+				builder.addLineFlowCode( `${propertyName} = ${snippet}` );
 
 				nodeData.snippet = snippet;
 				nodeData.propertyName = propertyName;

+ 1 - 1
examples/jsm/nodes/core/BypassNode.js

@@ -26,7 +26,7 @@ class BypassNode extends Node {
 
 		if ( snippet !== '' ) {
 
-			builder.addFlowCode( snippet );
+			builder.addLineFlowCode( snippet );
 
 		}
 

+ 1 - 1
examples/jsm/nodes/core/ExpressionNode.js

@@ -18,7 +18,7 @@ class ExpressionNode extends Node {
 
 		if ( type === 'void' ) {
 
-			builder.addFlowCode( snippet );
+			builder.addLineFlowCode( snippet );
 
 		} else {
 

+ 2 - 2
examples/jsm/nodes/core/Node.js

@@ -168,7 +168,7 @@ class Node {
 		}
 
 		builder.addNode( this );
-		builder.addStack( this );
+		builder.addChain( this );
 
 		/* Build stages expected results:
 			- "construct"	-> Node
@@ -233,7 +233,7 @@ class Node {
 
 		}
 
-		builder.removeStack( this );
+		builder.removeChain( this );
 
 		return result;
 

+ 77 - 33
examples/jsm/nodes/core/NodeBuilder.js

@@ -57,7 +57,9 @@ class NodeBuilder {
 		this.varyings = [];
 		this.vars = { vertex: [], fragment: [], compute: [] };
 		this.flow = { code: '' };
-		this.stack = [];
+		this.chaining = [];
+		this.stack = stack();
+		this.tab = '\t';
 
 		this.context = {
 			keywords: new NodeKeywords(),
@@ -75,59 +77,59 @@ class NodeBuilder {
 
 	}
 
-	get node() {
+	setHashNode( node, hash ) {
 
-		return this.stack[ this.stack.length - 1 ];
+		this.hashNodes[ hash ] = node;
 
 	}
 
-	addStack( node ) {
-
-		/*
-		if ( this.stack.indexOf( node ) !== - 1 ) {
-
-			console.warn( 'Recursive node: ', node );
+	addNode( node ) {
 
-		}
-		*/
+		if ( this.nodes.indexOf( node ) === - 1 ) {
 
-		this.stack.push( node );
+			const updateType = node.getUpdateType( this );
 
-	}
+			if ( updateType !== NodeUpdateType.NONE ) {
 
-	removeStack( node ) {
+				this.updateNodes.push( node );
 
-		const lastStack = this.stack.pop();
+			}
 
-		if ( lastStack !== node ) {
+			this.nodes.push( node );
 
-			throw new Error( 'NodeBuilder: Invalid node stack!' );
+			this.setHashNode( node, node.getHash( this ) );
 
 		}
 
 	}
 
-	setHashNode( node, hash ) {
+	get currentNode() {
 
-		this.hashNodes[ hash ] = node;
+		return this.chaining[ this.chaining.length - 1 ];
 
 	}
 
-	addNode( node ) {
+	addChain( node ) {
 
-		if ( this.nodes.indexOf( node ) === - 1 ) {
+		/*
+		if ( this.chaining.indexOf( node ) !== - 1 ) {
 
-			const updateType = node.getUpdateType( this );
+			console.warn( 'Recursive node: ', node );
 
-			if ( updateType !== NodeUpdateType.NONE ) {
+		}
+		*/
 
-				this.updateNodes.push( node );
+		this.chaining.push( node );
 
-			}
+	}
 
-			this.nodes.push( node );
+	removeChain( node ) {
 
-			this.setHashNode( node, node.getHash( this ) );
+		const lastChain = this.chaining.pop();
+
+		if ( lastChain !== node ) {
+
+			throw new Error( 'NodeBuilder: Invalid node chaining!' );
 
 		}
 
@@ -447,9 +449,21 @@ class NodeBuilder {
 
 	}
 
-	createStack() {
+	addStack() {
+
+		this.stack = stack( this.stack );
+
+		return this.stack;
+
+	}
+
+	removeStack() {
+
+		const currentStack = this.stack;
 
-		return stack();
+		this.stack = currentStack.parent;
+
+		return currentStack;
 
 	}
 
@@ -570,16 +584,46 @@ class NodeBuilder {
 
 	}
 
-	addFlowCode( code, breakline = true ) {
+	addLineFlowCode( code ) {
+
+		if ( code === '' ) return this;
 
-		if ( breakline && ! /;\s*$/.test( code ) ) {
+		code = this.tab + code;
 
-			code += ';\n\t';
+		if ( ! /;\s*$/.test( code ) ) {
+
+			code = code + ';\n';
 
 		}
 
 		this.flow.code += code;
 
+		return this;
+
+	}
+
+	addFlowCode( code ) {
+
+		this.flow.code += code;
+
+		return this;
+
+	}
+
+	addFlowTab() {
+
+		this.tab += '\t';
+
+		return this;
+
+	}
+
+	removeFlowTab() {
+
+		this.tab = this.tab.slice( 0, - 1 );
+
+		return this;
+
 	}
 
 	getFlowData( node/*, shaderStage*/ ) {
@@ -628,7 +672,7 @@ class NodeBuilder {
 
 		if ( propertyName !== null ) {
 
-			flowData.code += `${propertyName} = ${flowData.result};\n\t`;
+			flowData.code += `${propertyName} = ${flowData.result};\n` + this.tab;
 
 		}
 

+ 36 - 2
examples/jsm/nodes/core/StackNode.js

@@ -2,17 +2,22 @@ import Node, { addNodeClass } from './Node.js';
 import { assign } from '../math/OperatorNode.js';
 import { bypass } from '../core/BypassNode.js';
 import { expression } from '../core/ExpressionNode.js';
-import { nodeProxy } from '../shadernode/ShaderNode.js';
+import { cond } from '../math/CondNode.js';
+import { nodeProxy, shader } from '../shadernode/ShaderNode.js';
 
 class StackNode extends Node {
 
-	constructor() {
+	constructor( parent = null ) {
 
 		super();
 
 		this.nodes = [];
 		this.outputNode = null;
 
+		this.parent = parent;
+
+		this._currentCond = null;
+
 		this.isStackNode = true;
 
 	}
@@ -31,6 +36,35 @@ class StackNode extends Node {
 
 	}
 
+	if( boolNode, method ) {
+
+		const methodNode = shader( method );
+		this._currentCond = cond( boolNode, methodNode );
+
+		return this.add( this._currentCond );
+
+	}
+
+	elseif( boolNode, method ) {
+
+		const methodNode = shader( method );
+		const ifNode = cond( boolNode, methodNode );
+
+		this._currentCond.elseNode = ifNode;
+		this._currentCond = ifNode;
+
+		return this;
+
+	}
+
+	else( method ) {
+
+		this._currentCond.elseNode = shader( method );
+
+		return this;
+
+	}
+
 	assign( targetNode, sourceValue ) {
 
 		return this.add( assign( targetNode, sourceValue ) );

+ 1 - 1
examples/jsm/nodes/core/TempNode.js

@@ -36,7 +36,7 @@ class TempNode extends Node {
 				const nodeVar = builder.getVarFromNode( this, type );
 				const propertyName = builder.getPropertyName( nodeVar );
 
-				builder.addFlowCode( `${propertyName} = ${snippet}` );
+				builder.addLineFlowCode( `${propertyName} = ${snippet}` );
 
 				nodeData.snippet = snippet;
 				nodeData.propertyName = propertyName;

+ 1 - 1
examples/jsm/nodes/core/VarNode.js

@@ -70,7 +70,7 @@ class VarNode extends Node {
 
 		const propertyName = builder.getPropertyName( nodeVar );
 
-		builder.addFlowCode( `${propertyName} = ${snippet}` );
+		builder.addLineFlowCode( `${propertyName} = ${snippet}` );
 
 		return propertyName;
 

+ 1 - 1
examples/jsm/nodes/gpgpu/ComputeNode.js

@@ -53,7 +53,7 @@ class ComputeNode extends Node {
 
 			if ( snippet !== '' ) {
 
-				builder.addFlowCode( snippet );
+				builder.addLineFlowCode( snippet );
 
 			}
 

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

@@ -27,7 +27,7 @@ class MeshNormalNodeMaterial extends NodeMaterial {
 
 	}
 
-	constructDiffuseColor( builder, stack ) {
+	constructDiffuseColor( { stack } ) {
 
 		const opacityNode = this.opacityNode ? float( this.opacityNode ) : materialOpacity;
 

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

@@ -42,7 +42,7 @@ class MeshPhongNodeMaterial extends NodeMaterial {
 
 	}
 
-	constructVariants( builder, stack ) {
+	constructVariants( { stack } ) {
 
 		// SHININESS
 

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

@@ -48,7 +48,7 @@ class MeshStandardNodeMaterial extends NodeMaterial {
 
 	}
 
-	constructVariants( builder, stack ) {
+	constructVariants( { stack } ) {
 
 		// METALNESS
 

+ 16 - 18
examples/jsm/nodes/materials/NodeMaterial.js

@@ -52,30 +52,28 @@ class NodeMaterial extends ShaderMaterial {
 
 	construct( builder ) {
 
-		// < STACKS >
+		// < VERTEX STAGE >
 
-		const vertexStack = builder.createStack();
-		const fragmentStack = builder.createStack();
+		builder.addStack();
 
-		// < VERTEX STAGE >
+		builder.stack.outputNode = this.constructPosition( builder );
 
-		vertexStack.outputNode = this.constructPosition( builder, vertexStack );
+		builder.addFlow( 'vertex', builder.removeStack() );
 
 		// < FRAGMENT STAGE >
 
-		if ( this.normals === true ) this.constructNormal( builder, fragmentStack );
+		builder.addStack();
 
-		this.constructDiffuseColor( builder, fragmentStack );
-		this.constructVariants( builder, fragmentStack );
+		if ( this.normals === true ) this.constructNormal( builder );
 
-		const outgoingLightNode = this.constructLighting( builder, fragmentStack );
+		this.constructDiffuseColor( builder );
+		this.constructVariants( builder );
 
-		fragmentStack.outputNode = this.constructOutput( builder, fragmentStack, outgoingLightNode, diffuseColor.a );
+		const outgoingLightNode = this.constructLighting( builder );
 
-		// < FLOW >
+		builder.stack.outputNode = this.constructOutput( builder, outgoingLightNode, diffuseColor.a );
 
-		builder.addFlow( 'vertex', vertexStack );
-		builder.addFlow( 'fragment', fragmentStack );
+		builder.addFlow( 'fragment', builder.removeStack() );
 
 	}
 
@@ -109,13 +107,13 @@ class NodeMaterial extends ShaderMaterial {
 
 	}
 
-	constructDiffuseColor( builder, stack ) {
+	constructDiffuseColor( { stack, geometry } ) {
 
 		let colorNode = this.colorNode ? vec4( this.colorNode ) : materialColor;
 
 		// VERTEX COLORS
 
-		if ( this.vertexColors === true && builder.geometry.hasAttribute( 'color' ) ) {
+		if ( this.vertexColors === true && geometry.hasAttribute( 'color' ) ) {
 
 			colorNode = vec4( colorNode.xyz.mul( attribute( 'color' ) ), colorNode.a );
 
@@ -148,7 +146,7 @@ class NodeMaterial extends ShaderMaterial {
 
 	}
 
-	constructNormal( builder, stack ) {
+	constructNormal( { stack } ) {
 
 		// NORMAL VIEW
 
@@ -226,7 +224,7 @@ class NodeMaterial extends ShaderMaterial {
 
 	}
 
-	constructOutput( builder, stack, outgoingLight, opacity ) {
+	constructOutput( builder, outgoingLight, opacity ) {
 
 		const renderer = builder.renderer;
 
@@ -417,6 +415,6 @@ export function createNodeMaterialFromType( type ) {
 
 	}
 
-};
+}
 
 addNodeMaterial( NodeMaterial );

+ 13 - 6
examples/jsm/nodes/math/CondNode.js

@@ -41,26 +41,33 @@ class CondNode extends Node {
 		const type = this.getNodeType( builder );
 		const context = { tempWrite: false };
 
-		const needsProperty = this.ifNode.getNodeType( builder ) !== 'void' || ( this.elseNode && this.elseNode.getNodeType( builder ) !== 'void' );
+		const { ifNode, elseNode } = this;
+
+		const needsProperty = ifNode.getNodeType( builder ) !== 'void' || ( elseNode && elseNode.getNodeType( builder ) !== 'void' );
 		const nodeProperty = needsProperty ? property( type ).build( builder ) : '';
 
 		const nodeSnippet = contextNode( this.condNode/*, context*/ ).build( builder, 'bool' );
 
-		builder.addFlowCode( `if ( ${nodeSnippet} ) {\n\n\t\t`, false );
+		builder.addFlowCode( `\n${ builder.tab }if ( ${ nodeSnippet } ) {\n\n` ).addFlowTab();
 
 		let ifSnippet = contextNode( this.ifNode, context ).build( builder, type );
 
 		ifSnippet = needsProperty ? nodeProperty + ' = ' + ifSnippet + ';' : ifSnippet;
 
-		builder.addFlowCode( ifSnippet + '\n\n\t}', false );
+		builder.removeFlowTab().addFlowCode( builder.tab + '\t' + ifSnippet + '\n\n' + builder.tab + '}' );
 
-		let elseSnippet = this.elseNode ? contextNode( this.elseNode, context ).build( builder, type ) : null;
+		if ( elseNode !== null ) {
 
-		if ( elseSnippet ) {
+			builder.addFlowCode( ' else {\n\n' ).addFlowTab();
 
+			let elseSnippet = contextNode( elseNode, context ).build( builder, type );
 			elseSnippet = nodeProperty ? nodeProperty + ' = ' + elseSnippet + ';' : elseSnippet;
 
-			builder.addFlowCode( 'else {\n\n\t\t' + elseSnippet + '\n\n\t}', false );
+			builder.removeFlowTab().addFlowCode( builder.tab + '\t' + elseSnippet + '\n\n' + builder.tab + '}\n\n' );
+
+		} else {
+
+			builder.addFlowCode( '\n\n' );
 
 		}
 

+ 1 - 1
examples/jsm/nodes/math/OperatorNode.js

@@ -172,7 +172,7 @@ class OperatorNode extends TempNode {
 
 			if ( op === '=' ) {
 
-				builder.addFlowCode( `${a} ${this.op} ${b}` );
+				builder.addLineFlowCode( `${a} ${this.op} ${b}` );
 
 				return a;
 

+ 7 - 3
examples/jsm/nodes/shadernode/ShaderNode.js

@@ -205,9 +205,11 @@ class ShaderNodeInternal extends Node {
 
 	construct( builder ) {
 
-		const stackNode = builder.createStack();
-		stackNode.outputNode = this.call( {}, stackNode, builder );
-		return stackNode;
+		builder.addStack();
+
+		builder.stack.outputNode = nodeObject( this._jsFunc( builder.stack, builder ) );
+
+		return builder.removeStack();
 
 	}
 
@@ -311,6 +313,8 @@ export const nodeArray = ( val ) => new ShaderNodeArray( val );
 export const nodeProxy = ( ...val ) => new ShaderNodeProxy( ...val );
 export const nodeImmutable = ( ...val ) => new ShaderNodeImmutable( ...val );
 
+export const shader = ( ...val ) => new ShaderNode( ...val );
+
 addNodeClass( ShaderNode );
 
 // types

+ 0 - 12
examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js

@@ -64,18 +64,6 @@ class WebGLNodeBuilder extends NodeBuilder {
 
 	}
 
-	addFlowCode( code ) {
-
-		if ( ! /;\s*$/.test( code ) ) {
-
-			code += ';';
-
-		}
-
-		super.addFlowCode( code + '\n\t' );
-
-	}
-
 	_parseShaderLib() {
 
 		const material = this.material;

+ 4 - 5
examples/jsm/renderers/webgpu/nodes/WebGPUNodeBuilder.js

@@ -600,9 +600,8 @@ class WebGPUNodeBuilder extends NodeBuilder {
 
 		for ( const shaderStage in shadersData ) {
 
-			let flow = '// code\n';
-			flow += `\t${ this.flowCode[ shaderStage ] }`;
-			flow += '\n\t';
+			let flow = '// code\n\n';
+			flow += this.flowCode[ shaderStage ];
 
 			const flowNodes = this.flowNodes[ shaderStage ];
 			const mainNode = flowNodes[ flowNodes.length - 1 ];
@@ -616,7 +615,7 @@ class WebGPUNodeBuilder extends NodeBuilder {
 
 					if ( flow.length > 0 ) flow += '\n';
 
-					flow += `\t// FLOW -> ${ slotName }\n\t`;
+					flow += `\t// flow -> ${ slotName }\n\t`;
 
 				}
 
@@ -624,7 +623,7 @@ class WebGPUNodeBuilder extends NodeBuilder {
 
 				if ( node === mainNode && shaderStage !== 'compute' ) {
 
-					flow += '// FLOW RESULT\n\t';
+					flow += '// result\n\t';
 
 					if ( shaderStage === 'vertex' ) {
 

+ 1 - 1
examples/webgpu_audio_processing.html

@@ -136,7 +136,7 @@
 
 				// compute (shader-node)
 
-				const computeShaderNode = new ShaderNode( ( inputs, stack ) => {
+				const computeShaderNode = new ShaderNode( ( stack ) => {
 
 					const index = float( instanceIndex );
 

+ 2 - 2
examples/webgpu_compute.html

@@ -74,7 +74,7 @@
 
 				// create function
 
-				const computeShaderNode = new ShaderNode( ( inputs, stack ) => {
+				const computeShaderNode = new ShaderNode( ( stack ) => {
 
 					const particle = particleBufferNode.element( instanceIndex );
 					const velocity = velocityBufferNode.element( instanceIndex );
@@ -101,7 +101,7 @@
 				computeNode = computeShaderNode.compute( particleNum );
 				computeNode.onInit = ( { renderer } ) => {
 
-					const precomputeShaderNode = new ShaderNode( ( inputs, stack ) => {
+					const precomputeShaderNode = new ShaderNode( ( stack ) => {
 
 						const particleIndex = float( instanceIndex );