Jelajahi Sumber

TSL: Introduce `builtinAOContext` and Enhance AO Post-Processing Example (#32378)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: sunag <sunagbrasil@gmail.com>
Kirill Osipov 7 bulan lalu
induk
melakukan
ca69e6c7f1

+ 9 - 8
examples/webgpu_postprocessing_ao.html

@@ -36,7 +36,7 @@
 		<script type="module">
 
 			import * as THREE from 'three/webgpu';
-			import { sample, pass, mrt, context, screenUV, normalView, velocity, vec3, vec4, directionToColor, colorToDirection, colorSpaceToWorking } from 'three/tsl';
+			import { sample, pass, mrt, screenUV, normalView, velocity, vec3, vec4, directionToColor, colorToDirection, colorSpaceToWorking, builtinAOContext } from 'three/tsl';
 			import { ao } from 'three/addons/tsl/display/GTAONode.js';
 			import { traa } from 'three/addons/tsl/display/TRAANode.js';
 
@@ -49,7 +49,7 @@
 
 			let camera, scene, renderer, postProcessing, controls;
 
-			let aoPass, traaPass;
+			let aoPass, traaPass, transparentMesh;
 
 			const params = {
 				samples: 16,
@@ -58,7 +58,8 @@
 				radius: 0.25,
 				scale: 1,
 				thickness: 1,
-				aoOnly: false
+				aoOnly: false,
+				transparentOpacity: 0.3
 			};
 
 			init();
@@ -142,9 +143,7 @@
 
 				// scene context
 
-				scenePass.contextNode = context( {
-					ao: aoPassOutput.sample( screenUV ).r
-				} );
+				scenePass.contextNode = builtinAOContext( aoPassOutput.sample( screenUV ).r );
 
 				// final output + traa
 
@@ -170,8 +169,7 @@
 
 				//
 
-				const transparentMesh = new THREE.Mesh( new THREE.PlaneGeometry( 1.8, 2 ), new THREE.MeshStandardNodeMaterial( { transparent: true, opacity: .1 } ) );
-				transparentMesh.material.transparent = true;
+				transparentMesh = new THREE.Mesh( new THREE.PlaneGeometry( 1.8, 2 ), new THREE.MeshStandardNodeMaterial( { transparent: true, opacity: params.transparentOpacity } ) );
 				transparentMesh.position.z = 0;
 				transparentMesh.position.y = 0.5;
 				transparentMesh.visible = false;
@@ -192,6 +190,7 @@
 				gui.add( params, 'thickness', 0.01, 2 ).onChange( updateParameters );
 				gui.add( aoPass, 'useTemporalFiltering' ).name( 'temporal filtering' );
 				gui.add( transparentMesh, 'visible' ).name( 'show transparent mesh' );
+				gui.add( params, 'transparentOpacity', 0, 1, 0.01 ).name( 'transparent opacity' ).onChange( updateParameters );
 				gui.add( params, 'aoOnly' ).onChange( ( value ) => {
 
 					if ( value === true ) {
@@ -220,6 +219,8 @@
 				aoPass.scale.value = params.scale;
 				aoPass.thickness.value = params.thickness;
 
+				transparentMesh.material.opacity = params.transparentOpacity;
+
 			}
 
 			function onWindowResize() {

+ 1 - 0
src/Three.TSL.js

@@ -100,6 +100,7 @@ export const bufferAttribute = TSL.bufferAttribute;
 export const bumpMap = TSL.bumpMap;
 export const burn = TSL.burn;
 export const builtin = TSL.builtin;
+export const builtinAOContext = TSL.builtinAOContext;
 export const builtinShadowContext = TSL.builtinShadowContext;
 export const bvec2 = TSL.bvec2;
 export const bvec3 = TSL.bvec3;

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

@@ -1060,17 +1060,21 @@ class NodeMaterial extends Material {
 
 		}
 
-		let aoNode = builder.context.ao || null;
+		let aoNode = this.aoNode;
 
-		if ( this.aoNode !== null || builder.material.aoMap ) {
+		if ( aoNode === null && builder.material.aoMap ) {
 
-			const mtlAO = this.aoNode !== null ? this.aoNode : materialAO;
+			aoNode = materialAO;
 
-			aoNode = aoNode !== null ? aoNode.mul( mtlAO ) : mtlAO;
+		}
+
+		if ( builder.context.getAO ) {
+
+			aoNode = builder.context.getAO( aoNode, builder );
 
 		}
 
-		if ( aoNode !== null ) {
+		if ( aoNode ) {
 
 			materialLightsNode.push( new AONode( aoNode ) );
 

+ 1 - 1
src/materials/nodes/manager/NodeMaterialObserver.js

@@ -259,7 +259,7 @@ class NodeMaterialObserver {
 
 		}
 
-		if ( builder.context.modelViewMatrix || builder.context.modelNormalViewMatrix || builder.context.ao || builder.context.getShadow )
+		if ( builder.context.modelViewMatrix || builder.context.modelNormalViewMatrix || builder.context.getAO || builder.context.getShadow )
 			return true;
 
 		return false;

+ 26 - 0
src/nodes/core/ContextNode.js

@@ -232,6 +232,31 @@ export function builtinShadowContext( shadowNode, light, node = null ) {
 
 }
 
+/**
+ * TSL function for defining a built-in ambient occlusion context for a given node.
+ *
+ * @tsl
+ * @function
+ * @param {Node} aoNode - The ambient occlusion value node to apply.
+ * @param {Node} [node=null] - The node whose context should be modified.
+ * @returns {ContextNode}
+ */
+export function builtinAOContext( aoNode, node = null ) {
+
+	return context( node, {
+
+		getAO: ( inputNode, { material } ) => {
+
+			if ( material.transparent === true ) return inputNode;
+
+			return inputNode !== null ? inputNode.mul( aoNode ) : aoNode;
+
+		}
+
+	} );
+
+}
+
 /**
  * TSL function for defining a label context value for a given node.
  *
@@ -255,3 +280,4 @@ addMethodChaining( 'label', label );
 addMethodChaining( 'uniformFlow', uniformFlow );
 addMethodChaining( 'setName', setName );
 addMethodChaining( 'builtinShadowContext', ( node, shadowNode, light ) => builtinShadowContext( shadowNode, light, node ) );
+addMethodChaining( 'builtinAOContext', ( node, aoValue ) => builtinAOContext( aoValue, node ) );

粤ICP备19079148号