|
@@ -3,13 +3,14 @@ import {
|
|
|
FloatNodeUniform, Vector2NodeUniform, Vector3NodeUniform, Vector4NodeUniform,
|
|
|
ColorNodeUniform, Matrix3NodeUniform, Matrix4NodeUniform
|
|
|
} from './WebGPUNodeUniform.js';
|
|
|
-import WebGPUSampler from '../WebGPUSampler.js';
|
|
|
-import { WebGPUSampledTexture } from '../WebGPUSampledTexture.js';
|
|
|
+import WebGPUNodeSampler from './WebGPUNodeSampler.js';
|
|
|
+import { WebGPUNodeSampledTexture } from './WebGPUNodeSampledTexture.js';
|
|
|
|
|
|
import NodeSlot from '../../nodes/core/NodeSlot.js';
|
|
|
import NodeBuilder from '../../nodes/core/NodeBuilder.js';
|
|
|
+import MaterialNode from '../../nodes/accessors/MaterialNode.js';
|
|
|
import ModelViewProjectionNode from '../../nodes/accessors/ModelViewProjectionNode.js';
|
|
|
-
|
|
|
+import LightContextNode from '../../nodes/lights/LightContextNode.js';
|
|
|
import ShaderLib from './ShaderLib.js';
|
|
|
|
|
|
class WebGPUNodeBuilder extends NodeBuilder {
|
|
@@ -35,13 +36,26 @@ class WebGPUNodeBuilder extends NodeBuilder {
|
|
|
|
|
|
// get shader
|
|
|
|
|
|
- this.nativeShader = ShaderLib.common;
|
|
|
+ let shader = null;
|
|
|
+
|
|
|
+ if ( material.isMeshPhongMaterial ) {
|
|
|
+
|
|
|
+ shader = ShaderLib.phong;
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ shader = ShaderLib.common;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ this.nativeShader = shader;
|
|
|
|
|
|
// parse inputs
|
|
|
|
|
|
- if ( material.isMeshBasicMaterial || material.isPointsMaterial || material.isLineBasicMaterial ) {
|
|
|
+ if ( material.isMeshPhongMaterial || material.isMeshBasicMaterial || material.isPointsMaterial || material.isLineBasicMaterial ) {
|
|
|
|
|
|
const mvpNode = new ModelViewProjectionNode();
|
|
|
+ const lightNode = material.lightNode;
|
|
|
|
|
|
if ( material.positionNode !== undefined ) {
|
|
|
|
|
@@ -55,12 +69,52 @@ class WebGPUNodeBuilder extends NodeBuilder {
|
|
|
|
|
|
this.addSlot( 'fragment', new NodeSlot( material.colorNode, 'COLOR', 'vec4' ) );
|
|
|
|
|
|
+ } else {
|
|
|
+
|
|
|
+ this.addSlot( 'fragment', new NodeSlot( new MaterialNode( MaterialNode.COLOR ), 'COLOR', 'vec4' ) );
|
|
|
+
|
|
|
}
|
|
|
|
|
|
if ( material.opacityNode !== undefined ) {
|
|
|
|
|
|
this.addSlot( 'fragment', new NodeSlot( material.opacityNode, 'OPACITY', 'float' ) );
|
|
|
|
|
|
+ } else {
|
|
|
+
|
|
|
+ this.addSlot( 'fragment', new NodeSlot( new MaterialNode( MaterialNode.OPACITY ), 'OPACITY', 'float' ) );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( material.isMeshPhongMaterial ) {
|
|
|
+
|
|
|
+ if ( material.specularNode !== undefined ) {
|
|
|
+
|
|
|
+ this.addSlot( 'fragment', new NodeSlot( material.specularNode, 'SPECULAR', 'vec3' ) );
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ this.addSlot( 'fragment', new NodeSlot( new MaterialNode( MaterialNode.SPECULAR ), 'SPECULAR', 'vec3' ) );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( material.shininessNode !== undefined ) {
|
|
|
+
|
|
|
+ this.addSlot( 'fragment', new NodeSlot( material.shininessNode, 'SHININESS', 'float' ) );
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ this.addSlot( 'fragment', new NodeSlot( new MaterialNode( MaterialNode.SHININESS ), 'SHININESS', 'float' ) );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( lightNode !== undefined ) {
|
|
|
+
|
|
|
+ const lightContextNode = new LightContextNode( lightNode );
|
|
|
+
|
|
|
+ this.addSlot( 'fragment', new NodeSlot( lightContextNode, 'LIGHT', 'vec3' ) );
|
|
|
+
|
|
|
}
|
|
|
|
|
|
}
|
|
@@ -75,7 +129,7 @@ class WebGPUNodeBuilder extends NodeBuilder {
|
|
|
|
|
|
getPropertyName( node ) {
|
|
|
|
|
|
- if ( node.isNodeUniform ) {
|
|
|
+ if ( node.isNodeUniform === true ) {
|
|
|
|
|
|
const name = node.name;
|
|
|
const type = node.type;
|
|
@@ -117,8 +171,8 @@ class WebGPUNodeBuilder extends NodeBuilder {
|
|
|
|
|
|
if ( type === 'texture' ) {
|
|
|
|
|
|
- const sampler = new WebGPUSampler( `${uniformNode.name}_sampler`, uniformNode.value );
|
|
|
- const texture = new WebGPUSampledTexture( uniformNode.name, uniformNode.value );
|
|
|
+ const sampler = new WebGPUNodeSampler( `${uniformNode.name}_sampler`, uniformNode.node );
|
|
|
+ const texture = new WebGPUNodeSampledTexture( uniformNode.name, uniformNode.node );
|
|
|
|
|
|
// add first textures in sequence and group for last
|
|
|
const lastBinding = bindings[ bindings.length - 1 ];
|
|
@@ -206,7 +260,7 @@ class WebGPUNodeBuilder extends NodeBuilder {
|
|
|
|
|
|
const attribute = attributes[ index ];
|
|
|
|
|
|
- snippet += `layout(location = ${index}) in ${attribute.type} ${attribute.name};`;
|
|
|
+ snippet += `layout(location = ${index}) in ${attribute.type} ${attribute.name}; `;
|
|
|
|
|
|
}
|
|
|
|
|
@@ -228,7 +282,7 @@ class WebGPUNodeBuilder extends NodeBuilder {
|
|
|
|
|
|
const vary = varys[ index ];
|
|
|
|
|
|
- snippet += `layout(location = ${index}) ${ioStage} ${vary.type} ${vary.name};`;
|
|
|
+ snippet += `layout(location = ${index}) ${ioStage} ${vary.type} ${vary.name}; `;
|
|
|
|
|
|
}
|
|
|
|
|
@@ -244,7 +298,45 @@ class WebGPUNodeBuilder extends NodeBuilder {
|
|
|
|
|
|
for ( const vary of this.varys ) {
|
|
|
|
|
|
- snippet += `${vary.name} = ${vary.snippet};`;
|
|
|
+ snippet += `${vary.name} = ${vary.snippet}; `;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return snippet;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ getVarsHeaderSnippet( shaderStage ) {
|
|
|
+
|
|
|
+ let snippet = '';
|
|
|
+
|
|
|
+ const vars = this.vars[ shaderStage ];
|
|
|
+
|
|
|
+ for ( let index = 0; index < vars.length; index ++ ) {
|
|
|
+
|
|
|
+ const variable = vars[ index ];
|
|
|
+
|
|
|
+ snippet += `${variable.type} ${variable.name}; `;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return snippet;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ getVarsBodySnippet( shaderStage ) {
|
|
|
+
|
|
|
+ let snippet = '';
|
|
|
+
|
|
|
+ const vars = this.vars[ shaderStage ];
|
|
|
+
|
|
|
+ for ( const variable of vars ) {
|
|
|
+
|
|
|
+ if ( variable.snippet !== '' ) {
|
|
|
+
|
|
|
+ snippet += `${variable.name} = ${variable.snippet}; `;
|
|
|
|
|
|
}
|
|
|
|
|
@@ -267,14 +359,14 @@ class WebGPUNodeBuilder extends NodeBuilder {
|
|
|
|
|
|
if ( uniform.type === 'texture' ) {
|
|
|
|
|
|
- snippet += `layout(set = 0, binding = ${index ++}) uniform sampler ${uniform.name}_sampler;`;
|
|
|
- snippet += `layout(set = 0, binding = ${index ++}) uniform texture2D ${uniform.name};`;
|
|
|
+ snippet += `layout(set = 0, binding = ${index ++}) uniform sampler ${uniform.name}_sampler; `;
|
|
|
+ snippet += `layout(set = 0, binding = ${index ++}) uniform texture2D ${uniform.name}; `;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
const vectorType = this.getVectorType( uniform.type );
|
|
|
|
|
|
- groupSnippet += `uniform ${vectorType} ${uniform.name};`;
|
|
|
+ groupSnippet += `uniform ${vectorType} ${uniform.name}; `;
|
|
|
|
|
|
}
|
|
|
|
|
@@ -282,7 +374,7 @@ class WebGPUNodeBuilder extends NodeBuilder {
|
|
|
|
|
|
if ( groupSnippet ) {
|
|
|
|
|
|
- snippet += `layout(set = 0, binding = ${index ++}) uniform NodeUniforms { ${groupSnippet} } nodeUniforms;`;
|
|
|
+ snippet += `layout(set = 0, binding = ${index ++}) uniform NodeUniforms { ${groupSnippet} } nodeUniforms; `;
|
|
|
|
|
|
}
|
|
|
|
|
@@ -307,6 +399,16 @@ class WebGPUNodeBuilder extends NodeBuilder {
|
|
|
|
|
|
build() {
|
|
|
|
|
|
+ const keywords = this.getContextParameter( 'keywords' );
|
|
|
+
|
|
|
+ for ( const shaderStage of [ 'vertex', 'fragment' ] ) {
|
|
|
+
|
|
|
+ this.shaderStage = shaderStage;
|
|
|
+
|
|
|
+ keywords.include( this, this.nativeShader.fragmentShader );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
super.build();
|
|
|
|
|
|
this.vertexShader = this.composeShaderCode( this.nativeShader.vertexShader, this.vertexShader );
|