소스 검색

Node: add .construct() and some architectural changes (#24110)

* Rename EnvironmentLightNode to EnvronmentNode

* Node: add .construct()

* cleanup

* cleanup2
sunag 3 년 전
부모
커밋
d35bfbc7e4

+ 3 - 3
examples/jsm/nodes/Nodes.js

@@ -64,7 +64,7 @@ import LightsNode from './lighting/LightsNode.js';
 import LightingNode from './lighting/LightingNode.js';
 import LightingContextNode from './lighting/LightingContextNode.js';
 import HemisphereLightNode from './lighting/HemisphereLightNode.js';
-import EnvironmentLightNode from './lighting/EnvironmentLightNode.js';
+import EnvironmentNode from './lighting/EnvironmentNode.js';
 import AONode from './lighting/AONode.js';
 import AnalyticLightNode from './lighting/AnalyticLightNode.js';
 
@@ -167,7 +167,7 @@ const nodeLib = {
 	LightingNode,
 	LightingContextNode,
 	HemisphereLightNode,
-	EnvironmentLightNode,
+	EnvironmentNode,
 	AONode,
 	AnalyticLightNode,
 
@@ -269,7 +269,7 @@ export {
 	LightingNode,
 	LightingContextNode,
 	HemisphereLightNode,
-	EnvironmentLightNode,
+	EnvironmentNode,
 	AONode,
 	AnalyticLightNode,
 

+ 30 - 6
examples/jsm/nodes/accessors/CubeTextureNode.js

@@ -18,10 +18,37 @@ class CubeTextureNode extends TextureNode {
 
 	}
 
+	getConstructHash( builder ) {
+
+		return `${ this.uuid }-${ builder.context.environmentContext?.uuid || '' }`;
+
+	}
+
+	construct( builder ) {
+
+		const properties = builder.getNodeProperties( this );
+
+		const uvNode = this.uvNode || builder.context.uvNode || new ReflectNode();
+		let levelNode = this.levelNode || builder.context.levelNode;
+
+		if ( levelNode?.isNode === true ) {
+
+			const texture = this.value;
+
+			levelNode = builder.context.levelShaderNode ? builder.context.levelShaderNode.call( { texture, levelNode }, builder ) : levelNode;
+
+		}
+
+		properties.uvNode = uvNode;
+		properties.levelNode = levelNode;
+
+	}
+
 	generate( builder, output ) {
 
+		const { uvNode, levelNode } = builder.getNodeProperties( this );
+
 		const texture = this.value;
-		const uvNode = this.uvNode || builder.context.uvNode || new ReflectNode();
 
 		if ( ! texture || texture.isCubeTexture !== true ) {
 
@@ -48,13 +75,10 @@ class CubeTextureNode extends TextureNode {
 			if ( builder.context.tempRead === false || snippet === undefined ) {
 
 				const uvSnippet = uvNode.build( builder, 'vec3' );
-				const levelNode = this.levelNode || builder.context.levelNode;
-
-				if ( levelNode?.isNode === true ) {
 
-					const levelOutNode = builder.context.levelShaderNode ? builder.context.levelShaderNode.call( { texture, levelNode }, builder ) : levelNode;
+				if ( levelNode ) {
 
-					const levelSnippet = levelOutNode.build( builder, 'float' );
+					const levelSnippet = levelNode.build( builder, 'float' );
 
 					snippet = builder.getCubeTextureLevel( textureProperty, uvSnippet, levelSnippet );
 

+ 1 - 3
examples/jsm/nodes/accessors/Object3DNode.js

@@ -70,12 +70,11 @@ class Object3DNode extends Node {
 
 			const camera = frame.camera;
 
+			uniformNode.value = uniformNode.value || new Vector3();
 			uniformNode.value.setFromMatrixPosition( object.matrixWorld );
 
 			uniformNode.value.applyMatrix4( camera.matrixWorldInverse );
 
-			//uniformNode.value.setFromMatrixPosition( object.modelViewMatrix );
-
 		}
 
 	}
@@ -95,7 +94,6 @@ class Object3DNode extends Node {
 		} else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION ) {
 
 			this._uniformNode.nodeType = 'vec3';
-			this._uniformNode.value = new Vector3();
 
 		}
 

+ 7 - 3
examples/jsm/nodes/accessors/ReflectNode.js

@@ -23,26 +23,30 @@ class ReflectNode extends Node {
 
 	}
 
-	generate( builder ) {
+	construct() {
 
 		const scope = this.scope;
 
+		let outputNode = null;
+
 		if ( scope === ReflectNode.VECTOR ) {
 
 			const reflectView = reflect( negate( positionViewDirection ), transformedNormalView );
 			const reflectVec = transformDirection( reflectView, cameraViewMatrix );
 
-			return reflectVec.build( builder );
+			outputNode = reflectVec;
 
 		} else if ( scope === ReflectNode.CUBE ) {
 
 			const reflectVec = nodeObject( new ReflectNode( ReflectNode.VECTOR ) );
 			const cubeUV = vec3( negate( reflectVec.x ), reflectVec.yz );
 
-			return cubeUV.build( builder );
+			outputNode = cubeUV;
 
 		}
 
+		return outputNode;
+
 	}
 
 	serialize( data ) {

+ 14 - 0
examples/jsm/nodes/core/ContextNode.js

@@ -19,6 +19,20 @@ class ContextNode extends Node {
 
 	}
 
+	construct( builder ) {
+
+		const previousContext = builder.getContext();
+
+		builder.setContext( { ...builder.context, ...this.context } );
+
+		const node = this.node.build( builder );
+
+		builder.setContext( previousContext );
+
+		return node;
+
+	}
+
 	generate( builder, output ) {
 
 		const previousContext = builder.getContext();

+ 127 - 26
examples/jsm/nodes/core/Node.js

@@ -26,6 +26,38 @@ class Node {
 
 	}
 
+	getChildren() {
+
+		const children = [];
+
+		for ( const property in this ) {
+
+			const object = this[ property ];
+
+			if ( Array.isArray( object ) === true ) {
+
+				for ( const child of object ) {
+
+					if ( child?.isNode === true ) {
+
+						children.push( child );
+
+					}
+
+				}
+
+			} else if ( object?.isNode === true ) {
+
+				children.push( object );
+
+			}
+
+		}
+
+		return children;
+
+	}
+
 	getHash( /*builder*/ ) {
 
 		return this.uuid;
@@ -44,6 +76,12 @@ class Node {
 
 	}
 
+	getConstructHash( /*builder*/ ) {
+
+		return this.uuid;
+
+	}
+
 	getReference( builder ) {
 
 		const hash = this.getHash( builder );
@@ -53,41 +91,66 @@ class Node {
 
 	}
 
-	update( /*frame*/ ) {
+	construct( builder ) {
 
-		console.warn( 'Abstract function.' );
+		const nodeProperties = builder.getNodeProperties( this );
 
-	}
+		for ( const childNode of this.getChildren() ) {
 
-	generate( /*builder, output*/ ) {
+			nodeProperties[ '_node' + childNode.id ] = childNode;
 
-		console.warn( 'Abstract function.' );
+		}
+
+		// return a outputNode if exists
+		return null;
 
 	}
 
 	analyze( builder ) {
 
-		const refNode = this.getReference( builder );
+		const nodeData = builder.getDataFromNode( this );
+		nodeData.dependenciesCount = nodeData.dependenciesCount === undefined ? 1 : nodeData.dependenciesCount + 1;
 
-		if ( this !== refNode ) {
+		if ( nodeData.dependenciesCount === 1 ) {
+
+			// node flow children
+
+			const nodeProperties = builder.getNodeProperties( this );
+
+			for ( const childNode of Object.values( nodeProperties ) ) {
+
+				if ( childNode?.isNode === true ) {
 
-			return refNode.analyze( builder );
+					childNode.build( builder );
+
+				}
+
+			}
 
 		}
 
-		const nodeData = builder.getDataFromNode( this );
-		nodeData.dependenciesCount = nodeData.dependenciesCount === undefined ? 1 : nodeData.dependenciesCount + 1;
+	}
 
-		const nodeKeys = getNodesKeys( this );
+	generate( builder ) {
 
-		for ( const property of nodeKeys ) {
+		const { outputNode } = builder.getNodeProperties( this );
 
-			this[ property ].analyze( builder );
+		if ( outputNode?.isNode === true ) {
+
+			const type = this.getNodeType( builder );
+
+			return outputNode.build( builder, type );
 
 		}
 
 	}
 
+	update( /*frame*/ ) {
+
+		console.warn( 'Abstract function.' );
+
+	}
+
 	build( builder, output = null ) {
 
 		const refNode = this.getReference( builder );
@@ -101,36 +164,74 @@ class Node {
 		builder.addNode( this );
 		builder.addStack( this );
 
-		const nodeData = builder.getDataFromNode( this );
-		const isGenerateOnce = this.generate.length === 1;
+		/* expected return:
+			- "construct"	-> Node
+			- "analyze"		-> null
+			- "generat"		-> String
+		*/
+		let result = null;
 
-		let snippet = null;
+		const buildStage = builder.getBuildStage();
 
-		if ( isGenerateOnce ) {
+		if ( buildStage === 'construct' ) {
 
-			const type = this.getNodeType( builder );
+			const properties = builder.getNodeProperties( this );
+			const nodeData = builder.getDataFromNode( this );
 
-			snippet = nodeData.snippet;
+			if ( properties.initied !== true ) {
 
-			if ( snippet === undefined ) {
+				nodeData.initied = true;
 
-				snippet = this.generate( builder ) || '';
+				properties.outputNode =  this.construct( builder );
 
-				nodeData.snippet = snippet;
+				for ( const childNode of Object.values( properties ) ) {
+
+					if ( childNode?.isNode === true ) {
+
+						childNode.build( builder );
+
+					}
+
+				}
 
 			}
 
-			snippet = builder.format( snippet, type, output );
+		} else if ( buildStage === 'analyze' ) {
+
+			this.analyze( builder );
+
+		} else if ( buildStage === 'generate' ) {
+
+			const isGenerateOnce = this.generate.length === 1;
+
+			if ( isGenerateOnce ) {
+
+				const type = this.getNodeType( builder );
+				const nodeData = builder.getDataFromNode( this );
 
-		} else {
+				result = nodeData.snippet;
 
-			snippet = this.generate( builder, output ) || '';
+				if ( result === undefined ) {
+
+					result = this.generate( builder ) || '';
+
+					nodeData.snippet = result;
+
+				}
+
+				result = builder.format( result, type, output );
+
+			} else {
+
+				result = this.generate( builder, output ) || '';
+
+			}
 
 		}
 
 		builder.removeStack( this );
 
-		return snippet;
+		return result;
 
 	}
 

+ 67 - 18
examples/jsm/nodes/core/NodeBuilder.js

@@ -69,7 +69,13 @@ class NodeBuilder {
 		this.flowsData = new WeakMap();
 
 		this.shaderStage = null;
-		this.node = null;
+		this.buildStage = null;
+
+	}
+
+	get node() {
+
+		return this.stack[ this.stack.length - 1 ];
 
 	}
 
@@ -393,6 +399,18 @@ class NodeBuilder {
 
 	}
 
+	getNodeProperties( node, shaderStage = this.shaderStage ) {
+
+		const nodeData = this.getDataFromNode( this, shaderStage );
+		const constructHash = node.getConstructHash( this );
+
+		nodeData.properties = nodeData.properties || {};
+		nodeData.properties[ constructHash ] = nodeData.properties[ constructHash ] || { outputNode: null };
+
+		return nodeData.properties[ constructHash ];
+
+	}
+
 	getUniformFromNode( node, shaderStage, type ) {
 
 		const nodeData = this.getDataFromNode( node, shaderStage );
@@ -490,7 +508,7 @@ class NodeBuilder {
 
 	}
 
-	getFlowData( shaderStage, node ) {
+	getFlowData( node/*, shaderStage*/ ) {
 
 		return this.flowsData.get( node );
 
@@ -498,16 +516,12 @@ class NodeBuilder {
 
 	flowNode( node ) {
 
-		this.node = node;
-
 		const output = node.getNodeType( this );
 
 		const flowData = this.flowChildNode( node, output );
 
 		this.flowsData.set( node, flowData );
 
-		this.node = null;
-
 		return flowData;
 
 	}
@@ -570,9 +584,7 @@ class NodeBuilder {
 
 		const vars = this.vars[ shaderStage ];
 
-		for ( let index = 0; index < vars.length; index ++ ) {
-
-			const variable = vars[ index ];
+		for ( const variable of vars ) {
 
 			snippet += `${variable.type} ${variable.name}; `;
 
@@ -610,15 +622,27 @@ class NodeBuilder {
 
 	}
 
+	setShaderStage( shaderStage ) {
+
+		this.shaderStage = shaderStage;
+
+	}
+
 	getShaderStage() {
 
 		return this.shaderStage;
 
 	}
 
-	setShaderStage( shaderStage ) {
+	setBuildStage( buildStage ) {
 
-		this.shaderStage = shaderStage;
+		this.buildStage = buildStage;
+
+	}
+
+	getBuildStage() {
+
+		return this.buildStage;
 
 	}
 
@@ -630,7 +654,9 @@ class NodeBuilder {
 
 	build() {
 
-		// stage 1: analyze nodes to possible optimization and validation
+		// stage 1: generate shader node
+
+		this.setBuildStage( 'construct' );
 
 		for ( const shaderStage of shaderStages ) {
 
@@ -640,13 +666,33 @@ class NodeBuilder {
 
 			for ( const node of flowNodes ) {
 
-				node.analyze( this );
+				node.build( this );
 
 			}
 
 		}
 
-		// stage 2: pre-build vertex code used in fragment shader
+		// stage 2: analyze nodes to possible optimization and validation
+
+		this.setBuildStage( 'analyze' );
+
+		for ( const shaderStage of shaderStages ) {
+
+			this.setShaderStage( shaderStage );
+
+			const flowNodes = this.flowNodes[ shaderStage ];
+
+			for ( const node of flowNodes ) {
+
+				node.build( this );
+
+			}
+
+		}
+
+		// stage 3: pre-build vertex code used in fragment shader
+
+		this.setBuildStage( 'generate' );
 
 		if ( this.context.vertex && this.context.vertex.isNode ) {
 
@@ -654,7 +700,9 @@ class NodeBuilder {
 
 		}
 
-		// stage 3: generate shader
+		// stage 4: generate shader
+
+		this.setBuildStage( 'generate' );
 
 		for ( const shaderStage of shaderStages ) {
 
@@ -664,15 +712,16 @@ class NodeBuilder {
 
 			for ( const node of flowNodes ) {
 
-				this.flowNode( node, shaderStage );
+				this.flowNode( node );
 
 			}
 
 		}
 
+		this.setBuildStage( null );
 		this.setShaderStage( null );
 
-		// stage 4: build code for a specific output
+		// stage 5: build code for a specific output
 
 		this.buildCode();
 
@@ -702,7 +751,7 @@ class NodeBuilder {
 
 		}
 
-		if ( toTypeLength > 4 ) { // toType is matrix-like
+		if ( toTypeLength > 4 || toTypeLength === 0 ) { // toType is matrix-like or unknown
 
 			// @TODO: ignore for now
 

+ 18 - 12
examples/jsm/nodes/core/TempNode.js

@@ -12,26 +12,32 @@ class TempNode extends Node {
 
 	build( builder, output ) {
 
-		const type = builder.getVectorType( this.getNodeType( builder, output ) );
-		const nodeData = builder.getDataFromNode( this );
+		const buildStage = builder.getBuildStage();
 
-		if ( builder.context.tempRead !== false && nodeData.propertyName !== undefined ) {
+		if ( buildStage === 'generate' ) {
 
-			return builder.format( nodeData.propertyName, type, output );
+			const type = builder.getVectorType( this.getNodeType( builder, output ) );
+			const nodeData = builder.getDataFromNode( this );
 
-		} else if ( builder.context.tempWrite !== false && type !== 'void ' && output !== 'void' && nodeData.dependenciesCount > 1 ) {
+			if ( builder.context.tempRead !== false && nodeData.propertyName !== undefined ) {
 
-			const snippet = super.build( builder, type );
+				return builder.format( nodeData.propertyName, type, output );
 
-			const nodeVar = builder.getVarFromNode( this, type );
-			const propertyName = builder.getPropertyName( nodeVar );
+			} else if ( builder.context.tempWrite !== false && type !== 'void ' && output !== 'void' && nodeData.dependenciesCount > 1 ) {
 
-			builder.addFlowCode( `${propertyName} = ${snippet}` );
+				const snippet = super.build( builder, type );
 
-			nodeData.snippet = snippet;
-			nodeData.propertyName = propertyName;
+				const nodeVar = builder.getVarFromNode( this, type );
+				const propertyName = builder.getPropertyName( nodeVar );
 
-			return builder.format( nodeData.propertyName, type, output );
+				builder.addFlowCode( `${propertyName} = ${snippet}` );
+
+				nodeData.snippet = snippet;
+				nodeData.propertyName = propertyName;
+
+				return builder.format( nodeData.propertyName, type, output );
+
+			}
 
 		}
 

+ 8 - 6
examples/jsm/nodes/display/ColorSpaceNode.js

@@ -65,27 +65,29 @@ class ColorSpaceNode extends TempNode {
 
 	}
 
-	generate( builder ) {
-
-		const type = this.getNodeType( builder );
+	construct() {
 
 		const method = this.method;
 		const node = this.node;
 
+		let outputNode = null;
+
 		if ( method !== ColorSpaceNode.LINEAR_TO_LINEAR ) {
 
 			const encodingFunctionNode = EncodingLib[ method ];
 
-			return encodingFunctionNode.call( {
+			outputNode = encodingFunctionNode.call( {
 				value: node
-			} ).build( builder, type );
+			} );
 
 		} else {
 
-			return node.build( builder, type );
+			outputNode = node;
 
 		}
 
+		return outputNode;
+
 	}
 
 }

+ 7 - 9
examples/jsm/nodes/display/NormalMapNode.js

@@ -44,9 +44,7 @@ class NormalMapNode extends TempNode {
 
 	}
 
-	generate( builder ) {
-
-		const type = this.getNodeType( builder );
+	construct() {
 
 		const { normalMapType, scaleNode } = this;
 
@@ -60,27 +58,27 @@ class NormalMapNode extends TempNode {
 
 		}
 
+		let outputNode = null;
+
 		if ( normalMapType === ObjectSpaceNormalMap ) {
 
 			const vertexNormalNode = mul( new ModelNode( ModelNode.NORMAL_MATRIX ), normalMap );
 
-			const normal = normalize( vertexNormalNode );
-
-			return normal.build( builder, type );
+			outputNode = normalize( vertexNormalNode );
 
 		} else if ( normalMapType === TangentSpaceNormalMap ) {
 
-			const perturbNormal2ArbCall = perturbNormal2ArbNode.call( {
+			outputNode = perturbNormal2ArbNode.call( {
 				eye_pos: positionView,
 				surf_norm: normalView,
 				mapN: normalMap,
 				uv: uv()
 			} );
 
-			return perturbNormal2ArbCall.build( builder, type );
-
 		}
 
+		return outputNode;
+
 	}
 
 }

+ 7 - 5
examples/jsm/nodes/display/ToneMappingNode.js

@@ -23,25 +23,27 @@ class ToneMappingNode extends TempNode {
 
 	}
 
-	generate( builder ) {
-
-		const type = this.getNodeType( builder );
+	construct( builder ) {
 
 		const colorNode = this.color || builder.context.color;
 
 		const toneMapping = this.toneMapping;
 		const toneMappingParams = { exposure: this.exposureNode, color: colorNode };
 
+		let outputNode = null;
+
 		if ( toneMapping === LinearToneMapping ) {
 
-			return LinearToneMappingNode.call( toneMappingParams ).build( builder, type );
+			outputNode = LinearToneMappingNode.call( toneMappingParams );
 
 		} else {
 
-			return this.colorNode.build( builder, type );
+			outputNode = this.colorNode;
 
 		}
 
+		return outputNode;
+
 	}
 
 }

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

@@ -11,7 +11,7 @@ class AONode extends LightingNode {
 
 	}
 
-	generate( builder ) {
+	construct( builder ) {
 
 		const aoIntensity = 1;
 		const aoNode = add( mul( sub( float( this.aoNode ), 1.0 ), aoIntensity ), 1.0 );

+ 5 - 10
examples/jsm/nodes/lighting/EnvironmentLightNode.js → examples/jsm/nodes/lighting/EnvironmentNode.js

@@ -1,7 +1,6 @@
 import LightingNode from './LightingNode.js';
 import ContextNode from '../core/ContextNode.js';
 import MaxMipLevelNode from '../utils/MaxMipLevelNode.js';
-//import ReflectNode from '../accessors/ReflectNode.js';
 import { ShaderNode, float, add, mul, div, log2, clamp, roughness, reflect, mix, vec3, positionViewDirection, negate, normalize, transformedNormalView, transformedNormalWorld, transformDirection, cameraViewMatrix } from '../shadernode/ShaderNodeElements.js';
 
 // taken from here: http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html
@@ -15,13 +14,7 @@ const getSpecularMIPLevel = new ShaderNode( ( { texture, levelNode } ) => {
 	return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );
 
 } );
-/*
-const getMaxMIPLevel = new ShaderNode( ( { texture } ) => {
 
-	return new MaxMipLevelNode( texture );
-
-} );
-*/
 class EnvironmentLightNode extends LightingNode {
 
 	constructor( envNode = null ) {
@@ -32,7 +25,7 @@ class EnvironmentLightNode extends LightingNode {
 
 	}
 
-	generate( builder ) {
+	construct( builder ) {
 
 		const envNode = this.envNode;
 
@@ -43,8 +36,6 @@ class EnvironmentLightNode extends LightingNode {
 		reflectVec = transformDirection( reflectVec, cameraViewMatrix );
 		reflectVec = vec3( negate( reflectVec.x ), reflectVec.yz );
 
-		//reflectVec = normalize( mix( new ReflectNode(), flipNormalWorld, mul( roughness, roughness ) ) );
-
 		const radianceContext = new ContextNode( envNode, {
 			tempRead: false,
 			uvNode: reflectVec,
@@ -59,6 +50,10 @@ class EnvironmentLightNode extends LightingNode {
 			levelShaderNode: getSpecularMIPLevel
 		} );
 
+		// it's used to cache the construct only if necessary: See `CubeTextureNode.getConstructReference()`
+		radianceContext.context.environmentContext = radianceContext;
+		irradianceContext.context.environmentContext = irradianceContext;
+
 		builder.context.radiance.add( radianceContext );
 
 		builder.context.iblIrradiance.add( mul( Math.PI, irradianceContext ) );

+ 40 - 27
examples/jsm/nodes/lighting/LightingContextNode.js

@@ -17,42 +17,55 @@ class LightingContextNode extends ContextNode {
 
 	}
 
-	generate( builder ) {
-
-		const { context, lightingModelNode } = this;
-
-		if ( context.reflectedLight === undefined ) {
-
-			const directDiffuse = temp( vec3() ),
-				directSpecular = temp( vec3() ),
-				indirectDiffuse = temp( vec3() ),
-				indirectSpecular = temp( vec3() );
+	construct( builder ) {
+
+		const { lightingModelNode } = this;
+
+		const context = this.context = {}; // reset context
+		const properties = builder.getNodeProperties( this );
+
+		const directDiffuse = temp( vec3() ),
+			directSpecular = temp( vec3() ),
+			indirectDiffuse = temp( vec3() ),
+			indirectSpecular = temp( vec3() ),
+			total = add( directDiffuse, directSpecular, indirectDiffuse, indirectSpecular );
+
+		const reflectedLight = {
+			directDiffuse,
+			directSpecular,
+			indirectDiffuse,
+			indirectSpecular,
+			total
+		};
+
+		const lighting = {
+			radiance : temp( vec3() ),
+			irradiance : temp( vec3() ),
+			iblIrradiance : temp( vec3() ),
+			ambientOcclusion : temp( float( 1 ) )
+		};
+
+		Object.assign( properties, reflectedLight, lighting );
+		Object.assign( context, lighting );
+
+		context.reflectedLight = reflectedLight;
+		context.lightingModelNode = lightingModelNode || context.lightingModelNode;
 
-			context.reflectedLight = {
-				directDiffuse,
-				directSpecular,
-				indirectDiffuse,
-				indirectSpecular,
-				total: add( directDiffuse, directSpecular, indirectDiffuse, indirectSpecular )
-			};
+		if ( lightingModelNode?.indirectDiffuse ) lightingModelNode.indirectDiffuse.call( context );
+		if ( lightingModelNode?.indirectSpecular ) lightingModelNode.indirectSpecular.call( context );
+		if ( lightingModelNode?.ambientOcclusion ) lightingModelNode.ambientOcclusion.call( context );
 
-			context.radiance = temp( vec3() );
-			context.irradiance = temp( vec3() );
-			context.iblIrradiance = temp( vec3() );
-			context.ambientOcclusion = temp( float( 1 ) );
+		return super.construct( builder );
 
-		}
+	}
 
-		context.lightingModelNode = lightingModelNode || context.lightingModelNode;
+	generate( builder ) {
 
+		const { context } = this;
 		const type = this.getNodeType( builder );
 
 		super.generate( builder, type );
 
-		if ( lightingModelNode?.indirectDiffuse ) lightingModelNode.indirectDiffuse.call( context );
-		if ( lightingModelNode?.indirectSpecular ) lightingModelNode.indirectSpecular.call( context );
-		if ( lightingModelNode?.ambientOcclusion ) lightingModelNode.ambientOcclusion.call( context );
-
 		return context.reflectedLight.total.build( builder, type );
 
 	}

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

@@ -27,7 +27,7 @@ class LightsNode extends Node {
 
 	}
 
-	generate( builder ) {
+	construct( builder ) {
 
 		const lightNodes = this.lightNodes;
 

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

@@ -28,7 +28,7 @@ class PunctualLightNode extends AnalyticLightNode {
 
 	}
 
-	generate( builder ) {
+	construct( builder ) {
 
 		const { colorNode, cutoffDistanceNode, decayExponentNode } = this;
 

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

@@ -5,7 +5,7 @@ import {
 	materialRoughness, materialMetalness, materialEmissive
 } from '../shadernode/ShaderNodeElements.js';
 import LightsNode from '../lighting/LightsNode.js';
-import EnvironmentLightNode from '../lighting/EnvironmentLightNode.js';
+import EnvironmentNode from '../lighting/EnvironmentNode.js';
 import AONode from '../lighting/AONode.js';
 import getRoughness from '../functions/material/getRoughness.js';
 import PhysicalLightingModel from '../functions/PhysicalLightingModel.js';
@@ -63,7 +63,7 @@ export default class MeshStandardNodeMaterial extends NodeMaterial {
 
 		if ( envNode ) {
 
-			materialLightsNode.push( new EnvironmentLightNode( envNode ) );
+			materialLightsNode.push( new EnvironmentNode( envNode ) );
 
 		}
 

+ 1 - 1
examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js

@@ -403,7 +403,7 @@ ${this.shader[ getShaderStageProperty( shaderStage ) ]}
 
 			if ( node.name === name ) {
 
-				return this.getFlowData( shaderStage, node );
+				return this.getFlowData( node/*, shaderStage*/ );
 
 			}
 

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

@@ -444,9 +444,7 @@ class WebGPUNodeBuilder extends NodeBuilder {
 		const snippets = [];
 		const vars = this.vars[ shaderStage ];
 
-		for ( let index = 0; index < vars.length; index ++ ) {
-
-			const variable = vars[ index ];
+		for (const variable of vars) {
 
 			const name = variable.name;
 			const type = this.getType( variable.type );
@@ -595,7 +593,7 @@ class WebGPUNodeBuilder extends NodeBuilder {
 
 			for ( const node of flowNodes ) {
 
-				const flowSlotData = this.getFlowData( shaderStage, node );
+				const flowSlotData = this.getFlowData( node/*, shaderStage*/ );
 				const slotName = node.name;
 
 				if ( slotName ) {