Skip to content

Commit 000d4fb

Browse files
mrdoobclaude
andauthored
WebGPURenderer: Optimize VSM shadow code (#32209)
Port optimizations from PR #32181 to the WebGPU renderer: - Extract mean variable for clarity - Add early return optimization for fully lit pixels - Improve variable naming (d, p_max) - Correct variance epsilon from 0 to 0.0000001 - Pre-compute constant (0.65 instead of 0.95 - 0.3) - Remove redundant outer clamp - Add clarifying comments These changes improve performance by reducing operations per pixel while maintaining identical visual output. Co-authored-by: Claude <noreply@anthropic.com>
1 parent 2bf24e8 commit 000d4fb

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

src/nodes/lighting/ShadowFilterNode.js

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,6 @@ export const PCFSoftShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoo
185185
*/
186186
export const VSMShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoord, depthLayer } ) => {
187187

188-
const occlusion = float( 1 ).toVar();
189-
190188
let distribution = texture( depthTexture ).sample( shadowCoord.xy );
191189

192190
if ( depthTexture.isArrayTexture ) {
@@ -197,19 +195,28 @@ export const VSMShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoord,
197195

198196
distribution = distribution.rg;
199197

200-
const hardShadow = step( shadowCoord.z, distribution.x );
198+
const mean = distribution.x;
199+
const variance = max( 0.0000001, distribution.y.mul( distribution.y ) );
200+
201+
const hardShadow = step( shadowCoord.z, mean );
201202

202-
If( hardShadow.notEqual( float( 1.0 ) ), () => {
203+
// Early return if fully lit
204+
If( hardShadow.equal( 1.0 ), () => {
203205

204-
const distance = shadowCoord.z.sub( distribution.x );
205-
const variance = max( 0, distribution.y.mul( distribution.y ) );
206-
let softnessProbability = variance.div( variance.add( distance.mul( distance ) ) ); // Chebeyshevs inequality
207-
softnessProbability = clamp( sub( softnessProbability, 0.3 ).div( 0.95 - 0.3 ) );
208-
occlusion.assign( clamp( max( hardShadow, softnessProbability ) ) );
206+
return float( 1.0 );
209207

210208
} );
211209

212-
return occlusion;
210+
// Distance from mean
211+
const d = shadowCoord.z.sub( mean );
212+
213+
// Chebyshev's inequality for upper bound on probability
214+
let p_max = variance.div( variance.add( d.mul( d ) ) );
215+
216+
// Reduce light bleeding by remapping [amount, 1] to [0, 1]
217+
p_max = clamp( sub( p_max, 0.3 ).div( 0.65 ) );
218+
219+
return max( hardShadow, p_max );
213220

214221
} );
215222

0 commit comments

Comments
 (0)