Просмотр исходного кода

WebGPURenderer: New normal nodes approach (#29137)

* new normal nodes approach

* cleanup

* cleanup

* removing default attribute value, use Fn() instead

* caching some nodes

* cleanup

* cleanup

* rev

* add normalFlat var

* cleanup
sunag 1 год назад
Родитель
Сommit
f571082bcb

+ 0 - 1
examples/webgpu_compute_birds.html

@@ -223,7 +223,6 @@
 			
 				const birdGeometry = new BirdGeometry();
 				const birdMaterial = new THREE.NodeMaterial();
-				birdMaterial.normals = false;
 
 				// Declare varyings
 

+ 2 - 2
src/nodes/accessors/MaterialNode.js

@@ -396,10 +396,10 @@ export const materialSpecularStrength = nodeImmutable( MaterialNode, MaterialNod
 export const materialReflectivity = nodeImmutable( MaterialNode, MaterialNode.REFLECTIVITY );
 export const materialRoughness = nodeImmutable( MaterialNode, MaterialNode.ROUGHNESS );
 export const materialMetalness = nodeImmutable( MaterialNode, MaterialNode.METALNESS );
-export const materialNormal = nodeImmutable( MaterialNode, MaterialNode.NORMAL );
+export const materialNormal = nodeImmutable( MaterialNode, MaterialNode.NORMAL ).context( { getUV: null } );
 export const materialClearcoat = nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT );
 export const materialClearcoatRoughness = nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT_ROUGHNESS );
-export const materialClearcoatNormal = nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT_NORMAL );
+export const materialClearcoatNormal = nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT_NORMAL ).context( { getUV: null } );
 export const materialRotation = nodeImmutable( MaterialNode, MaterialNode.ROTATION );
 export const materialSheen = nodeImmutable( MaterialNode, MaterialNode.SHEEN );
 export const materialSheenRoughness = nodeImmutable( MaterialNode, MaterialNode.SHEEN_ROUGHNESS );

+ 1 - 1
src/nodes/accessors/MorphNode.js

