interleavedGradientNoise
Interleaved Gradient Noise (IGN) from Jimenez 2014. Takes a 2D position and returns a low‑discrepancy pseudo‑random value in [0,1), stable per position and ideal for dithering and sample jitter.
Core Advantages
Extremely cheap (dot + fract), evenly distributed, and artifact‑resistant. More suitable than white noise for banding removal and screen‑space dithering; deterministic for the same position.
Common Uses
Dither color gradients to remove 8‑bit banding
Stochastic alpha / alpha‑to‑coverage for softer cutout edges
Per‑pixel low‑discrepancy jitter for TAA / multi‑sampling
Randomize sample rotation or offsets in SSAO/SSR/volumetrics
Break up patterns in screen‑space blur and bloom
How to adjust
1) Coordinates: for resolution‑independent, pixel‑stable patterns pass integer pixel coordinates, e.g., floor(viewportCoordinate). Normalized UV will make the pattern resolution‑dependent. 2) Strength: control effect by scaling the noise amplitude where it is used, e.g., (IGN − 0.5) * (1/255). 3) Temporal change: add a seed like frameId or time, e.g., interleavedGradientNoise(floor(viewportCoordinate) + float(frameId)). 4) Domain: prefer screen‑space (viewportCoordinate) for dithering; use world or UV space if you need object‑space randomness.
Code Examples
1// Use case A: 8‑bit gradient dithering to reduce banding
2const pixel = floor( viewportCoordinate ); // integer pixel coords
3const ign = interleavedGradientNoise( pixel ); // [0,1)
4const dither = ign.sub( 0.5 ).mul( 1.0 / 255.0 ); // about one LSB
5
6const uvScreen = viewportCoordinate.div( viewportSize );
7const gradient = uvScreen.y; // vertical 0..1 gradient
8output.color = vec3( gradient.add( dither ) ).saturate();
9
10// Use case B: stochastic transparency to soften alpha‑test edges
11const baseAlpha = texture( map, uv() ).a.saturate();
12const n = interleavedGradientNoise( floor( viewportCoordinate ) );
13if ( n.greaterThan( baseAlpha ) ) { discard(); }
14
15// Optional: per‑frame reseed (e.g., for TAA)
16const nTemporal = interleavedGradientNoise( floor( viewportCoordinate ).add( float( frameId ) ) );