Browse Source

WebGPURenderer: Add `shadowNode` to NodeMaterial - discard/opacity/color (#27625)

* add custom shadownode

* cleanup example

* update screenshot

* use node material instead

* shadow color and opacity

* update non-shadowNode materials

* updates

* Update webgpu_shadowmap.jpg

* update

---------

Co-authored-by: sunag <[email protected]>
Renaud Rohlinger 1 year ago
parent
commit
964d35d4ea

+ 5 - 2
examples/jsm/nodes/lighting/AnalyticLightNode.js

@@ -57,7 +57,8 @@ class AnalyticLightNode extends LightingNode {
 			if ( overrideMaterial === null ) {
 
 				overrideMaterial = builder.createNodeMaterial();
-				overrideMaterial.fragmentNode = vec4( 1 );
+				overrideMaterial.fragmentNode = vec4( 0, 0, 0, 1 );
+				overrideMaterial.isShadowNodeMaterial = true; // Use to avoid other overrideMaterial override material.fragmentNode unintentionally when using material.shadowNode
 
 			}
 
@@ -147,8 +148,10 @@ class AnalyticLightNode extends LightingNode {
 			*/
 			//
 
+			const shadowColor = texture( rtt.texture, shadowCoord );
+
 			this.rtt = rtt;
-			this.colorNode = this.colorNode.mul( frustumTest.mix( 1, shadowNode ) );
+			this.colorNode = this.colorNode.mul( frustumTest.mix( 1, shadowNode.mix( shadowColor.a.mix( 1, shadowColor ), 1 ) ) );
 
 			this.shadowNode = shadowNode;
 

+ 2 - 0
examples/jsm/nodes/materials/NodeMaterial.js

@@ -53,6 +53,7 @@ class NodeMaterial extends ShaderMaterial {
 		this.positionNode = null;
 
 		this.depthNode = null;
+		this.shadowNode = null;
 
 		this.outputNode = null;
 
@@ -496,6 +497,7 @@ class NodeMaterial extends ShaderMaterial {
 		this.positionNode = source.positionNode;
 
 		this.depthNode = source.depthNode;
+		this.shadowNode = source.shadowNode;
 
 		this.outputNode = source.outputNode;
 

+ 14 - 0
examples/jsm/renderers/common/Renderer.js

@@ -1085,6 +1085,7 @@ class Renderer {
 	renderObject( object, scene, camera, geometry, material, group, lightsNode ) {
 
 		let overridePositionNode;
+		let overrideFragmentNode;
 
 		//
 
@@ -1106,6 +1107,13 @@ class Renderer {
 
 			}
 
+			if ( overrideMaterial.isShadowNodeMaterial && ( material.shadowNode && material.shadowNode.isNode ) ) {
+
+				overrideFragmentNode = overrideMaterial.fragmentNode;
+				overrideMaterial.fragmentNode = material.shadowNode;
+
+			}
+
 			material = overrideMaterial;
 
 		}
@@ -1136,6 +1144,12 @@ class Renderer {
 
 		}
 
+		if ( overrideFragmentNode !== undefined ) {
+
+			scene.overrideMaterial.fragmentNode = overrideFragmentNode;
+
+		}
+
 		//
 
 		object.onAfterRender( this, scene, camera, geometry, material, group );

BIN
examples/screenshots/webgpu_shadowmap.jpg


+ 27 - 4
examples/webgpu_shadowmap.html

@@ -31,7 +31,7 @@
 			import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-
+			import { vec4, tslFn, vertexIndex, MeshPhongNodeMaterial } from 'three/nodes';
 			let camera, scene, renderer, clock;
 			let dirLight, spotLight;
 			let torusKnot, dirGroup;
@@ -93,14 +93,37 @@
 
 				// geometry
 
-				const geometry = new THREE.TorusKnotGeometry( 25, 8, 75, 20 );
-				const material = new THREE.MeshPhongMaterial( {
+				const geometry = new THREE.TorusKnotGeometry( 25, 8, 75, 80 );
+				const material = new MeshPhongNodeMaterial( {
 					color: 0x999999,
 					shininess: 0,
 					specular: 0x222222
 				} );
 
-				torusKnot = new THREE.Mesh( geometry, material );
+				const materialCustomShadow = material.clone();
+				materialCustomShadow.transparent = true;
+
+				const materialColor = vec4( 1, 0, 1, .5 );
+			
+				const discardNode = vertexIndex.hash().greaterThan( 0.5 );
+
+				materialCustomShadow.colorNode = tslFn( () => {
+
+					discardNode.discard();
+
+					return materialColor;
+
+				} )();
+
+				materialCustomShadow.shadowNode = tslFn( () => {
+
+					discardNode.discard();
+
+					return materialColor;
+			
+				} )();
+
+				torusKnot = new THREE.Mesh( geometry, materialCustomShadow );
 				torusKnot.scale.multiplyScalar( 1 / 18 );
 				torusKnot.position.y = 3;
 				torusKnot.castShadow = true;