diff --git a/examples/jsm/renderers/nodes/ShaderNode.js b/examples/jsm/renderers/nodes/ShaderNode.js index d03a32b1b64344939d6e9161e88f7c1a1eaf4603..7217dcc0b5f9799507c4d88f49a548c599f3218a 100644 --- a/examples/jsm/renderers/nodes/ShaderNode.js +++ b/examples/jsm/renderers/nodes/ShaderNode.js @@ -302,16 +302,16 @@ export const and = ShaderNodeProxy( OperatorNode, '&&' ); export const element = ShaderNodeProxy( ArrayElementNode ); -export const normalGeometry = new NormalNode( NormalNode.GEOMETRY ); -export const normalLocal = new NormalNode( NormalNode.LOCAL ); -export const normalWorld = new NormalNode( NormalNode.WORLD ); -export const normalView = new NormalNode( NormalNode.VIEW ); -export const transformedNormalView = new VarNode( new NormalNode( NormalNode.VIEW ), 'TransformedNormalView', 'vec3' ); +export const normalGeometry = ShaderNodeObject( new NormalNode( NormalNode.GEOMETRY ) ); +export const normalLocal = ShaderNodeObject( new NormalNode( NormalNode.LOCAL ) ); +export const normalWorld = ShaderNodeObject( new NormalNode( NormalNode.WORLD ) ); +export const normalView = ShaderNodeObject( new NormalNode( NormalNode.VIEW ) ); +export const transformedNormalView = ShaderNodeObject( new VarNode( new NormalNode( NormalNode.VIEW ), 'TransformedNormalView', 'vec3' ) ); -export const positionLocal = new PositionNode( PositionNode.LOCAL ); -export const positionWorld = new PositionNode( PositionNode.WORLD ); -export const positionView = new PositionNode( PositionNode.VIEW ); -export const positionViewDirection = new PositionNode( PositionNode.VIEW_DIRECTION ); +export const positionLocal = ShaderNodeObject( new PositionNode( PositionNode.LOCAL ) ); +export const positionWorld = ShaderNodeObject( new PositionNode( PositionNode.WORLD ) ); +export const positionView = ShaderNodeObject( new PositionNode( PositionNode.VIEW ) ); +export const positionViewDirection = ShaderNodeObject( new PositionNode( PositionNode.VIEW_DIRECTION ) ); export const PI = float( 3.141592653589793 ); export const PI2 = float( 6.283185307179586 ); @@ -320,11 +320,11 @@ export const RECIPROCAL_PI = float( 0.3183098861837907 ); export const RECIPROCAL_PI2 = float( 0.15915494309189535 ); export const EPSILON = float( 1e-6 ); -export const diffuseColor = new PropertyNode( 'DiffuseColor', 'vec4' ); -export const roughness = new PropertyNode( 'Roughness', 'float' ); -export const metalness = new PropertyNode( 'Metalness', 'float' ); -export const alphaTest = new PropertyNode( 'AlphaTest', 'float' ); -export const specularColor = new PropertyNode( 'SpecularColor', 'color' ); +export const diffuseColor = ShaderNodeObject( new PropertyNode( 'DiffuseColor', 'vec4' ) ); +export const roughness = ShaderNodeObject( new PropertyNode( 'Roughness', 'float' ) ); +export const metalness = ShaderNodeObject( new PropertyNode( 'Metalness', 'float' ) ); +export const alphaTest = ShaderNodeObject( new PropertyNode( 'AlphaTest', 'float' ) ); +export const specularColor = ShaderNodeObject( new PropertyNode( 'SpecularColor', 'color' ) ); export const abs = ShaderNodeProxy( MathNode, 'abs' ); export const acos = ShaderNodeProxy( MathNode, 'acos' ); diff --git a/examples/jsm/renderers/nodes/core/Node.js b/examples/jsm/renderers/nodes/core/Node.js index 9b4b78ec3eab91cf5bb22f41ca6115d348abf2ef..2606d721f1bea8d62bab0d6a90bc47cf27891fb0 100644 --- a/examples/jsm/renderers/nodes/core/Node.js +++ b/examples/jsm/renderers/nodes/core/Node.js @@ -50,6 +50,30 @@ class Node { } + analyze( builder ) { + + const hash = this.getHash( builder ); + const sharedNode = builder.getNodeFromHash( hash ); + + if ( sharedNode !== undefined && this !== sharedNode ) { + + return sharedNode.analyze( builder ); + + } + + const nodeData = builder.getDataFromNode( this ); + nodeData.dependenciesCount = nodeData.dependenciesCount === undefined ? 1 : nodeData.dependenciesCount + 1; + + const nodeKeys = getNodesKeys( this ); + + for ( const property of nodeKeys ) { + + this[ property ].analyze( builder ); + + } + + } + build( builder, output = null ) { const hash = this.getHash( builder ); @@ -64,6 +88,7 @@ class Node { builder.addNode( this ); builder.addStack( this ); + const nodeData = builder.getDataFromNode( this ); const isGenerateOnce = this.generate.length === 1; let snippet = null; @@ -71,7 +96,6 @@ class Node { if ( isGenerateOnce ) { const type = this.getNodeType( builder ); - const nodeData = builder.getDataFromNode( this ); snippet = nodeData.snippet; diff --git a/examples/jsm/renderers/nodes/core/NodeBuilder.js b/examples/jsm/renderers/nodes/core/NodeBuilder.js index 5f3230d4d98bd3e3da477dd617e5cd38b50e2167..abe4c1ed58af1a26ebf2975c567432ea38f1cc90 100644 --- a/examples/jsm/renderers/nodes/core/NodeBuilder.js +++ b/examples/jsm/renderers/nodes/core/NodeBuilder.js @@ -58,7 +58,8 @@ class NodeBuilder { console.warn( 'Recursive node: ', node ); } -*/ + */ + this.stack.push( node ); } @@ -449,25 +450,9 @@ class NodeBuilder { } - getAttributes( shaderStage ) { - - let snippet = ''; - - if ( shaderStage === 'vertex' ) { - - const attributes = this.attributes; - - for ( let index = 0; index < attributes.length; index ++ ) { - - const attribute = attributes[ index ]; - - snippet += `layout(location = ${index}) in ${attribute.type} ${attribute.name}; `; + getAttributes( /*shaderStage*/ ) { - } - - } - - return snippet; + console.warn( 'Abstract function.' ); } @@ -543,12 +528,32 @@ class NodeBuilder { build() { + // stage 1: analyze nodes to possible optimization and validation + + for ( const shaderStage of shaderStages ) { + + this.setShaderStage( shaderStage ); + + const flowNodes = this.flowNodes[ shaderStage ]; + + for ( const node of flowNodes ) { + + node.analyze( this ); + + } + + } + + // stage 2: pre-build vertex code used in fragment shader + if ( this.context.vertex && this.context.vertex.isNode ) { this.flowNodeFromShaderStage( 'vertex', this.context.vertex ); } + // stage 3: generate shader + for ( const shaderStage of shaderStages ) { this.setShaderStage( shaderStage ); @@ -565,6 +570,8 @@ class NodeBuilder { this.setShaderStage( null ); + // stage 4: build code for a specific output + this.buildCode(); return this; diff --git a/examples/jsm/renderers/nodes/core/TempNode.js b/examples/jsm/renderers/nodes/core/TempNode.js index bbeaf05d087a215f11aed66db080d0dfce056018..e1570c437edaf62061e6be57719e41acfab78d3b 100644 --- a/examples/jsm/renderers/nodes/core/TempNode.js +++ b/examples/jsm/renderers/nodes/core/TempNode.js @@ -11,10 +11,9 @@ class TempNode extends Node { build( builder, output ) { const type = builder.getVectorType( this.getNodeType( builder, output ) ); + const nodeData = builder.getDataFromNode( this ); - if ( builder.context.temp !== false && type !== 'void ' && output !== 'void' ) { - - const nodeData = builder.getDataFromNode( this ); + if ( builder.context.temp !== false && type !== 'void ' && output !== 'void' && nodeData.dependenciesCount > 1 ) { if ( nodeData.snippet === undefined ) { diff --git a/examples/jsm/renderers/nodes/functions/BSDFs.js b/examples/jsm/renderers/nodes/functions/BSDFs.js index c0a8b61d590ab52f5dbd2e37a756114b34f5dcfd..367997b5aee4de55a82a77e12ed647e566161234 100644 --- a/examples/jsm/renderers/nodes/functions/BSDFs.js +++ b/examples/jsm/renderers/nodes/functions/BSDFs.js @@ -107,7 +107,7 @@ export const RE_Direct_Physical = new ShaderNode( ( inputs ) => { irradiance = mul( irradiance, PI ); // punctual light - addTo( directDiffuse, mul( irradiance, BRDF_Lambert( { diffuseColor } ) ) ); + addTo( directDiffuse, mul( irradiance, BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) ); addTo( directSpecular, mul( irradiance, BRDF_GGX( { lightDirection, f0: specularColor, f90: 1, roughness } ) ) ); diff --git a/examples/jsm/renderers/nodes/math/MathNode.js b/examples/jsm/renderers/nodes/math/MathNode.js index fb709b3d432e89cb17f762341abf69271cd00546..ca79f32073c17c5d40aac86a6297bb0518bd703c 100644 --- a/examples/jsm/renderers/nodes/math/MathNode.js +++ b/examples/jsm/renderers/nodes/math/MathNode.js @@ -231,7 +231,7 @@ class MathNode extends TempNode { } - return `${ builder.getMethod( method ) }( ${params.join( ', ' )} )`; + return builder.format( `${ builder.getMethod( method ) }( ${params.join( ', ' )} )`, type, output ); } diff --git a/examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js b/examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js index 63c678b7b5d1dff52a62fffff0482245795c26f6..a0e47dff20f51c8b9d14a55dff338bff4bfe15fe 100644 --- a/examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js +++ b/examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js @@ -1,12 +1,10 @@ -import NodeBuilder from '../../nodes/core/NodeBuilder.js'; +import NodeBuilder, { shaderStages } from '../../nodes/core/NodeBuilder.js'; import SlotNode from './SlotNode.js'; import GLSLNodeParser from '../../nodes/parsers/GLSLNodeParser.js'; import WebGLPhysicalContextNode from './WebGLPhysicalContextNode.js'; import { ShaderChunk, ShaderLib, UniformsUtils, UniformsLib, - LinearEncoding, RGBAFormat, UnsignedByteType, sRGBEncoding } from 'three'; - -const shaderStages = [ 'vertex', 'fragment' ]; + LinearEncoding, RGBAFormat, UnsignedByteType, sRGBEncoding } from 'three'; const nodeShaderLib = { LineBasicNodeMaterial: ShaderLib.basic,