|
@@ -2,7 +2,6 @@ import NodeBuilder, { defaultShaderStages } from 'three-nodes/core/NodeBuilder.j
|
|
|
import NodeFrame from 'three-nodes/core/NodeFrame.js';
|
|
|
import SlotNode from './SlotNode.js';
|
|
|
import GLSLNodeParser from 'three-nodes/parsers/GLSLNodeParser.js';
|
|
|
-import WebGLPhysicalContextNode from './WebGLPhysicalContextNode.js';
|
|
|
|
|
|
import { PerspectiveCamera, ShaderChunk, ShaderLib, UniformsUtils, UniformsLib,
|
|
|
LinearEncoding, RGBAFormat, UnsignedByteType, sRGBEncoding } from 'three';
|
|
@@ -16,7 +15,7 @@ const nodeShaderLib = {
|
|
|
MeshBasicNodeMaterial: ShaderLib.basic,
|
|
|
PointsNodeMaterial: ShaderLib.points,
|
|
|
MeshStandardNodeMaterial: ShaderLib.standard,
|
|
|
- MeshPhysicalMaterial: ShaderLib.physical
|
|
|
+ MeshPhysicalNodeMaterial: ShaderLib.physical
|
|
|
};
|
|
|
|
|
|
const glslMethods = {
|
|
@@ -44,8 +43,12 @@ class WebGLNodeBuilder extends NodeBuilder {
|
|
|
this.shader = shader;
|
|
|
this.slots = { vertex: [], fragment: [] };
|
|
|
|
|
|
+ this._parseShaderLib();
|
|
|
+ this._parseInclude( 'fragment', 'lights_physical_fragment', 'clearcoat_normal_fragment_begin', 'transmission_fragment' );
|
|
|
this._parseObject();
|
|
|
|
|
|
+ this._sortSlotsToFlow();
|
|
|
+
|
|
|
}
|
|
|
|
|
|
getMethod( method ) {
|
|
@@ -58,8 +61,6 @@ class WebGLNodeBuilder extends NodeBuilder {
|
|
|
|
|
|
this.slots[ shaderStage ].push( slotNode );
|
|
|
|
|
|
- return this.addFlow( shaderStage, slotNode );
|
|
|
-
|
|
|
}
|
|
|
|
|
|
addFlowCode( code ) {
|
|
@@ -74,20 +75,12 @@ class WebGLNodeBuilder extends NodeBuilder {
|
|
|
|
|
|
}
|
|
|
|
|
|
- _parseObject() {
|
|
|
-
|
|
|
- const { material, renderer } = this;
|
|
|
+ _parseShaderLib() {
|
|
|
|
|
|
- let type = material.type;
|
|
|
+ const type = this.material.type;
|
|
|
|
|
|
// shader lib
|
|
|
|
|
|
- if ( material.isMeshPhysicalNodeMaterial ) type = 'MeshPhysicalMaterial';
|
|
|
- else if ( material.isMeshStandardNodeMaterial ) type = 'MeshStandardNodeMaterial';
|
|
|
- else if ( material.isMeshBasicNodeMaterial ) type = 'MeshBasicNodeMaterial';
|
|
|
- else if ( material.isPointsNodeMaterial ) type = 'PointsNodeMaterial';
|
|
|
- else if ( material.isLineBasicNodeMaterial ) type = 'LineBasicNodeMaterial';
|
|
|
-
|
|
|
if ( nodeShaderLib[ type ] !== undefined ) {
|
|
|
|
|
|
const shaderLib = nodeShaderLib[ type ];
|
|
@@ -99,9 +92,20 @@ class WebGLNodeBuilder extends NodeBuilder {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ }
|
|
|
+
|
|
|
+ _parseObject() {
|
|
|
+
|
|
|
+ const { material, renderer } = this;
|
|
|
+
|
|
|
if ( renderer.toneMappingNode?.isNode === true ) {
|
|
|
|
|
|
- this.replaceCode( 'fragment', getIncludeSnippet( 'tonemapping_fragment' ), '' );
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.colorNode,
|
|
|
+ nodeType: 'vec4',
|
|
|
+ source: getIncludeSnippet( 'tonemapping_fragment' ),
|
|
|
+ target: ''
|
|
|
+ } ) );
|
|
|
|
|
|
}
|
|
|
|
|
@@ -109,129 +113,308 @@ class WebGLNodeBuilder extends NodeBuilder {
|
|
|
|
|
|
if ( material.colorNode && material.colorNode.isNode ) {
|
|
|
|
|
|
- this.addSlot( 'fragment', new SlotNode( material.colorNode, 'COLOR', 'vec4' ) );
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.colorNode,
|
|
|
+ nodeType: 'vec4',
|
|
|
+ source: getIncludeSnippet( 'color_fragment' ),
|
|
|
+ target: 'diffuseColor = %RESULT%;',
|
|
|
+ inclusionType: 'append'
|
|
|
+ } ) );
|
|
|
|
|
|
}
|
|
|
|
|
|
if ( material.opacityNode && material.opacityNode.isNode ) {
|
|
|
|
|
|
- this.addSlot( 'fragment', new SlotNode( material.opacityNode, 'OPACITY', 'float' ) );
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.opacityNode,
|
|
|
+ nodeType: 'float',
|
|
|
+ source: getIncludeSnippet( 'alphatest_fragment' ),
|
|
|
+ target: 'diffuseColor.a = %RESULT%;',
|
|
|
+ inclusionType: 'append'
|
|
|
+ } ) );
|
|
|
|
|
|
}
|
|
|
|
|
|
if ( material.normalNode && material.normalNode.isNode ) {
|
|
|
|
|
|
- this.addSlot( 'fragment', new SlotNode( material.normalNode, 'NORMAL', 'vec3' ) );
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.normalNode,
|
|
|
+ nodeType: 'vec3',
|
|
|
+ source: getIncludeSnippet( 'normal_fragment_begin' ),
|
|
|
+ target: 'normal = %RESULT%;',
|
|
|
+ inclusionType: 'append'
|
|
|
+ } ) );
|
|
|
|
|
|
}
|
|
|
|
|
|
if ( material.emissiveNode && material.emissiveNode.isNode ) {
|
|
|
|
|
|
- this.addSlot( 'fragment', new SlotNode( material.emissiveNode, 'EMISSIVE', 'vec3' ) );
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.emissiveNode,
|
|
|
+ nodeType: 'vec3',
|
|
|
+ source: getIncludeSnippet( 'emissivemap_fragment' ),
|
|
|
+ target: 'totalEmissiveRadiance = %RESULT%;',
|
|
|
+ inclusionType: 'append'
|
|
|
+ } ) );
|
|
|
|
|
|
}
|
|
|
|
|
|
- if ( material.metalnessNode && material.metalnessNode.isNode ) {
|
|
|
+ if ( material.isMeshStandardNodeMaterial ) {
|
|
|
|
|
|
- this.addSlot( 'fragment', new SlotNode( material.metalnessNode, 'METALNESS', 'float' ) );
|
|
|
+ if ( material.metalnessNode && material.metalnessNode.isNode ) {
|
|
|
|
|
|
- }
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.metalnessNode,
|
|
|
+ nodeType: 'float',
|
|
|
+ source: getIncludeSnippet( 'metalnessmap_fragment' ),
|
|
|
+ target: 'metalnessFactor = %RESULT%;',
|
|
|
+ inclusionType: 'append'
|
|
|
+ } ) );
|
|
|
|
|
|
- if ( material.roughnessNode && material.roughnessNode.isNode ) {
|
|
|
+ }
|
|
|
|
|
|
- this.addSlot( 'fragment', new SlotNode( material.roughnessNode, 'ROUGHNESS', 'float' ) );
|
|
|
+ if ( material.roughnessNode && material.roughnessNode.isNode ) {
|
|
|
|
|
|
- }
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.roughnessNode,
|
|
|
+ nodeType: 'float',
|
|
|
+ source: getIncludeSnippet( 'roughnessmap_fragment' ),
|
|
|
+ target: 'roughnessFactor = %RESULT%;',
|
|
|
+ inclusionType: 'append'
|
|
|
+ } ) );
|
|
|
|
|
|
- if ( material.isMeshPhysicalNodeMaterial ) {
|
|
|
+ }
|
|
|
|
|
|
- if ( material.clearcoatNode && material.clearcoatNode.isNode ) {
|
|
|
+ if ( material.isMeshPhysicalNodeMaterial ) {
|
|
|
|
|
|
- this.addSlot( 'fragment', new SlotNode( material.clearcoatNode, 'CLEARCOAT', 'float' ) );
|
|
|
+ if ( material.clearcoatNode && material.clearcoatNode.isNode ) {
|
|
|
|
|
|
- if ( material.clearcoatRoughnessNode && material.clearcoatRoughnessNode.isNode ) {
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.clearcoatNode,
|
|
|
+ nodeType: 'float',
|
|
|
+ source: 'material.clearcoat = clearcoat;',
|
|
|
+ target: 'material.clearcoat = %RESULT%;'
|
|
|
+ } ) );
|
|
|
|
|
|
- this.addSlot( 'fragment', new SlotNode( material.clearcoatRoughnessNode, 'CLEARCOAT_ROUGHNESS', 'float' ) );
|
|
|
+ if ( material.clearcoatRoughnessNode && material.clearcoatRoughnessNode.isNode ) {
|
|
|
|
|
|
- }
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.clearcoatRoughnessNode,
|
|
|
+ nodeType: 'float',
|
|
|
+ source: 'material.clearcoatRoughness = clearcoatRoughness;',
|
|
|
+ target: 'material.clearcoatRoughness = %RESULT%;'
|
|
|
+ } ) );
|
|
|
|
|
|
- if ( material.clearcoatNormalNode && material.clearcoatNormalNode.isNode ) {
|
|
|
+ }
|
|
|
|
|
|
- this.addSlot( 'fragment', new SlotNode( material.clearcoatNormalNode, 'CLEARCOAT_NORMAL', 'vec3' ) );
|
|
|
+ if ( material.clearcoatNormalNode && material.clearcoatNormalNode.isNode ) {
|
|
|
+
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.clearcoatNormalNode,
|
|
|
+ nodeType: 'vec3',
|
|
|
+ source: 'vec3 clearcoatNormal = geometryNormal;',
|
|
|
+ target: 'vec3 clearcoatNormal = %RESULT%;'
|
|
|
+ } ) );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ material.defines.USE_CLEARCOAT = '';
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ delete material.defines.USE_CLEARCOAT;
|
|
|
|
|
|
}
|
|
|
|
|
|
- material.defines.USE_CLEARCOAT = '';
|
|
|
+ if ( material.sheenNode && material.sheenNode.isNode ) {
|
|
|
|
|
|
- } else {
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.sheenNode,
|
|
|
+ nodeType: 'vec3',
|
|
|
+ source: 'material.sheenColor = sheenColor;',
|
|
|
+ target: 'material.sheenColor = %RESULT%;'
|
|
|
+ } ) );
|
|
|
|
|
|
- delete material.defines.USE_CLEARCOAT;
|
|
|
+ if ( material.sheenRoughnessNode && material.sheenRoughnessNode.isNode ) {
|
|
|
|
|
|
- }
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.sheenRoughnessNode,
|
|
|
+ nodeType: 'float',
|
|
|
+ source: 'material.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );',
|
|
|
+ target: 'material.sheenRoughness = clamp( %RESULT%, 0.07, 1.0 );'
|
|
|
+ } ) );
|
|
|
|
|
|
- if ( material.sheenNode && material.sheenNode.isNode ) {
|
|
|
+ }
|
|
|
|
|
|
- this.addSlot( 'fragment', new SlotNode( material.sheenNode, 'SHEEN', 'vec3' ) );
|
|
|
+ material.defines.USE_SHEEN = '';
|
|
|
|
|
|
- if ( material.sheenRoughnessNode && material.sheenRoughnessNode.isNode ) {
|
|
|
+ } else {
|
|
|
|
|
|
- this.addSlot( 'fragment', new SlotNode( material.sheenRoughnessNode, 'SHEEN_ROUGHNESS', 'float' ) );
|
|
|
+ delete material.defines.USE_SHEEN;
|
|
|
|
|
|
}
|
|
|
|
|
|
- material.defines.USE_SHEEN = '';
|
|
|
+ if ( material.iridescenceNode && material.iridescenceNode.isNode ) {
|
|
|
|
|
|
- } else {
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.iridescenceNode,
|
|
|
+ nodeType: 'float',
|
|
|
+ source: 'material.iridescence = iridescence;',
|
|
|
+ target: 'material.iridescence = %RESULT%;'
|
|
|
+ } ) );
|
|
|
|
|
|
- delete material.defines.USE_SHEEN;
|
|
|
+ if ( material.iridescenceIORNode && material.iridescenceIORNode.isNode ) {
|
|
|
|
|
|
- }
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.iridescenceIORNode,
|
|
|
+ nodeType: 'float',
|
|
|
+ source: 'material.iridescenceIOR = iridescenceIOR;',
|
|
|
+ target: 'material.iridescenceIOR = %RESULT%;'
|
|
|
+ } ) );
|
|
|
|
|
|
- if ( material.iridescenceNode && material.iridescenceNode.isNode ) {
|
|
|
+ }
|
|
|
|
|
|
- this.addSlot( 'fragment', new SlotNode( material.iridescenceNode, 'IRIDESCENCE', 'float' ) );
|
|
|
+ if ( material.iridescenceThicknessNode && material.iridescenceThicknessNode.isNode ) {
|
|
|
|
|
|
- if ( material.iridescenceIORNode && material.iridescenceIORNode.isNode ) {
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.iridescenceThicknessNode,
|
|
|
+ nodeType: 'float',
|
|
|
+ source: 'material.iridescenceThickness = iridescenceThicknessMaximum;',
|
|
|
+ target: 'material.iridescenceThickness = %RESULT%;'
|
|
|
+ } ) );
|
|
|
|
|
|
- this.addSlot( 'fragment', new SlotNode( material.iridescenceIORNode, 'IRIDESCENCE_IOR', 'float' ) );
|
|
|
+ }
|
|
|
+
|
|
|
+ material.defines.USE_IRIDESCENCE = '';
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ delete material.defines.USE_IRIDESCENCE;
|
|
|
|
|
|
}
|
|
|
|
|
|
- if ( material.iridescenceThicknessNode && material.iridescenceThicknessNode.isNode ) {
|
|
|
+ if ( material.iorNode && material.iorNode.isNode ) {
|
|
|
|
|
|
- this.addSlot( 'fragment', new SlotNode( material.iridescenceThicknessNode, 'IRIDESCENCE_THICKNESS', 'float' ) );
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.iorNode,
|
|
|
+ nodeType: 'float',
|
|
|
+ source: 'material.ior = ior;',
|
|
|
+ target: 'material.ior = %RESULT%;'
|
|
|
+ } ) );
|
|
|
|
|
|
}
|
|
|
|
|
|
- material.defines.USE_IRIDESCENCE = '';
|
|
|
+ if ( material.specularColorNode && material.specularColorNode.isNode ) {
|
|
|
|
|
|
- } else {
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.specularColorNode,
|
|
|
+ nodeType: 'vec3',
|
|
|
+ source: 'vec3 specularColorFactor = specularColor;',
|
|
|
+ target: 'vec3 specularColorFactor = %RESULT%;'
|
|
|
+ } ) );
|
|
|
|
|
|
- delete material.defines.USE_IRIDESCENCE;
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ if ( material.specularIntensityNode && material.specularIntensityNode.isNode ) {
|
|
|
|
|
|
- }
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.specularIntensityNode,
|
|
|
+ nodeType: 'float',
|
|
|
+ source: 'float specularIntensityFactor = specularIntensity;',
|
|
|
+ target: 'float specularIntensityFactor = %RESULT%;'
|
|
|
+ } ) );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( material.transmissionNode && material.transmissionNode.isNode ) {
|
|
|
+
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.transmissionNode,
|
|
|
+ nodeType: 'float',
|
|
|
+ source: 'material.transmission = transmission;',
|
|
|
+ target: 'material.transmission = %RESULT%;'
|
|
|
+ } ) );
|
|
|
+
|
|
|
+ if ( material.thicknessNode && material.thicknessNode.isNode ) {
|
|
|
+
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.thicknessNode,
|
|
|
+ nodeType: 'float',
|
|
|
+ source: 'material.thickness = thickness;',
|
|
|
+ target: 'material.thickness = %RESULT%;'
|
|
|
+ } ) );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( material.thicknessNode && material.thicknessNode.isNode ) {
|
|
|
+
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.thicknessNode,
|
|
|
+ nodeType: 'float',
|
|
|
+ source: 'material.thickness = thickness;',
|
|
|
+ target: 'material.thickness = %RESULT%;'
|
|
|
+ } ) );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( material.attenuationDistanceNode && material.attenuationDistanceNode.isNode ) {
|
|
|
+
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.attenuationDistanceNode,
|
|
|
+ nodeType: 'float',
|
|
|
+ source: 'material.attenuationDistance = attenuationDistance;',
|
|
|
+ target: 'material.attenuationDistance = %RESULT%;'
|
|
|
+ } ) );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( material.attenuationColorNode && material.attenuationColorNode.isNode ) {
|
|
|
+
|
|
|
+ this.addSlot( 'fragment', new SlotNode( {
|
|
|
+ node: material.attenuationColorNode,
|
|
|
+ nodeType: 'vec3',
|
|
|
+ source: 'material.attenuationColor = attenuationColor;',
|
|
|
+ target: 'material.attenuationColor = %RESULT%;'
|
|
|
+ } ) );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ material.transmission = 1;
|
|
|
+ material.defines.USE_TRANSMISSION = '';
|
|
|
+
|
|
|
+ } else {
|
|
|
|
|
|
- if ( material.envNode && material.envNode.isNode ) {
|
|
|
+ material.transmission = 0;
|
|
|
+ delete material.defines.USE_TRANSMISSION;
|
|
|
|
|
|
- const envRadianceNode = new WebGLPhysicalContextNode( WebGLPhysicalContextNode.RADIANCE, material.envNode );
|
|
|
- const envIrradianceNode = new WebGLPhysicalContextNode( WebGLPhysicalContextNode.IRRADIANCE, material.envNode );
|
|
|
+ }
|
|
|
|
|
|
- this.addSlot( 'fragment', new SlotNode( envRadianceNode, 'RADIANCE', 'vec3' ) );
|
|
|
- this.addSlot( 'fragment', new SlotNode( envIrradianceNode, 'IRRADIANCE', 'vec3' ) );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
+ //
|
|
|
+
|
|
|
if ( material.positionNode && material.positionNode.isNode ) {
|
|
|
|
|
|
- this.addSlot( 'vertex', new SlotNode( material.positionNode, 'POSITION', 'vec3' ) );
|
|
|
+ this.addSlot( 'vertex', new SlotNode( {
|
|
|
+ node: material.positionNode,
|
|
|
+ nodeType: 'vec3',
|
|
|
+ source: getIncludeSnippet( 'begin_vertex' ),
|
|
|
+ target: 'transformed = %RESULT%;',
|
|
|
+ inclusionType: 'append'
|
|
|
+ } ) );
|
|
|
|
|
|
}
|
|
|
|
|
|
if ( material.sizeNode && material.sizeNode.isNode ) {
|
|
|
|
|
|
- this.addSlot( 'vertex', new SlotNode( material.sizeNode, 'SIZE', 'float' ) );
|
|
|
+ this.addSlot( 'vertex', new SlotNode( {
|
|
|
+ node: material.sizeNode,
|
|
|
+ nodeType: 'float',
|
|
|
+ source: 'gl_PointSize = size;',
|
|
|
+ target: 'gl_PointSize = %RESULT%;'
|
|
|
+ } ) );
|
|
|
|
|
|
}
|
|
|
|
|
@@ -335,7 +518,7 @@ class WebGLNodeBuilder extends NodeBuilder {
|
|
|
|
|
|
}
|
|
|
|
|
|
- addCodeAfterSnippet( shaderStage, snippet, code ) {
|
|
|
+ addCodeAfterCode( shaderStage, snippet, code ) {
|
|
|
|
|
|
const shaderProperty = getShaderStageProperty( shaderStage );
|
|
|
|
|
@@ -356,14 +539,6 @@ class WebGLNodeBuilder extends NodeBuilder {
|
|
|
|
|
|
}
|
|
|
|
|
|
- addCodeAfterInclude( shaderStage, includeName, code ) {
|
|
|
-
|
|
|
- const includeSnippet = getIncludeSnippet( includeName );
|
|
|
-
|
|
|
- this.addCodeAfterSnippet( shaderStage, includeSnippet, code );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
replaceCode( shaderStage, source, target ) {
|
|
|
|
|
|
const shaderProperty = getShaderStageProperty( shaderStage );
|
|
@@ -372,19 +547,6 @@ class WebGLNodeBuilder extends NodeBuilder {
|
|
|
|
|
|
}
|
|
|
|
|
|
- parseInclude( shaderStage, ...includes ) {
|
|
|
-
|
|
|
- for ( const name of includes ) {
|
|
|
-
|
|
|
- const includeSnippet = getIncludeSnippet( name );
|
|
|
- const code = ShaderChunk[ name ];
|
|
|
-
|
|
|
- this.replaceCode( shaderStage, includeSnippet, code );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
getTextureEncodingFromMap( map ) {
|
|
|
|
|
|
const isWebGL2 = this.renderer.capabilities.isWebGL2;
|
|
@@ -463,208 +625,77 @@ ${this.shader[ getShaderStageProperty( shaderStage ) ]}
|
|
|
|
|
|
}
|
|
|
|
|
|
- getSlot( shaderStage, name ) {
|
|
|
-
|
|
|
- const slots = this.slots[ shaderStage ];
|
|
|
+ _parseInclude( shaderStage, ...includes ) {
|
|
|
|
|
|
- for ( const node of slots ) {
|
|
|
+ for ( const name of includes ) {
|
|
|
|
|
|
- if ( node.name === name ) {
|
|
|
+ const includeSnippet = getIncludeSnippet( name );
|
|
|
+ const code = ShaderChunk[ name ];
|
|
|
|
|
|
- return this.getFlowData( node/*, shaderStage*/ );
|
|
|
+ const shaderProperty = getShaderStageProperty( shaderStage );
|
|
|
|
|
|
- }
|
|
|
+ this.shader[ shaderProperty ] = this.shader[ shaderProperty ].replaceAll( includeSnippet, code );
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
- _addSnippets() {
|
|
|
-
|
|
|
- this.parseInclude( 'fragment', 'lights_physical_fragment' );
|
|
|
- this.parseInclude( 'fragment', 'clearcoat_normal_fragment_begin' );
|
|
|
-
|
|
|
- const colorSlot = this.getSlot( 'fragment', 'COLOR' );
|
|
|
- const opacityNode = this.getSlot( 'fragment', 'OPACITY' );
|
|
|
- const normalSlot = this.getSlot( 'fragment', 'NORMAL' );
|
|
|
- const emissiveNode = this.getSlot( 'fragment', 'EMISSIVE' );
|
|
|
- const roughnessNode = this.getSlot( 'fragment', 'ROUGHNESS' );
|
|
|
- const metalnessNode = this.getSlot( 'fragment', 'METALNESS' );
|
|
|
- const clearcoatNode = this.getSlot( 'fragment', 'CLEARCOAT' );
|
|
|
- const clearcoatRoughnessNode = this.getSlot( 'fragment', 'CLEARCOAT_ROUGHNESS' );
|
|
|
- const clearcoatNormalNode = this.getSlot( 'fragment', 'CLEARCOAT_NORMAL' );
|
|
|
- const sheenNode = this.getSlot( 'fragment', 'SHEEN' );
|
|
|
- const sheenRoughnessNode = this.getSlot( 'fragment', 'SHEEN_ROUGHNESS' );
|
|
|
- const iridescenceNode = this.getSlot( 'fragment', 'IRIDESCENCE' );
|
|
|
- const iridescenceIORNode = this.getSlot( 'fragment', 'IRIDESCENCE_IOR' );
|
|
|
- const iridescenceThicknessNode = this.getSlot( 'fragment', 'IRIDESCENCE_THICKNESS' );
|
|
|
-
|
|
|
- const positionNode = this.getSlot( 'vertex', 'POSITION' );
|
|
|
- const sizeNode = this.getSlot( 'vertex', 'SIZE' );
|
|
|
-
|
|
|
- if ( colorSlot !== undefined ) {
|
|
|
-
|
|
|
- this.addCodeAfterInclude(
|
|
|
- 'fragment',
|
|
|
- 'color_fragment',
|
|
|
- `${colorSlot.code}\n\tdiffuseColor = ${colorSlot.result};`
|
|
|
- );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( opacityNode !== undefined ) {
|
|
|
-
|
|
|
- this.addCodeAfterInclude(
|
|
|
- 'fragment',
|
|
|
- 'alphatest_fragment',
|
|
|
- `${opacityNode.code}\n\tdiffuseColor.a = ${opacityNode.result};`
|
|
|
- );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( normalSlot !== undefined ) {
|
|
|
-
|
|
|
- this.addCodeAfterInclude(
|
|
|
- 'fragment',
|
|
|
- 'normal_fragment_begin',
|
|
|
- `${normalSlot.code}\n\tnormal = ${normalSlot.result};`
|
|
|
- );
|
|
|
-
|
|
|
- }
|
|
|
+ _sortSlotsToFlow() {
|
|
|
|
|
|
- if ( emissiveNode !== undefined ) {
|
|
|
-
|
|
|
- this.addCodeAfterInclude(
|
|
|
- 'fragment',
|
|
|
- 'emissivemap_fragment',
|
|
|
- `${emissiveNode.code}\n\ttotalEmissiveRadiance = ${emissiveNode.result};`
|
|
|
- );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( roughnessNode !== undefined ) {
|
|
|
-
|
|
|
- this.addCodeAfterInclude(
|
|
|
- 'fragment',
|
|
|
- 'roughnessmap_fragment',
|
|
|
- `${roughnessNode.code}\n\troughnessFactor = ${roughnessNode.result};`
|
|
|
- );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( metalnessNode !== undefined ) {
|
|
|
-
|
|
|
- this.addCodeAfterInclude(
|
|
|
- 'fragment',
|
|
|
- 'metalnessmap_fragment',
|
|
|
- `${metalnessNode.code}\n\tmetalnessFactor = ${metalnessNode.result};`
|
|
|
- );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( clearcoatNode !== undefined ) {
|
|
|
-
|
|
|
- this.addCodeAfterSnippet(
|
|
|
- 'fragment',
|
|
|
- 'material.clearcoat = clearcoat;',
|
|
|
- `${clearcoatNode.code}\n\tmaterial.clearcoat = ${clearcoatNode.result};`
|
|
|
- );
|
|
|
-
|
|
|
- if ( clearcoatRoughnessNode !== undefined ) {
|
|
|
-
|
|
|
- this.addCodeAfterSnippet(
|
|
|
- 'fragment',
|
|
|
- 'material.clearcoatRoughness = clearcoatRoughness;',
|
|
|
- `${clearcoatRoughnessNode.code}\n\tmaterial.clearcoatRoughness = ${clearcoatRoughnessNode.result};`
|
|
|
- );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( clearcoatNormalNode !== undefined ) {
|
|
|
+ for ( const shaderStage of defaultShaderStages ) {
|
|
|
|
|
|
- this.addCodeAfterSnippet(
|
|
|
- 'fragment',
|
|
|
- 'vec3 clearcoatNormal = geometryNormal;',
|
|
|
- `${clearcoatNormalNode.code}\n\tclearcoatNormal = ${clearcoatNormalNode.result};`
|
|
|
- );
|
|
|
+ const sourceCode = this.shader[ getShaderStageProperty( shaderStage ) ];
|
|
|
|
|
|
- }
|
|
|
+ const slots = this.slots[ shaderStage ].sort( ( slotA, slotB ) => {
|
|
|
|
|
|
- }
|
|
|
+ if ( sourceCode.indexOf( slotA.source ) == - 1 ) {
|
|
|
+ //console.log( slotA, sourceCode.indexOf( slotA.source ), sourceCode.indexOf( slotB.source ) );
|
|
|
+ //console.log(sourceCode);
|
|
|
+ }
|
|
|
|
|
|
- if ( sheenNode !== undefined ) {
|
|
|
+ return sourceCode.indexOf( slotA.source ) > sourceCode.indexOf( slotB.source ) ? 1 : - 1;
|
|
|
|
|
|
- this.addCodeAfterSnippet(
|
|
|
- 'fragment',
|
|
|
- 'material.sheenColor = sheenColor;',
|
|
|
- `${sheenNode.code}\n\tmaterial.sheenColor = ${sheenNode.result};`
|
|
|
- );
|
|
|
+ } );
|
|
|
|
|
|
- if ( sheenRoughnessNode !== undefined ) {
|
|
|
+ for ( const slotNode of slots ) {
|
|
|
|
|
|
- this.replaceCode(
|
|
|
- 'fragment',
|
|
|
- 'material.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );',
|
|
|
- `${sheenRoughnessNode.code}\n\tmaterial.sheenRoughness = clamp( ${sheenRoughnessNode.result}, 0.07, 1.0 );`
|
|
|
- );
|
|
|
+ this.addFlow( shaderStage, slotNode );
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
- if ( iridescenceNode !== undefined ) {
|
|
|
-
|
|
|
- this.addCodeAfterSnippet(
|
|
|
- 'fragment',
|
|
|
- 'material.iridescence = iridescence;',
|
|
|
- `${iridescenceNode.code}\n\tmaterial.iridescence = ${iridescenceNode.result};`
|
|
|
- );
|
|
|
-
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- if ( iridescenceIORNode !== undefined ) {
|
|
|
+ _addSnippets() {
|
|
|
|
|
|
- this.addCodeAfterSnippet(
|
|
|
- 'fragment',
|
|
|
- 'material.iridescenceIOR = iridescenceIOR;',
|
|
|
- `${iridescenceIORNode.code}\n\tmaterial.iridescenceIOR = ${iridescenceIORNode.result};`
|
|
|
- );
|
|
|
+ for ( const shaderStage of defaultShaderStages ) {
|
|
|
|
|
|
- }
|
|
|
+ for ( const slotNode of this.slots[ shaderStage ] ) {
|
|
|
|
|
|
- if ( iridescenceThicknessNode !== undefined ) {
|
|
|
+ const flowData = this.getFlowData( slotNode/*, shaderStage*/ );
|
|
|
|
|
|
- this.addCodeAfterSnippet(
|
|
|
- 'fragment',
|
|
|
- 'material.iridescenceThickness = iridescenceThicknessMaximum;',
|
|
|
- `${iridescenceThicknessNode.code}\n\tmaterial.iridescenceThickness = ${iridescenceThicknessNode.result};`
|
|
|
- );
|
|
|
+ const inclusionType = slotNode.inclusionType;
|
|
|
+ const source = slotNode.source;
|
|
|
+ const target = flowData.code + '\n\t' + slotNode.target.replace( '%RESULT%', flowData.result );
|
|
|
|
|
|
- }
|
|
|
+ if ( inclusionType === 'append' ) {
|
|
|
|
|
|
- if ( positionNode !== undefined ) {
|
|
|
+ this.addCodeAfterCode( shaderStage, source, target );
|
|
|
|
|
|
- this.addCodeAfterInclude(
|
|
|
- 'vertex',
|
|
|
- 'begin_vertex',
|
|
|
- `${positionNode.code}\n\ttransformed = ${positionNode.result};`
|
|
|
- );
|
|
|
+ } else if ( inclusionType === 'replace' ) {
|
|
|
|
|
|
- }
|
|
|
+ this.replaceCode( shaderStage, source, target );
|
|
|
|
|
|
- if ( sizeNode !== undefined ) {
|
|
|
+ } else {
|
|
|
|
|
|
- this.addCodeAfterSnippet(
|
|
|
- 'vertex',
|
|
|
- 'gl_PointSize = size;',
|
|
|
- `${sizeNode.code}\n\tgl_PointSize = ${sizeNode.result};`
|
|
|
- );
|
|
|
+ console.warn( `Inclusion type "${ inclusionType }" not compatible.` );
|
|
|
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- for ( const shaderStage of defaultShaderStages ) {
|
|
|
+ }
|
|
|
|
|
|
- this.addCodeAfterSnippet(
|
|
|
+ this.addCodeAfterCode(
|
|
|
shaderStage,
|
|
|
'main() {',
|
|
|
this.flowCode[ shaderStage ]
|