Skip to content

Commit b140fba

Browse files
authored
TSL: Move Interleaved Gradient Noise into PostProcessingUtils. (#32074)
* TSL: Move Interleaved Gradient Noise into `PostProcessingUtils`. * Update PostProcessingUtils.js
1 parent 62e6f43 commit b140fba

File tree

4 files changed

+33
-33
lines changed

4 files changed

+33
-33
lines changed

examples/jsm/tsl/display/SSGINode.js

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { RenderTarget, Vector2, TempNode, QuadMesh, NodeMaterial, RendererUtils, MathUtils } from 'three/webgpu';
2-
import { clamp, normalize, reference, nodeObject, Fn, NodeUpdateType, uniform, vec4, passTexture, uv, logarithmicDepthToViewZ, viewZToPerspectiveDepth, getViewPosition, screenCoordinate, float, sub, fract, dot, vec2, rand, vec3, Loop, mul, PI, cos, sin, uint, cross, acos, sign, pow, luminance, If, max, abs, Break, sqrt, HALF_PI, div, ceil, shiftRight, convertToTexture, bool, getNormalFromDepth } from 'three/tsl';
2+
import { clamp, normalize, reference, nodeObject, Fn, NodeUpdateType, uniform, vec4, passTexture, uv, logarithmicDepthToViewZ, viewZToPerspectiveDepth, getViewPosition, screenCoordinate, float, sub, fract, dot, vec2, rand, vec3, Loop, mul, PI, cos, sin, uint, cross, acos, sign, pow, luminance, If, max, abs, Break, sqrt, HALF_PI, div, ceil, shiftRight, convertToTexture, bool, getNormalFromDepth, interleavedGradientNoise } from 'three/tsl';
33

44
const _quadMesh = /*@__PURE__*/ new QuadMesh();
55
const _size = /*@__PURE__*/ new Vector2();
@@ -413,20 +413,6 @@ class SSGINode extends TempNode {
413413
]
414414
} );
415415

