Преглед изворни кода

PostProcessingUtils: Add `getScreenPosition()`. (#29599)

* PostProcessingUtils: Add `getScreenPosition()`.

* renamed types: `matrix4` -> `mat4`

---------
Michael Herzog пре 1 година
родитељ
комит
e6e4398a34

+ 19 - 27
examples/jsm/tsl/display/GTAONode.js

@@ -1,5 +1,5 @@
 import { DataTexture, RenderTarget, RepeatWrapping, Vector2, Vector3, PostProcessingUtils } from 'three';
-import { getViewPosition, QuadMesh, TempNode, nodeObject, Fn, float, NodeUpdateType, uv, uniform, Loop, vec2, vec3, vec4, int, dot, max, pow, abs, If, textureSize, sin, cos, PI, texture, passTexture, mat3, add, normalize, mul, cross, div, mix, sqrt, sub, acos, clamp, NodeMaterial } from 'three/tsl';
+import { getScreenPosition, getViewPosition, QuadMesh, TempNode, nodeObject, Fn, float, NodeUpdateType, uv, uniform, Loop, vec2, vec3, vec4, int, dot, max, pow, abs, If, textureSize, sin, cos, PI, texture, passTexture, mat3, add, normalize, mul, cross, div, mix, sqrt, sub, acos, clamp, NodeMaterial } from 'three/tsl';
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
@@ -92,24 +92,14 @@ class GTAONode extends TempNode {
 		const sampleDepth = ( uv ) => this.depthNode.uv( uv ).x;
 		const sampleNoise = ( uv ) => this.noiseNode.uv( uv );
 
-		const getSceneUvAndDepth = Fn( ( [ sampleViewPos ] )=> {
-
-			const sampleClipPos = this.cameraProjectionMatrix.mul( vec4( sampleViewPos, 1.0 ) );
-			let sampleUv = sampleClipPos.xy.div( sampleClipPos.w ).mul( 0.5 ).add( 0.5 ).toVar();
-			sampleUv = vec2( sampleUv.x, sampleUv.y.oneMinus() );
-			const sampleSceneDepth = sampleDepth( sampleUv );
-			return vec3( sampleUv, sampleSceneDepth );
-
-		} );
-
 		const ao = Fn( () => {
 
-			const depth = sampleDepth( uvNode );
+			const depth = sampleDepth( uvNode ).toVar();
 
 			depth.greaterThanEqual( 1.0 ).discard();
 
-			const viewPosition = getViewPosition( uvNode, depth, this.cameraProjectionMatrixInverse );
-			const viewNormal = this.normalNode.rgb.normalize();
+			const viewPosition = getViewPosition( uvNode, depth, this.cameraProjectionMatrixInverse ).toVar();
+			const viewNormal = this.normalNode.rgb.normalize().toVar();
 
 			const radiusToUse = this.radius;
 
@@ -122,23 +112,23 @@ class GTAONode extends TempNode {
 			const bitangent = vec3( tangent.y.mul( - 1.0 ), tangent.x, 0.0 );
 			const kernelMatrix = mat3( tangent, bitangent, vec3( 0.0, 0.0, 1.0 ) );
 
-			const DIRECTIONS = this.SAMPLES.lessThan( 30 ).select( 3, 5 );
-			const STEPS = add( this.SAMPLES, DIRECTIONS.sub( 1 ) ).div( DIRECTIONS );
+			const DIRECTIONS = this.SAMPLES.lessThan( 30 ).select( 3, 5 ).toVar();
+			const STEPS = add( this.SAMPLES, DIRECTIONS.sub( 1 ) ).div( DIRECTIONS ).toVar();
 
 			const ao = float( 0 ).toVar();
 
 			Loop( { start: int( 0 ), end: DIRECTIONS, type: 'int', condition: '<' }, ( { i } ) => {
 
-				const angle = float( i ).div( float( DIRECTIONS ) ).mul( PI );
+				const angle = float( i ).div( float( DIRECTIONS ) ).mul( PI ).toVar();
 				const sampleDir = vec4( cos( angle ), sin( angle ), 0., add( 0.5, mul( 0.5, noiseTexel.w ) ) );
 				sampleDir.xyz = normalize( kernelMatrix.mul( sampleDir.xyz ) );
 
-				const viewDir = normalize( viewPosition.xyz.negate() );
-				const sliceBitangent = normalize( cross( sampleDir.xyz, viewDir ) );
+				const viewDir = normalize( viewPosition.xyz.negate() ).toVar();
+				const sliceBitangent = normalize( cross( sampleDir.xyz, viewDir ) ).toVar();
 				const sliceTangent = cross( sliceBitangent, viewDir );
 				const normalInSlice = normalize( viewNormal.sub( sliceBitangent.mul( dot( viewNormal, sliceBitangent ) ) ) );
 
-				const tangentToNormalInSlice = cross( normalInSlice, sliceBitangent );
+				const tangentToNormalInSlice = cross( normalInSlice, sliceBitangent ).toVar();
 				const cosHorizons = vec2( dot( viewDir, tangentToNormalInSlice ), dot( viewDir, tangentToNormalInSlice.negate() ) ).toVar();
 
 				Loop( { end: STEPS, type: 'int', name: 'j', condition: '<' }, ( { j } ) => {
@@ -147,9 +137,10 @@ class GTAONode extends TempNode {
 
 					// x
 
-					const sampleSceneUvDepthX = getSceneUvAndDepth( viewPosition.add( sampleViewOffset ) );
-					const sampleSceneViewPositionX = getViewPosition( sampleSceneUvDepthX.xy, sampleSceneUvDepthX.z, this.cameraProjectionMatrixInverse );
-					const viewDeltaX = sampleSceneViewPositionX.sub( viewPosition );
+					const sampleScreenPositionX = getScreenPosition( viewPosition.add( sampleViewOffset ), this.cameraProjectionMatrix ).toVar();
+					const sampleDepthX = sampleDepth( sampleScreenPositionX ).toVar();
+					const sampleSceneViewPositionX = getViewPosition( sampleScreenPositionX, sampleDepthX, this.cameraProjectionMatrixInverse ).toVar();
+					const viewDeltaX = sampleSceneViewPositionX.sub( viewPosition ).toVar();
 
 					If( abs( viewDeltaX.z ).lessThan( this.thickness ), () => {
 
@@ -160,9 +151,10 @@ class GTAONode extends TempNode {
 
 					// y
 
-					const sampleSceneUvDepthY = getSceneUvAndDepth( viewPosition.sub( sampleViewOffset ) );
-					const sampleSceneViewPositionY = getViewPosition( sampleSceneUvDepthY.xy, sampleSceneUvDepthY.z, this.cameraProjectionMatrixInverse );
-					const viewDeltaY = sampleSceneViewPositionY.sub( viewPosition );
+					const sampleScreenPositionY = getScreenPosition( viewPosition.sub( sampleViewOffset ), this.cameraProjectionMatrix ).toVar();
+					const sampleDepthY = sampleDepth( sampleScreenPositionY ).toVar();
+					const sampleSceneViewPositionY = getViewPosition( sampleScreenPositionY, sampleDepthY, this.cameraProjectionMatrixInverse ).toVar();
+					const viewDeltaY = sampleSceneViewPositionY.sub( viewPosition ).toVar();
 
 					If( abs( viewDeltaY.z ).lessThan( this.thickness ), () => {
 
@@ -173,7 +165,7 @@ class GTAONode extends TempNode {
 
 				} );
 
-				const sinHorizons = sqrt( sub( 1.0, cosHorizons.mul( cosHorizons ) ) );
+				const sinHorizons = sqrt( sub( 1.0, cosHorizons.mul( cosHorizons ) ) ).toVar();
 				const nx = dot( normalInSlice, sliceTangent );
 				const ny = dot( normalInSlice, viewDir );
 				const nxb = mul( 0.5, acos( cosHorizons.y ).sub( acos( cosHorizons.x ) ).add( sinHorizons.x.mul( cosHorizons.x ).sub( sinHorizons.y.mul( cosHorizons.y ) ) ) );

+ 2 - 10
examples/jsm/tsl/display/SSRNode.js

@@ -1,5 +1,5 @@
 import { NearestFilter, RenderTarget, Vector2, PostProcessingUtils } from 'three';
-import { getViewPosition, sqrt, mul, div, cross, float, Continue, Break, Loop, int, max, abs, sub, If, dot, reflect, normalize, screenCoordinate, QuadMesh, TempNode, nodeObject, Fn, NodeUpdateType, passTexture, NodeMaterial, uv, uniform, perspectiveDepthToViewZ, orthographicDepthToViewZ, vec2, vec3, vec4 } from 'three/tsl';
+import { getScreenPosition, getViewPosition, sqrt, mul, div, cross, float, Continue, Break, Loop, int, max, abs, sub, If, dot, reflect, normalize, screenCoordinate, QuadMesh, TempNode, nodeObject, Fn, NodeUpdateType, passTexture, NodeMaterial, uv, uniform, perspectiveDepthToViewZ, orthographicDepthToViewZ, vec2, vec3, vec4 } from 'three/tsl';
 
 const _quadMesh = /*@__PURE__*/ new QuadMesh();
 const _size = /*@__PURE__*/ new Vector2();
@@ -151,14 +151,6 @@ class SSRNode extends TempNode {
 
 		} );
 
-		const viewPositionToSceneUv = Fn( ( [ sampleViewPos ] )=> {
-
-			const sampleClipPos = this._cameraProjectionMatrix.mul( vec4( sampleViewPos, 1.0 ) );
-			const sampleUv = sampleClipPos.xy.div( sampleClipPos.w ).mul( 0.5 ).add( 0.5 ).toVar();
-			return vec2( sampleUv.x, sampleUv.y.oneMinus() );
-
-		} );
-
 		const ssr = Fn( () => {
 
 			const metalness = this.metalnessNode.uv( uvNode ).r;
@@ -195,7 +187,7 @@ class SSRNode extends TempNode {
 
 			// d0 and d1 are the start and maximum points of the reflection ray in screen space
 			const d0 = screenCoordinate.xy.toVar();
-			const d1 = viewPositionToSceneUv( d1viewPosition ).mul( this._resolution ).toVar();
+			const d1 = getScreenPosition( d1viewPosition, this._cameraProjectionMatrix ).mul( this._resolution ).toVar();
 
 			// below variables are used to control the raymarching process
 

+ 25 - 0
src/nodes/utils/PostProcessingUtils.js

@@ -1,6 +1,15 @@
 import { Fn, vec2, vec3, vec4 } from '../tsl/TSLBase.js';
 import { WebGPUCoordinateSystem } from '../../constants.js';
 
+/**
+* Computes a position in view space based on a fragment's screen position expressed as uv coordinates, the fragments
+* depth value and the camera's inverse projection matrix.
+*
+* @param {vec2} screenPosition - The fragment's screen position expressed as uv coordinates.
+* @param {float} depth - The fragment's depth value.
+* @param {mat4} projectionMatrixInverse - The camera's inverse projection matrix.
+* @return {vec3} The fragments position in view space.
+*/
 export const getViewPosition = /*@__PURE__*/ Fn( ( [ screenPosition, depth, projectionMatrixInverse ], builder ) => {
 
 	let clipSpacePosition;
@@ -21,3 +30,19 @@ export const getViewPosition = /*@__PURE__*/ Fn( ( [ screenPosition, depth, proj
 	return viewSpacePosition.xyz.div( viewSpacePosition.w );
 
 } );
+
+/**
+* Computes a screen position expressed as uv coordinates based on a fragment's position in view space
+* and the camera's projection matrix
+*
+* @param {vec3} viewPosition - The fragments position in view space.
+* @param {mat4} projectionMatrix - The camera's projection matrix.
+* @return {vec2} Teh fragment's screen position expressed as uv coordinates.
+*/
+export const getScreenPosition = /*@__PURE__*/ Fn( ( [ viewPosition, projectionMatrix ] ) => {
+
+	const sampleClipPos = projectionMatrix.mul( vec4( viewPosition, 1.0 ) );
+	const sampleUv = sampleClipPos.xy.div( sampleClipPos.w ).mul( 0.5 ).add( 0.5 ).toVar();
+	return vec2( sampleUv.x, sampleUv.y.oneMinus() );
+
+} );

粤ICP备19079148号