Back home 🏡 WGSL Spec Bevy WGSL Functions

shadow_sampling.wgsl

Import path

Constants

Name Type Value
SPOT_SHADOW_TEXEL_SIZE # f32 0.0134277345
POINT_SHADOW_SCALE # f32 0.003
POINT_SHADOW_TEMPORAL_OFFSET_SCALE # f32 0.5

Functions

sample_shadow_map_hardware

#
Do the lookup, using HW 2x2 PCF and comparison
fn sample_shadow_map_hardware(light_local: vec2<f32>, depth: f32, array_index: i32) -> f32
Parameter Type
light_local vec2<f32>
depth f32
array_index i32
Returns: f32

search_for_blockers_in_shadow_map_hardware

#
Does a single sample of the blocker search, a part of the PCSS algorithm. This is the variant used for directional lights.
fn search_for_blockers_in_shadow_map_hardware(light_local: vec2<f32>, depth: f32, array_index: i32) -> vec2<f32>
Parameter Type
light_local vec2<f32>
depth f32
array_index i32
Returns: vec2<f32>

sample_shadow_map_castano_thirteen

#
https://web.archive.org/web/20230210095515/http://the-witness.net/news/2013/09/shadow-mapping-summary-part-1
fn sample_shadow_map_castano_thirteen(light_local: vec2<f32>, depth: f32, array_index: i32) -> f32
Parameter Type
light_local vec2<f32>
depth f32
array_index i32
Returns: f32

map

#
fn map(min1: f32, max1: f32, min2: f32, max2: f32, value: f32) -> f32
Parameter Type
min1 f32
max1 f32
min2 f32
max2 f32
value f32
Returns: f32

random_rotation_matrix

#
Creates a random rotation matrix using interleaved gradient noise. See: https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare/
fn random_rotation_matrix(scale: vec2<f32>, temporal: bool) -> mat2x2<f32>
Parameter Type
scale vec2<f32>
temporal bool
Returns: mat2x2<f32>

calculate_uv_offset_scale_jimenez_fourteen

#
Calculates the distance between spiral samples for the given texel size and penumbra size. This is used for the Jimenez '14 (i.e. temporal) variant of shadow sampling.
fn calculate_uv_offset_scale_jimenez_fourteen(texel_size: f32, blur_size: f32) -> vec2<f32>
Parameter Type
texel_size f32
blur_size f32
Returns: vec2<f32>

sample_shadow_map_jimenez_fourteen

#
fn sample_shadow_map_jimenez_fourteen(light_local: vec2<f32>, depth: f32, array_index: i32, texel_size: f32, blur_size: f32, temporal: bool) -> f32
Parameter Type
light_local vec2<f32>
depth f32
array_index i32
texel_size f32
blur_size f32
temporal bool
Returns: f32

search_for_blockers_in_shadow_map

#
Performs the blocker search portion of percentage-closer soft shadows (PCSS). This is the variation used for directional lights. We can't use Castano '13 here because that has a hard-wired fixed size, while the PCSS algorithm requires a search size that varies based on the size of the light. So we instead use the D3D sample point positions, spaced according to the search size, to provide a sample pattern in a similar manner to the cubemap sampling approach we use for PCF. search_size is the size of the search region in texels.
fn search_for_blockers_in_shadow_map(light_local: vec2<f32>, depth: f32, array_index: i32, texel_size: f32, search_size: f32) -> f32
Parameter Type
light_local vec2<f32>
depth f32
array_index i32
texel_size f32
search_size f32
Returns: f32

sample_shadow_map

#
fn sample_shadow_map(light_local: vec2<f32>, depth: f32, array_index: i32, texel_size: f32) -> f32
Parameter Type
light_local vec2<f32>
depth f32
array_index i32
texel_size f32
Returns: f32

sample_shadow_map_pcss

#
Samples the shadow map for a directional light when percentage-closer soft shadows are being used. We first search for a *blocker*, which is the average depth value of any shadow map samples that are adjacent to the sample we're considering. That allows us to determine the penumbra size; a larger gap between the blocker and the depth of this sample results in a wider penumbra. Finally, we sample the shadow map the same way we do in PCF, using that penumbra width. A good overview of the technique: <https://medium.com/@varunm100/soft-shadows-for-mobile-ar-9e8da2e6f4ba>
fn sample_shadow_map_pcss(light_local: vec2<f32>, depth: f32, array_index: i32, texel_size: f32, light_size: f32) -> f32
Parameter Type
light_local vec2<f32>
depth f32
array_index i32
texel_size f32
light_size f32
Returns: f32

sample_shadow_cubemap_hardware