416-
// Interleaved gradient function from Jimenez 2014 http://goo.gl/eomGso
417-
418-
const gradientNoise = Fn( ( [ position ] ) => {
419-
420-
return fract( float( 52.9829189 ).mul( fract( dot( position, vec2( 0.06711056, 0.00583715 ) ) ) ) );
421-
422-
} ).setLayout( {
423-
name: 'gradientNoise',
424-
type: 'float',
425-
inputs: [
426-
{ name: 'position', type: 'vec2' }
427-
]
428-
} );
429-
430416
const GTAOFastAcos = Fn( ( [ value ] ) => {
431417

432418
const outVal = abs( value ).mul( float( - 0.156583 ) ).add( HALF_PI );
@@ -576,7 +562,7 @@ class SSGINode extends TempNode {
576562
//
577563

578564
const noiseOffset = spatialOffsets( screenCoordinate );
579-
const noiseDirection = gradientNoise( screenCoordinate );
565+
const noiseDirection = interleavedGradientNoise( screenCoordinate );
580566
const noiseJitterIdx = this._temporalDirection.mul( 0.02 ); // Port: Add noiseJitterIdx here for slightly better noise convergence with TRAA (see #31890 for more details)
581567
const initialRayStep = fract( noiseOffset.add( this._temporalOffset ) ).add( rand( uvNode.add( noiseJitterIdx ).mul( 2 ).sub( 1 ) ) );
582568

examples/jsm/tsl/display/SSSNode.js

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { RedFormat, RenderTarget, Vector2, RendererUtils, QuadMesh, TempNode, NodeMaterial, NodeUpdateType, UnsignedByteType } from 'three/webgpu';
2-
import { reference, viewZToPerspectiveDepth, logarithmicDepthToViewZ, getScreenPosition, getViewPosition, float, Break, Loop, int, max, abs, If, dot, screenCoordinate, nodeObject, Fn, passTexture, uv, uniform, perspectiveDepthToViewZ, orthographicDepthToViewZ, vec2, lightPosition, lightTargetPosition, fract, rand, mix } from 'three/tsl';
2+
import { reference, viewZToPerspectiveDepth, logarithmicDepthToViewZ, getScreenPosition, getViewPosition, float, Break, Loop, int, max, abs, If, interleavedGradientNoise, screenCoordinate, nodeObject, Fn, passTexture, uv, uniform, perspectiveDepthToViewZ, orthographicDepthToViewZ, vec2, lightPosition, lightTargetPosition, fract, rand, mix } from 'three/tsl';
33

44
const _quadMesh = /*@__PURE__*/ new QuadMesh();
55
const _size = /*@__PURE__*/ new Vector2();
@@ -371,20 +371,6 @@ class SSSNode extends TempNode {
371371

372372
};
373373

374-
// Interleaved gradient function from Jimenez 2014 http://goo.gl/eomGso
375-
376-
const gradientNoise = Fn( ( [ position ] ) => {
377-
378-
return fract( float( 52.9829189 ).mul( fract( dot( position, vec2( 0.06711056, 0.00583715 ) ) ) ) );
379-
380-
} ).setLayout( {
381-
name: 'gradientNoise',
382-
type: 'float',
383-
inputs: [
384-
{ name: 'position', type: 'vec2' }
385-
]
386-
} );
387-
388374
const sss = Fn( () => {
389375

390376
const depth = sampleDepth( uvNode ).toVar();
@@ -419,7 +405,7 @@ class SSSNode extends TempNode {
419405
const ySpan = yLen.div( totalStep ).toVar();
420406

421407
// compute noise based ray offset
422-
const noise = gradientNoise( screenCoordinate );
408+
const noise = interleavedGradientNoise( screenCoordinate );
423409
const offset = fract( noise.add( this._temporalOffset ) ).add( rand( uvNode.add( this._frameId ) ) ).toConst( 'offset' );
424410

425411
const occlusion = float( 0 ).toVar();

src/Three.TSL.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ export const getDirection = TSL.getDirection;
198198
export const getDistanceAttenuation = TSL.getDistanceAttenuation;
199199
export const getGeometryRoughness = TSL.getGeometryRoughness;
200200
export const getNormalFromDepth = TSL.getNormalFromDepth;
201+
export const interleavedGradientNoise = TSL.interleavedGradientNoise;
201202
export const getParallaxCorrectNormal = TSL.getParallaxCorrectNormal;
202203
export const getRoughness = TSL.getRoughness;
203204
export const getScreenPosition = TSL.getScreenPosition;

src/nodes/utils/PostProcessingUtils.js

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { abs, cross, float, Fn, normalize, ivec2, sub, vec2, vec3, vec4 } from '../tsl/TSLBase.js';
1+
import { abs, cross, float, Fn, normalize, ivec2, sub, vec2, vec3, vec4, fract, dot } from '../tsl/TSLBase.js';
22
import { textureSize } from '../accessors/TextureSizeNode.js';
33
import { textureLoad } from '../accessors/TextureNode.js';
44
import { WebGPUCoordinateSystem } from '../../constants.js';
@@ -93,3 +93,30 @@ export const getNormalFromDepth = /*@__PURE__*/ Fn( ( [ uv, depthTexture, projec
9393
return normalize( cross( dpdx, dpdy ) );
9494

9595
} );
96+
97+
/**
98+
* Interleaved Gradient Noise (IGN) from Jimenez 2014.
99+
*
100+
* IGN has "low discrepancy" resulting in evenly distributed samples. It's superior compared to
101+
* default white noise, blue noise or Bayer.
102+
*
103+
* References:
104+
* - {@link https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare/}
105+
* - {@link https://blog.demofox.org/2022/01/01/interleaved-gradient-noise-a-different-kind-of-low-discrepancy-sequence/}
106+
*
107+
* @tsl
108+
* @function
109+
* @param {Node<vec2>} position - The input position, usually screen coordinates.
110+
* @return {Node<float>} The noise value.
111+
*/
112+
export const interleavedGradientNoise = Fn( ( [ position ] ) => {
113+
114+
return fract( float( 52.9829189 ).mul( fract( dot( position, vec2( 0.06711056, 0.00583715 ) ) ) ) );
115+
116+
} ).setLayout( {
117+
name: 'interleavedGradientNoise',
118+
type: 'float',
119+
inputs: [
120+
{ name: 'position', type: 'vec2' }
121+
]
122+
} );

0 commit comments

Comments
 (0)