Builtin Library
- ..
- README.md1.7 KB
- module.wgsl35.6 KB
README.md
shadows
The shadow-sampling interface every surface shader calls instead of writing its
own PCF loop: compute_directional_shadow_factor for the sun (its virtual
shadow map's pages),
compute_spot_shadow_factor, compute_point_shadow_factor and
compute_area_shadow_factor for punctual lights. Each answers 1.0 for fully lit
and 0.0 for fully shadowed.
A shader that walks the punctual lights (zero_point_light(i)) rather than
naming one light asks
compute_punctual_shadow_factor(index, world_pos, normal) instead, which reads
the row's kind and answers for whatever shape it casts in, and weighs the
answers with zshadow_light_reach(index, world_pos, normal, object_channels) —
how much direct light that row actually puts on a surface on those light
channels, zero exactly where it puts none, the channel mask included.
zshadow_punctual_probe and zshadow_directional_probe go one level under a
factor, returning the depth the fragment carries in a light's map beside the
depth the map already held there, loaded rather than compared.
Routing through these is what keeps a shader in step with the renderer — the
page levels, map resolution and filter width come from the bound frame data
rather than from constants baked into the shader. The directional call selects
the level the receiver's screen footprint asks for, and inside a hero box
(renderer.setShadowHero) a level finer by the box's level bias.
// @domain: surface
#include "@builtin::shaderModules.shadows"
fn fragment(input: FragmentData) -> vec4<f32> {
let n = normalize(input.world_normal);
let lit = compute_directional_shadow_factor(input.world_position, n, uniforms.light_direction);
return vec4<f32>(vec3<f32>(lit), 1.0);
}