diff --git a/examples/screenshots/webgl_pmrem_test.jpg b/examples/screenshots/webgl_pmrem_test.jpg index d99ddcc72f6897..0b8428e6004e71 100644 Binary files a/examples/screenshots/webgl_pmrem_test.jpg and b/examples/screenshots/webgl_pmrem_test.jpg differ diff --git a/examples/webgpu_pmrem_test.html b/examples/webgpu_pmrem_test.html index 670392723126b5..9ba44ee9930a6a 100644 --- a/examples/webgpu_pmrem_test.html +++ b/examples/webgpu_pmrem_test.html @@ -4,26 +4,31 @@ three.js webgpu - PMREM directional light test - + -
-
- three.js webgpu - - PMREM test by Emmett Lalish -
-
1: white metal. 2: white dielectric. 3: black dielectric. +
+ + +
+ three.jsPMREM Directional Light Test +
+ + + 1: white metal. 2: white dielectric. 3: black dielectric.
PMREM on: HDR with a single bright pixel. PMREM off: DirectionalLight.
The difference between these renders indicates the error in the PMREM approximations. -
+
PMREM test by Emmett Lalish +
diff --git a/src/nodes/functions/BSDF/DFGApprox.js b/src/nodes/functions/BSDF/DFGApprox.js index 1170ed0aa6227b..9c25a36b0d154d 100644 --- a/src/nodes/functions/BSDF/DFGApprox.js +++ b/src/nodes/functions/BSDF/DFGApprox.js @@ -1,30 +1,28 @@ -import { Fn, vec2, vec4 } from '../../tsl/TSLBase.js'; +import { Fn, vec2 } from '../../tsl/TSLBase.js'; +import { texture } from '../../accessors/TextureNode.js'; +import { getDFGLUT } from '../../../renderers/shaders/DFGLUTData.js'; -// Analytical approximation of the DFG LUT, one half of the -// split-sum approximation used in indirect specular lighting. -// via 'environmentBRDF' from "Physically Based Shading on Mobile" -// https://www.unrealengine.com/blog/physically-based-shading-on-mobile -const DFGApprox = /*@__PURE__*/ Fn( ( { roughness, dotNV } ) => { +// Cached DFG LUT texture + +let dfgLUT = null; - const c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 ); +// DFG LUT sampling for physically-based rendering. +// Uses a precomputed lookup table for the split-sum approximation +// used in indirect specular lighting. +// Reference: "Real Shading in Unreal Engine 4" by Brian Karis + +const DFGApprox = /*@__PURE__*/ Fn( ( { roughness, dotNV } ) => { - const c1 = vec4( 1, 0.0425, 1.04, - 0.04 ); + if ( dfgLUT === null ) { - const r = roughness.mul( c0 ).add( c1 ); + dfgLUT = getDFGLUT(); - const a004 = r.x.mul( r.x ).min( dotNV.mul( - 9.28 ).exp2() ).mul( r.x ).add( r.y ); + } - const fab = vec2( - 1.04, 1.04 ).mul( a004 ).add( r.zw ); + const uv = vec2( roughness, dotNV ); - return fab; + return texture( dfgLUT, uv ).rg; -} ).setLayout( { - name: 'DFGApprox', - type: 'vec2', - inputs: [ - { name: 'roughness', type: 'float' }, - { name: 'dotNV', type: 'vec3' } - ] } ); export default DFGApprox;