PointShadowFilter
A PCF (percentage-closer filtering) function node designed for point-light cube-map shadow maps. It performs depth comparisons over a fixed 3×3 sampling pattern on the cube map’s UV atlas and averages the results, smoothing aliased point-light shadow edges into soft shadows.
Core Advantages
Handles direction-to-UV conversion for point-light shadows and optimizes the sampling distribution, encapsulating nine-tap PCF sampling and depth-compare logic. No need to hand-write cube-coordinate to UV conversion or configure a sampling kernel to achieve stable, controllable soft-shadow quality.
Common Uses
Omnidirectional soft shadows from indoor or local lights (bulbs, candles, flashlights)
Real-time softening of shadows when characters carry point lights
Smoother point-light shadow transitions in stylized rendering
How to adjust
Softness is primarily controlled by `shadow.radius`; sampling stride is set by `texelSize.y` and is indirectly affected by `shadow.mapSize`. A larger `radius` widens the 3×3 kernel coverage and yields softer shadows; higher map resolution produces finer edges for the same radius. If you see “shadow acne” or the “Peter Pan effect,” adjust the light’s `shadow.bias` and `shadow.normalBias`.
Code Examples
1// JS: configure point-light shadows
2pointLight.castShadow = true;
3pointLight.shadow.mapSize.set( 1024, 1024 );
4pointLight.shadow.radius = 1.0; // penumbra width
5
6// TSL: usually no explicit call is needed; pointShadow selects an appropriate filter internally.
7// For a custom point-light shadow pipeline, call directly:
8const factor = PointShadowFilter({
9 depthTexture, // point-light shadow depth texture (cube-map unwrapped/atlas)
10 bd3D, // direction from fragment to light (with offset)
11 dp, // depth comparison value
12 texelSize, // pixel size derived from mapSize
13 shadow // shadow context providing radius, etc.
14});
15
16diffuseColor.rgb *= factor;