From 7df1bab38a42d8a33bc50ca583d4be37bd9c9f0d Mon Sep 17 00:00:00 2001 From: Robert Swain Date: Tue, 13 Jul 2021 16:20:05 +0200 Subject: [PATCH] bevy_pbr2: Do manual shadow map depth comparisons for more flexibility --- pipelined/bevy_pbr2/src/render/light.rs | 4 +-- pipelined/bevy_pbr2/src/render/mod.rs | 4 +-- pipelined/bevy_pbr2/src/render/pbr.wgsl | 33 +++++++++++++++---------- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/pipelined/bevy_pbr2/src/render/light.rs b/pipelined/bevy_pbr2/src/render/light.rs index ccb7bdc11e357..3458265e23dba 100644 --- a/pipelined/bevy_pbr2/src/render/light.rs +++ b/pipelined/bevy_pbr2/src/render/light.rs @@ -200,7 +200,7 @@ impl FromWorld for ShadowShaders { mag_filter: FilterMode::Nearest, min_filter: FilterMode::Nearest, mipmap_filter: FilterMode::Nearest, - compare: Some(CompareFunction::LessEqual), + compare: None, ..Default::default() }), directional_light_sampler: render_device.create_sampler(&SamplerDescriptor { @@ -210,7 +210,7 @@ impl FromWorld for ShadowShaders { mag_filter: FilterMode::Nearest, min_filter: FilterMode::Nearest, mipmap_filter: FilterMode::Nearest, - compare: Some(CompareFunction::LessEqual), + compare: None, ..Default::default() }), } diff --git a/pipelined/bevy_pbr2/src/render/mod.rs b/pipelined/bevy_pbr2/src/render/mod.rs index 0c03cc12d4ccf..e33d4ca878b2b 100644 --- a/pipelined/bevy_pbr2/src/render/mod.rs +++ b/pipelined/bevy_pbr2/src/render/mod.rs @@ -88,7 +88,7 @@ impl FromWorld for PbrShaders { binding: 3, visibility: ShaderStage::FRAGMENT, ty: BindingType::Sampler { - comparison: true, + comparison: false, filtering: false, }, count: None, @@ -109,7 +109,7 @@ impl FromWorld for PbrShaders { binding: 5, visibility: ShaderStage::FRAGMENT, ty: BindingType::Sampler { - comparison: true, + comparison: false, filtering: false, }, count: None, diff --git a/pipelined/bevy_pbr2/src/render/pbr.wgsl b/pipelined/bevy_pbr2/src/render/pbr.wgsl index f99a149969b06..8b80ea725af04 100644 --- a/pipelined/bevy_pbr2/src/render/pbr.wgsl +++ b/pipelined/bevy_pbr2/src/render/pbr.wgsl @@ -131,11 +131,11 @@ var lights: Lights; [[group(0), binding(2)]] var point_shadow_textures: texture_depth_cube_array; [[group(0), binding(3)]] -var point_shadow_textures_sampler: sampler_comparison; +var point_shadow_textures_sampler: sampler; [[group(0), binding(4)]] var directional_shadow_textures: texture_depth_2d_array; [[group(0), binding(5)]] -var directional_shadow_textures_sampler: sampler_comparison; +var directional_shadow_textures_sampler: sampler; [[group(2), binding(0)]] var material: StandardMaterial; @@ -398,13 +398,14 @@ fn fetch_point_shadow(light_id: i32, frag_position: vec4) -> f32 { let w = major_axis_magnitude; let depth = z / w; - // do the lookup, using HW PCF and comparison - // NOTE: Due to the non-uniform control flow above, we must use the Level variant of - // textureSampleCompare to avoid undefined behaviour 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. - return textureSampleCompareLevel(point_shadow_textures, point_shadow_textures_sampler, frag_ls, i32(light_id), depth); + let shadow_map_depth = textureSampleLevel(point_shadow_textures, point_shadow_textures_sampler, frag_ls, i32(light_id), 0.0); + var shadow: f32; + if (depth < shadow_map_depth) { + shadow = 1.0; + } else { + shadow = 0.0; + } + return shadow; } fn fetch_directional_shadow(light_id: i32, frag_position: vec4) -> f32 { @@ -418,10 +419,16 @@ fn fetch_directional_shadow(light_id: i32, frag_position: vec4) -> f32 { let proj_correction = 1.0 / homogeneous_coords.w; // compute texture coordinates for shadow lookup let light_local = homogeneous_coords.xy * flip_correction * proj_correction + vec2(0.5, 0.5); - // do the lookup, using HW PCF and comparison - // NOTE: Due to non-uniform control flow above, we must use the level variant of the texture - // sampler to avoid use of implicit derivatives causing possible undefined behavior. - return textureSampleCompareLevel(directional_shadow_textures, directional_shadow_textures_sampler, light_local, i32(light_id), homogeneous_coords.z * proj_correction); + let depth = homogeneous_coords.z * proj_correction; + + let shadow_map_depth = textureSampleLevel(directional_shadow_textures, directional_shadow_textures_sampler, light_local, i32(light_id), 0.0); + var shadow: f32; + if (depth < shadow_map_depth) { + shadow = 1.0; + } else { + shadow = 0.0; + } + return shadow; } struct FragmentInput {