#
NOTE: Due to the non-uniform control flow in shadows::fetch_point_shadow, we must use the Level variant of textureSampleCompare to avoid undefined behavior due to some of the fragments in a quad (2x2 fragments) being processed not being sampled, and this messing with mip-mapping functionality. The shadow maps have no mipmaps so Level just samples from LOD 0.
fn sample_shadow_cubemap_hardware(light_local: vec3<f32>, depth: f32, light_id: u32) -> f32
Parameter Type
light_local vec3<f32>
depth f32
light_id u32
Returns: f32

search_for_blockers_in_shadow_cubemap_hardware

#
Performs one sample of the blocker search. This variation of the blocker search function is for point and spot lights.
fn search_for_blockers_in_shadow_cubemap_hardware(light_local: vec3<f32>, depth: f32, light_id: u32) -> vec2<f32>
Parameter Type
light_local vec3<f32>
depth f32
light_id u32
Returns: vec2<f32>

sample_shadow_cubemap_at_offset

#
fn sample_shadow_cubemap_at_offset(position: vec2<f32>, coeff: f32, x_basis: vec3<f32>, y_basis: vec3<f32>, light_local: vec3<f32>, depth: f32, light_id: u32) -> f32
Parameter Type
position vec2<f32>
coeff f32
x_basis vec3<f32>
y_basis vec3<f32>
light_local vec3<f32>
depth f32
light_id u32
Returns: f32

search_for_blockers_in_shadow_cubemap_at_offset

#
Computes the search position and performs one sample of the blocker search. This variation of the blocker search function is for point and spot lights. x_basis`, `y_basis`, and `light_local form an orthonormal basis over which the blocker search happens.
fn search_for_blockers_in_shadow_cubemap_at_offset(position: vec2<f32>, x_basis: vec3<f32>, y_basis: vec3<f32>, light_local: vec3<f32>, depth: f32, light_id: u32) -> vec2<f32>
Parameter Type
position vec2<f32>
x_basis vec3<f32>
y_basis vec3<f32>
light_local vec3<f32>
depth f32
light_id u32
Returns: vec2<f32>

sample_shadow_cubemap_gaussian

#
This more or less does what Castano13 does, but in 3D space. Castano13 is essentially an optimized 2D Gaussian filter that takes advantage of the bilinear filtering hardware to reduce the number of samples needed. This trick doesn't apply to cubemaps, so we manually apply a Gaussian filter over the standard 8xMSAA pattern instead.
fn sample_shadow_cubemap_gaussian(light_local: vec3<f32>, depth: f32, scale: f32, distance_to_light: f32, light_id: u32) -> f32
Parameter Type
light_local vec3<f32>
depth f32
scale f32
distance_to_light f32
light_id u32
Returns: f32

sample_shadow_cubemap_jittered

#
This is a port of the Jimenez14 filter above to the 3D space. It jitters the points in the spiral pattern after first creating a 2D orthonormal basis along the principal light direction.
fn sample_shadow_cubemap_jittered(light_local: vec3<f32>, depth: f32, scale: f32, distance_to_light: f32, light_id: u32, temporal: bool) -> f32
Parameter Type
light_local vec3<f32>
depth f32
scale f32
distance_to_light f32
light_id u32
temporal bool
Returns: f32

sample_shadow_cubemap

#
fn sample_shadow_cubemap(light_local: vec3<f32>, distance_to_light: f32, depth: f32, light_id: u32) -> f32
Parameter Type
light_local vec3<f32>
distance_to_light f32
depth f32
light_id u32
Returns: f32

search_for_blockers_in_shadow_cubemap

#
Searches for PCSS blockers in a cubemap. This is the variant of the blocker search used for point and spot lights. This follows the logic in sample_shadow_cubemap_gaussian, but uses linear sampling instead of percentage-closer filtering. The scale parameter represents the size of the light.
fn search_for_blockers_in_shadow_cubemap(light_local: vec3<f32>, depth: f32, scale: f32, distance_to_light: f32, light_id: u32) -> f32
Parameter Type
light_local vec3<f32>
depth f32
scale f32
distance_to_light f32
light_id u32
Returns: f32

sample_shadow_cubemap_pcss

#
Samples the shadow map for a point or spot light when percentage-closer soft shadows are being used. A good overview of the technique: <https://medium.com/@varunm100/soft-shadows-for-mobile-ar-9e8da2e6f4ba>
fn sample_shadow_cubemap_pcss(light_local: vec3<f32>, distance_to_light: f32, depth: f32, light_id: u32, light_size: f32) -> f32
Parameter Type
light_local vec3<f32>
distance_to_light f32
depth f32
light_id u32
light_size f32
Returns: f32