Răsfoiți Sursa

TSL: Add output and material.outputNode (#26419)

* TSL: Add output and material.outputNode

* Move output assign to constructOutput()
sunag 2 ani în urmă
părinte
comite
986e89816f

+ 1 - 1
examples/jsm/nodes/Nodes.js

@@ -24,7 +24,7 @@ export { default as NodeKeywords } from './core/NodeKeywords.js';
 export { default as NodeUniform } from './core/NodeUniform.js';
 export { default as NodeVar } from './core/NodeVar.js';
 export { default as NodeVarying } from './core/NodeVarying.js';
-export { default as PropertyNode, property, diffuseColor, roughness, metalness, specularColor, shininess } from './core/PropertyNode.js';
+export { default as PropertyNode, property, output, diffuseColor, roughness, metalness, specularColor, shininess } from './core/PropertyNode.js';
 export { default as StackNode, stack } from './core/StackNode.js';
 export { default as TempNode } from './core/TempNode.js';
 export { default as UniformNode, uniform } from './core/UniformNode.js';

+ 1 - 0
examples/jsm/nodes/core/PropertyNode.js

@@ -53,5 +53,6 @@ export const sheen = nodeImmutable( PropertyNode, 'vec3', 'Sheen' );
 export const sheenRoughness = nodeImmutable( PropertyNode, 'float', 'SheenRoughness' );
 export const specularColor = nodeImmutable( PropertyNode, 'color', 'SpecularColor' );
 export const shininess = nodeImmutable( PropertyNode, 'float', 'Shininess' );
+export const output = nodeImmutable( PropertyNode, 'vec4', 'Output' );
 
 addNodeClass( PropertyNode );

+ 13 - 3
examples/jsm/nodes/materials/NodeMaterial.js

@@ -1,7 +1,7 @@
 import { Material, ShaderMaterial, NoColorSpace } from 'three';
 import { getNodeChildren, getCacheKey } from '../core/NodeUtils.js';
 import { attribute } from '../core/AttributeNode.js';
-import { diffuseColor } from '../core/PropertyNode.js';
+import { output, diffuseColor } from '../core/PropertyNode.js';
 import { materialNormal } from '../accessors/ExtendedMaterialNode.js';
 import { materialAlphaTest, materialColor, materialOpacity, materialEmissive } from '../accessors/MaterialNode.js';
 import { modelViewProjection } from '../accessors/ModelViewProjectionNode.js';
@@ -76,6 +76,8 @@ class NodeMaterial extends ShaderMaterial {
 
 		builder.addStack();
 
+		let outputNode;
+
 		if ( this.isUnlit === false ) {
 
 			if ( this.normals === true ) this.constructNormal( builder );
@@ -85,14 +87,18 @@ class NodeMaterial extends ShaderMaterial {
 
 			const outgoingLightNode = this.constructLighting( builder );
 
-			builder.stack.outputNode = this.constructOutput( builder, vec4( outgoingLightNode, diffuseColor.a ) );
+			outputNode = this.constructOutput( builder, vec4( outgoingLightNode, diffuseColor.a ) );
+
+			if ( this.outputNode !== null ) outputNode = this.outputNode;
 
 		} else {
 
-			builder.stack.outputNode = this.constructOutput( builder, this.outputNode || vec4( 0, 0, 0, 1 ) );
+			outputNode = this.constructOutput( builder, this.outputNode || vec4( 0, 0, 0, 1 ) );
 
 		}
 
+		builder.stack.outputNode = outputNode;
+
 		builder.addFlow( 'fragment', builder.removeStack() );
 
 	}
@@ -330,6 +336,10 @@ class NodeMaterial extends ShaderMaterial {
 
 		if ( fogNode ) outputNode = vec4( fogNode.mixAssign( outputNode.rgb ), outputNode.a );
 
+		// OUTPUT NODE
+
+		builder.stack.assign( output, outputNode );
+
 		return outputNode;
 
 	}

+ 8 - 1
examples/webgpu_backdrop.html

@@ -27,7 +27,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { float, vec3, color, toneMapping, viewportSharedTexture, viewportTopLeft, checker, uv, oscSine, MeshStandardNodeMaterial } from 'three/nodes';
+			import { float, vec3, color, toneMapping, viewportSharedTexture, viewportTopLeft, checker, uv, timerLocal, oscSine, output, MeshStandardNodeMaterial } from 'three/nodes';
 
 			import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
 
@@ -74,6 +74,13 @@
 					const object = gltf.scene;
 					mixer = new THREE.AnimationMixer( object );
 
+					const material = object.children[ 0 ].children[ 0 ].material;
+
+					// output material effect ( better using hsv )
+					// ignore output.sRGBToLinear().linearTosRGB() for now
+
+					material.outputNode = oscSine( timerLocal( .1 ) ).mix( output, output.add( .1 ).posterize( 4 ).mul( 2 ) );
+
 					const action = mixer.clipAction( gltf.animations[ 0 ] );
 					action.play();