Skip to content

Commit

Permalink
PostProcessingUtils: Add getScreenPosition(). (#29599)
Browse files Browse the repository at this point in the history
* PostProcessingUtils: Add `getScreenPosition()`.

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

---------
  • Loading branch information
Mugen87 authored Oct 9, 2024
1 parent 1d91b42 commit e6e4398
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 37 deletions.
46 changes: 19 additions & 27 deletions examples/jsm/tsl/display/GTAONode.js
Original file line number Diff line number Diff line change
@@ -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();
Expand Down Expand Up @@ -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;

Expand All @@ -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 } ) => {
Expand All @@ -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 ), () => {

Expand All @@ -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 ), () => {

Expand All @@ -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 ) ) ) );
Expand Down
12 changes: 2 additions & 10 deletions examples/jsm/tsl/display/SSRNode.js
Original file line number Diff line number Diff line change
@@ -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();
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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

Expand Down
25 changes: 25 additions & 0 deletions src/nodes/utils/PostProcessingUtils.js
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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() );

} );

0 comments on commit e6e4398

Please sign in to comment.