@@ -176,7 +176,7 @@ class MorphNode extends Node {
 		const { geometry } = builder;
 
 		const hasMorphPosition = geometry.morphAttributes.position !== undefined;
-		const hasMorphNormals = geometry.morphAttributes.normal !== undefined;
+		const hasMorphNormals = geometry.hasAttribute( 'normal' ) && geometry.morphAttributes.normal !== undefined;
 
 		const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
 		const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0;

+ 55 - 6
src/nodes/accessors/NormalNode.js

@@ -1,14 +1,63 @@
 import { attribute } from '../core/AttributeNode.js';
 import { varying } from '../core/VaryingNode.js';
-import { property } from '../core/PropertyNode.js';
 import { cameraViewMatrix } from './CameraNode.js';
 import { modelNormalMatrix } from './ModelNode.js';
 import { vec3 } from '../shadernode/ShaderNode.js';
+import { positionView } from './PositionNode.js';
+import { Fn } from '../shadernode/ShaderNode.js';
+import { faceDirection } from '../display/FrontFacingNode.js';
+
+export const normalGeometry = /*#__PURE__*/ attribute( 'normal', 'vec3' );
+
+export const normalLocal = /*#__PURE__*/ ( Fn( ( builder ) => {
+
+	if ( builder.geometry.hasAttribute( 'normal' ) === false ) {
+
+		console.warn( 'TSL.NormalNode: Vertex attribute "normal" not found on geometry.' );
+
+		return vec3( 0, 1, 0 );
+
+	}
+
+	return normalGeometry;
+
+}, 'vec3' ).once() )().toVar( 'normalLocal' );
+
+export const normalFlat = /*#__PURE__*/ positionView.dFdx().cross( positionView.dFdy() ).normalize().toVar( 'normalFlat' );
+
+let normalViewVarying = null;
+
+export const normalView = /*#__PURE__*/ ( Fn( ( builder ) => {
+
+	let node;
+
+	if ( builder.material.flatShading === true ) {
+
+		node = normalFlat;
+
+	} else {
+
+		node = normalViewVarying || ( normalViewVarying = varying( modelNormalMatrix.mul( normalLocal ), 'v_normalView' ).normalize() );
+
+	}
+
+	return node;
+
+}, 'vec3' ).once() )().toVar( 'normalView' );
 
-export const normalGeometry = /*#__PURE__*/ attribute( 'normal', 'vec3', vec3( 0, 1, 0 ) );
-export const normalLocal = /*#__PURE__*/ normalGeometry.toVar( 'normalLocal' );
-export const normalView = /*#__PURE__*/ varying( modelNormalMatrix.mul( normalLocal ), 'v_normalView' ).normalize().toVar( 'normalView' );
 export const normalWorld = /*#__PURE__*/ varying( normalView.transformDirection( cameraViewMatrix ), 'v_normalWorld' ).normalize().toVar( 'normalWorld' );
-export const transformedNormalView = /*#__PURE__*/ property( 'vec3', 'transformedNormalView' );
+
+export const transformedNormalView = /*#__PURE__*/ ( Fn( ( builder ) => {
+
+	return builder.context.setupNormal();
+
+}, 'vec3' ).once() )().mul( faceDirection ).toVar( 'transformedNormalView' );
+
+
 export const transformedNormalWorld = /*#__PURE__*/ transformedNormalView.transformDirection( cameraViewMatrix ).normalize().toVar( 'transformedNormalWorld' );
-export const transformedClearcoatNormalView = /*#__PURE__*/ property( 'vec3', 'transformedClearcoatNormalView' );
+
+export const transformedClearcoatNormalView = /*#__PURE__*/ ( Fn( ( builder ) => {
+
+	return builder.context.setupClearcoatNormal();
+
+}, 'vec3' ).once() )().mul( faceDirection ).toVar( 'transformedClearcoatNormalView' );

+ 0 - 1
src/nodes/accessors/TextureNode.js

@@ -106,7 +106,6 @@ class TextureNode extends UniformNode {
 
 		return this._matrixUniform.mul( vec3( uvNode, 1 ) ).xy;
 
-
 	}
 
 	setUpdateMatrix( value ) {

+ 4 - 16
src/nodes/core/AttributeNode.js

@@ -4,12 +4,10 @@ import { nodeObject } from '../shadernode/ShaderNode.js';
 
 class AttributeNode extends Node {
 
-	constructor( attributeName, nodeType = null, defaultNode = null ) {
+	constructor( attributeName, nodeType = null ) {
 
 		super( nodeType );
 
-		this.defaultNode = defaultNode;
-
 		this.global = true;
 
 		this._attributeName = attributeName;
@@ -24,7 +22,7 @@ class AttributeNode extends Node {
 
 	getNodeType( builder ) {
 
-		let nodeType = super.getNodeType( builder );
+		let nodeType = this.nodeType;
 
 		if ( nodeType === null ) {
 
@@ -91,17 +89,7 @@ class AttributeNode extends Node {
 
 			console.warn( `AttributeNode: Vertex attribute "${ attributeName }" not found on geometry.` );
 
-			const { defaultNode } = this;
-
-			if ( defaultNode !== null ) {
-
-				return defaultNode.build( builder, nodeType );
-
-			} else {
-
-				return builder.generateConst( nodeType );
-
-			}
+			return builder.generateConst( nodeType );
 
 		}
 
@@ -129,6 +117,6 @@ class AttributeNode extends Node {
 
 export default AttributeNode;
 
-export const attribute = ( name, nodeType, defaultNode ) => nodeObject( new AttributeNode( name, nodeType, nodeObject( defaultNode ) ) );
+export const attribute = ( name, nodeType ) => nodeObject( new AttributeNode( name, nodeType ) );
 
 addNodeClass( 'AttributeNode', AttributeNode );

+ 2 - 2
src/nodes/functions/material/getGeometryRoughness.js

@@ -1,9 +1,9 @@
-import { normalGeometry } from '../../accessors/NormalNode.js';
+import { normalView } from '../../accessors/NormalNode.js';
 import { Fn } from '../../shadernode/ShaderNode.js';
 
 const getGeometryRoughness = Fn( () => {
 
-	const dxy = normalGeometry.dFdx().abs().max( normalGeometry.dFdy().abs() );
+	const dxy = normalView.dFdx().abs().max( normalView.dFdy().abs() );
 	const geometryRoughness = dxy.x.max( dxy.y ).max( dxy.z );
 
 	return geometryRoughness;

+ 0 - 2
src/nodes/materials/InstancedPointsNodeMaterial.js

@@ -21,8 +21,6 @@ class InstancedPointsNodeMaterial extends NodeMaterial {
 
 		super();
 
-		this.normals = false;
-
 		this.lights = false;
 
 		this.useAlphaToCoverage = true;

+ 0 - 1
src/nodes/materials/Line2NodeMaterial.js

@@ -23,7 +23,6 @@ class Line2NodeMaterial extends NodeMaterial {
 
 		super();
 
-		this.normals = false;
 		this.lights = false;
 
 		this.setDefaultValues( _defaultValues );

+ 0 - 1
src/nodes/materials/LineBasicNodeMaterial.js

@@ -13,7 +13,6 @@ class LineBasicNodeMaterial extends NodeMaterial {
 		this.isLineBasicNodeMaterial = true;
 
 		this.lights = false;
-		this.normals = false;
 
 		this.setDefaultValues( _defaultValues );
 

+ 0 - 1
src/nodes/materials/LineDashedNodeMaterial.js

@@ -18,7 +18,6 @@ class LineDashedNodeMaterial extends NodeMaterial {
 		this.isLineDashedNodeMaterial = true;
 
 		this.lights = false;
-		this.normals = false;
 
 		this.setDefaultValues( _defaultValues );
 

+ 2 - 3
src/nodes/materials/MeshBasicNodeMaterial.js

@@ -4,7 +4,7 @@ import { MeshBasicMaterial } from '../../materials/MeshBasicMaterial.js';
 import BasicEnvironmentNode from '../lighting/BasicEnvironmentNode.js';
 import BasicLightMapNode from '../lighting/BasicLightMapNode.js';
 import BasicLightingModel from '../functions/BasicLightingModel.js';
-import { transformedNormalView, normalView } from '../accessors/NormalNode.js';
+import { normalView } from '../accessors/NormalNode.js';
 import { diffuseColor } from '../core/PropertyNode.js';
 
 const _defaultValues = /*@__PURE__*/ new MeshBasicMaterial();
@@ -18,7 +18,6 @@ class MeshBasicNodeMaterial extends NodeMaterial {
 		this.isMeshBasicNodeMaterial = true;
 
 		this.lights = true;
-		//this.normals = false; @TODO: normals usage by context
 
 		this.setDefaultValues( _defaultValues );
 
@@ -28,7 +27,7 @@ class MeshBasicNodeMaterial extends NodeMaterial {
 
 	setupNormal() {
 
-		transformedNormalView.assign( normalView ); // see #28839
+		return normalView; // see #28839
 
 	}
 

+ 7 - 6
src/nodes/materials/MeshPhysicalNodeMaterial.js

@@ -1,5 +1,4 @@
 import { addNodeMaterial } from './NodeMaterial.js';
-import { transformedClearcoatNormalView } from '../accessors/NormalNode.js';
 import { clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness, specularColor, specularF90, diffuseColor, metalness, roughness, anisotropy, alphaT, anisotropyT, anisotropyB, ior, transmission, thickness, attenuationDistance, attenuationColor, dispersion } from '../core/PropertyNode.js';
 import { materialClearcoat, materialClearcoatRoughness, materialClearcoatNormal, materialSheen, materialSheenRoughness, materialIridescence, materialIridescenceIOR, materialIridescenceThickness, materialSpecularIntensity, materialSpecularColor, materialAnisotropy, materialIOR, materialTransmission, materialThickness, materialAttenuationDistance, materialAttenuationColor, materialDispersion } from '../accessors/MaterialNode.js';
 import { float, vec2, vec3, If } from '../shadernode/ShaderNode.js';
@@ -197,15 +196,17 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial {
 
 	}
 
-	setupNormal( builder ) {
+	setupClearcoatNormal() {
 
-		super.setupNormal( builder );
+		return this.clearcoatNormalNode ? vec3( this.clearcoatNormalNode ) : materialClearcoatNormal;
 
-		// CLEARCOAT NORMAL
+	}
+
+	setup( builder ) {
 
-		const clearcoatNormalNode = this.clearcoatNormalNode ? vec3( this.clearcoatNormalNode ) : materialClearcoatNormal;
+		builder.context.setupClearcoatNormal = () => this.setupClearcoatNormal( builder );
 
-		transformedClearcoatNormalView.assign( clearcoatNormalNode );
+		super.setup( builder );
 
 	}
 

+ 5 - 22
src/nodes/materials/NodeMaterial.js

@@ -6,11 +6,11 @@ import { attribute } from '../core/AttributeNode.js';
 import { output, diffuseColor, emissive, varyingProperty } from '../core/PropertyNode.js';
 import { materialAlphaTest, materialColor, materialOpacity, materialEmissive, materialNormal, materialLightMap, materialAOMap } from '../accessors/MaterialNode.js';
 import { modelViewProjection } from '../accessors/ModelViewProjectionNode.js';
-import { transformedNormalView, normalLocal } from '../accessors/NormalNode.js';
+import { normalLocal } from '../accessors/NormalNode.js';
 import { instance } from '../accessors/InstanceNode.js';
 import { batch } from '../accessors/BatchNode.js';
 import { materialReference } from '../accessors/MaterialReferenceNode.js';
-import { positionLocal, positionView } from '../accessors/PositionNode.js';
+import { positionLocal } from '../accessors/PositionNode.js';
 import { skinningReference } from '../accessors/SkinningNode.js';
 import { morphReference } from '../accessors/MorphNode.js';
 import { lightsNode } from '../lighting/LightsNode.js';
@@ -22,7 +22,6 @@ import IrradianceNode from '../lighting/IrradianceNode.js';
 import { depth } from '../display/ViewportDepthNode.js';
 import { cameraLogDepth } from '../accessors/CameraNode.js';
 import { clipping, clippingAlpha } from '../accessors/ClippingNode.js';
-import { faceDirection } from '../display/FrontFacingNode.js';
 
 const NodeMaterials = new Map();
 
@@ -40,7 +39,6 @@ class NodeMaterial extends Material {
 
 		this.fog = true;
 		this.lights = false;
-		this.normals = true;
 
 		this.lightsNode = null;
 		this.envNode = null;
@@ -81,6 +79,8 @@ class NodeMaterial extends Material {
 
 	setup( builder ) {
 
+		builder.context.setupNormal = () => this.setupNormal( builder );
+
 		// < VERTEX STAGE >
 
 		builder.addStack();
@@ -101,8 +101,6 @@ class NodeMaterial extends Material {
 
 		if ( this.fragmentNode === null ) {
 
-			if ( this.normals === true ) this.setupNormal( builder );
-
 			this.setupDiffuseColor( builder );
 			this.setupVariants( builder );
 
@@ -345,7 +343,6 @@ class NodeMaterial extends Material {
 
 	}
 
-
 	setupOutgoingLight() {
 
 		return ( this.lights === true ) ? vec3( 0 ) : diffuseColor.rgb;
@@ -354,21 +351,7 @@ class NodeMaterial extends Material {
 
 	setupNormal() {
 
-		// NORMAL VIEW
-
-		if ( this.flatShading === true ) {
-
-			const normalNode = positionView.dFdx().cross( positionView.dFdy() ).normalize();
-
-			transformedNormalView.assign( normalNode.mul( faceDirection ) );
-
-		} else {
-
-			const normalNode = this.normalNode ? vec3( this.normalNode ) : materialNormal;
-
-			transformedNormalView.assign( normalNode.mul( faceDirection ) );
-
-		}
+		return this.normalNode ? vec3( this.normalNode ) : materialNormal;
 
 	}
 

+ 0 - 1
src/nodes/materials/PointsNodeMaterial.js

@@ -13,7 +13,6 @@ class PointsNodeMaterial extends NodeMaterial {
 		this.isPointsNodeMaterial = true;
 
 		this.lights = false;
-		this.normals = false;
 		this.transparent = true;
 
 		this.sizeNode = null;

+ 0 - 1
src/nodes/materials/SpriteNodeMaterial.js

@@ -19,7 +19,6 @@ class SpriteNodeMaterial extends NodeMaterial {
 		this.isSpriteNodeMaterial = true;
 
 		this.lights = false;
-		this.normals = false;
 
 		this.positionNode = null;
 		this.rotationNode = null;

+ 0 - 1
src/nodes/materials/VolumeNodeMaterial.js

@@ -16,7 +16,6 @@ class VolumeNodeMaterial extends NodeMaterial {
 
 		super();
 
-		this.normals = false;
 		this.lights = false;
 		this.isVolumeNodeMaterial = true;
 		this.testNode = null;

粤ICP备19079148号