diff --git a/crates/bevy_pbr/src/render/shadow_sampling.wgsl b/crates/bevy_pbr/src/render/shadow_sampling.wgsl index d4f0751e17e68..4706665a53a4a 100644 --- a/crates/bevy_pbr/src/render/shadow_sampling.wgsl +++ b/crates/bevy_pbr/src/render/shadow_sampling.wgsl @@ -208,6 +208,11 @@ fn sample_shadow_map_jimenez_fourteen( return sum / 8.0; } +const PENUMBRA_FILTER_SIZE: vec2 = vec2(128.0f); +// Offset for use with interleaved gradient noise and similar to avoid using the +// same noise pattern for multiple algorithms +const BLOCKER_SEARCH_OFFSET: vec2 = vec2(17.23f); + // Performs the blocker search portion of percentage-closer soft shadows (PCSS). // This is the variation used for directional lights. // @@ -222,20 +227,20 @@ fn search_for_blockers_in_shadow_map( light_local: vec2, depth: f32, array_index: i32, - texel_size: f32, - search_size: f32, + frag_coord_xy: vec2, ) -> f32 { let shadow_map_size = vec2(textureDimensions(view_bindings::directional_shadow_textures)); - let uv_offset_scale = search_size / (texel_size * shadow_map_size); - - let offset0 = D3D_SAMPLE_POINT_POSITIONS[0] * uv_offset_scale; - let offset1 = D3D_SAMPLE_POINT_POSITIONS[1] * uv_offset_scale; - let offset2 = D3D_SAMPLE_POINT_POSITIONS[2] * uv_offset_scale; - let offset3 = D3D_SAMPLE_POINT_POSITIONS[3] * uv_offset_scale; - let offset4 = D3D_SAMPLE_POINT_POSITIONS[4] * uv_offset_scale; - let offset5 = D3D_SAMPLE_POINT_POSITIONS[5] * uv_offset_scale; - let offset6 = D3D_SAMPLE_POINT_POSITIONS[6] * uv_offset_scale; - let offset7 = D3D_SAMPLE_POINT_POSITIONS[7] * uv_offset_scale; + let rotation_matrix = random_rotation_matrix(frag_coord_xy + BLOCKER_SEARCH_OFFSET, false); + let uv_offset_scale = PENUMBRA_FILTER_SIZE / shadow_map_size; + + let offset0 = rotation_matrix * D3D_SAMPLE_POINT_POSITIONS[0] * uv_offset_scale; + let offset1 = rotation_matrix * D3D_SAMPLE_POINT_POSITIONS[1] * uv_offset_scale; + let offset2 = rotation_matrix * D3D_SAMPLE_POINT_POSITIONS[2] * uv_offset_scale; + let offset3 = rotation_matrix * D3D_SAMPLE_POINT_POSITIONS[3] * uv_offset_scale; + let offset4 = rotation_matrix * D3D_SAMPLE_POINT_POSITIONS[4] * uv_offset_scale; + let offset5 = rotation_matrix * D3D_SAMPLE_POINT_POSITIONS[5] * uv_offset_scale; + let offset6 = rotation_matrix * D3D_SAMPLE_POINT_POSITIONS[6] * uv_offset_scale; + let offset7 = rotation_matrix * D3D_SAMPLE_POINT_POSITIONS[7] * uv_offset_scale; var sum = vec2(0.0); sum += search_for_blockers_in_shadow_map_hardware(light_local + offset0, depth, array_index); @@ -296,8 +301,7 @@ fn sample_shadow_map_pcss( light_size: f32, ) -> f32 { // Determine the average Z value of the closest blocker. - let z_blocker = search_for_blockers_in_shadow_map( - light_local, depth, array_index, texel_size, light_size); + let z_blocker = search_for_blockers_in_shadow_map(light_local, depth, array_index, frag_coord_xy); // Don't let the blur size go below 0.5, or shadows will look unacceptably aliased. let blur_size = max((z_blocker - depth) * light_size / depth, 0.5);