
[*Percentage-closer soft shadows*] are a technique from 2004 that allow shadows to become blurrier farther from the objects that cast them. It works by introducing a *blocker search* step that runs before the normal shadow map sampling. The blocker search step detects the difference between the depth of the fragment being rasterized and the depth of the nearby samples in the depth buffer. Larger depth differences result in a larger penumbra and therefore a blurrier shadow. To enable PCSS, fill in the `soft_shadow_size` value in `DirectionalLight`, `PointLight`, or `SpotLight`, as appropriate. This shadow size value represents the size of the light and should be tuned as appropriate for your scene. Higher values result in a wider penumbra (i.e. blurrier shadows). When using PCSS, temporal shadow maps (`ShadowFilteringMethod::Temporal`) are recommended. If you don't use `ShadowFilteringMethod::Temporal` and instead use `ShadowFilteringMethod::Gaussian`, Bevy will use the same technique as `Temporal`, but the result won't vary over time. This produces a rather noisy result. Doing better would likely require downsampling the shadow map, which would be complex and slower (and would require PR #13003 to land first). In addition to PCSS, this commit makes the near Z plane for the shadow map configurable on a per-light basis. Previously, it had been hardcoded to 0.1 meters. This change was necessary to make the point light shadow map in the example look reasonable, as otherwise the shadows appeared far too aliased. A new example, `pcss`, has been added. It demonstrates the percentage-closer soft shadow technique with directional lights, point lights, spot lights, non-temporal operation, and temporal operation. The assets are my original work. Both temporal and non-temporal shadows are rather noisy in the example, and, as mentioned before, this is unavoidable without downsampling the depth buffer, which we can't do yet. Note also that the shadows don't look particularly great for point lights; the example simply isn't an ideal scene for them. Nevertheless, I felt that the benefits of the ability to do a side-by-side comparison of directional and point lights outweighed the unsightliness of the point light shadows in that example, so I kept the point light feature in. Fixes #3631. [*Percentage-closer soft shadows*]: https://developer.download.nvidia.com/shaderlibrary/docs/shadow_PCSS.pdf ## Changelog ### Added * Percentage-closer soft shadows (PCSS) are now supported, allowing shadows to become blurrier as they stretch away from objects. To use them, set the `soft_shadow_size` field in `DirectionalLight`, `PointLight`, or `SpotLight`, as applicable. * The near Z value for shadow maps is now customizable via the `shadow_map_near_z` field in `DirectionalLight`, `PointLight`, and `SpotLight`. ## Screenshots PCSS off:  PCSS on:  --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: Torstein Grindvik <52322338+torsteingrindvik@users.noreply.github.com>
104 lines
4.3 KiB
WebGPU Shading Language
104 lines
4.3 KiB
WebGPU Shading Language
#define_import_path bevy_pbr::mesh_view_bindings
|
|
|
|
#import bevy_pbr::mesh_view_types as types
|
|
#import bevy_render::{
|
|
view::View,
|
|
globals::Globals,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> view: View;
|
|
@group(0) @binding(1) var<uniform> lights: types::Lights;
|
|
#ifdef NO_CUBE_ARRAY_TEXTURES_SUPPORT
|
|
@group(0) @binding(2) var point_shadow_textures: texture_depth_cube;
|
|
#else
|
|
@group(0) @binding(2) var point_shadow_textures: texture_depth_cube_array;
|
|
#endif
|
|
@group(0) @binding(3) var point_shadow_textures_comparison_sampler: sampler_comparison;
|
|
@group(0) @binding(4) var point_shadow_textures_linear_sampler: sampler;
|
|
#ifdef NO_ARRAY_TEXTURES_SUPPORT
|
|
@group(0) @binding(5) var directional_shadow_textures: texture_depth_2d;
|
|
#else
|
|
@group(0) @binding(5) var directional_shadow_textures: texture_depth_2d_array;
|
|
#endif
|
|
@group(0) @binding(6) var directional_shadow_textures_comparison_sampler: sampler_comparison;
|
|
@group(0) @binding(7) var directional_shadow_textures_linear_sampler: sampler;
|
|
|
|
#if AVAILABLE_STORAGE_BUFFER_BINDINGS >= 3
|
|
@group(0) @binding(8) var<storage> clusterable_objects: types::ClusterableObjects;
|
|
@group(0) @binding(9) var<storage> clusterable_object_index_lists: types::ClusterLightIndexLists;
|
|
@group(0) @binding(10) var<storage> cluster_offsets_and_counts: types::ClusterOffsetsAndCounts;
|
|
#else
|
|
@group(0) @binding(8) var<uniform> clusterable_objects: types::ClusterableObjects;
|
|
@group(0) @binding(9) var<uniform> clusterable_object_index_lists: types::ClusterLightIndexLists;
|
|
@group(0) @binding(10) var<uniform> cluster_offsets_and_counts: types::ClusterOffsetsAndCounts;
|
|
#endif
|
|
|
|
@group(0) @binding(11) var<uniform> globals: Globals;
|
|
@group(0) @binding(12) var<uniform> fog: types::Fog;
|
|
@group(0) @binding(13) var<uniform> light_probes: types::LightProbes;
|
|
|
|
const VISIBILITY_RANGE_UNIFORM_BUFFER_SIZE: u32 = 64u;
|
|
#if AVAILABLE_STORAGE_BUFFER_BINDINGS >= 6
|
|
@group(0) @binding(14) var<storage> visibility_ranges: array<vec4<f32>>;
|
|
#else
|
|
@group(0) @binding(14) var<uniform> visibility_ranges: array<vec4<f32>, VISIBILITY_RANGE_UNIFORM_BUFFER_SIZE>;
|
|
#endif
|
|
|
|
@group(0) @binding(15) var<uniform> ssr_settings: types::ScreenSpaceReflectionsSettings;
|
|
@group(0) @binding(16) var screen_space_ambient_occlusion_texture: texture_2d<f32>;
|
|
|
|
#ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY
|
|
@group(0) @binding(17) var diffuse_environment_maps: binding_array<texture_cube<f32>, 8u>;
|
|
@group(0) @binding(18) var specular_environment_maps: binding_array<texture_cube<f32>, 8u>;
|
|
#else
|
|
@group(0) @binding(17) var diffuse_environment_map: texture_cube<f32>;
|
|
@group(0) @binding(18) var specular_environment_map: texture_cube<f32>;
|
|
#endif
|
|
@group(0) @binding(19) var environment_map_sampler: sampler;
|
|
@group(0) @binding(20) var<uniform> environment_map_uniform: types::EnvironmentMapUniform;
|
|
|
|
#ifdef IRRADIANCE_VOLUMES_ARE_USABLE
|
|
#ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY
|
|
@group(0) @binding(21) var irradiance_volumes: binding_array<texture_3d<f32>, 8u>;
|
|
#else
|
|
@group(0) @binding(21) var irradiance_volume: texture_3d<f32>;
|
|
#endif
|
|
@group(0) @binding(22) var irradiance_volume_sampler: sampler;
|
|
#endif
|
|
|
|
// NB: If you change these, make sure to update `tonemapping_shared.wgsl` too.
|
|
@group(0) @binding(23) var dt_lut_texture: texture_3d<f32>;
|
|
@group(0) @binding(24) var dt_lut_sampler: sampler;
|
|
|
|
#ifdef MULTISAMPLED
|
|
#ifdef DEPTH_PREPASS
|
|
@group(0) @binding(25) var depth_prepass_texture: texture_depth_multisampled_2d;
|
|
#endif // DEPTH_PREPASS
|
|
#ifdef NORMAL_PREPASS
|
|
@group(0) @binding(26) var normal_prepass_texture: texture_multisampled_2d<f32>;
|
|
#endif // NORMAL_PREPASS
|
|
#ifdef MOTION_VECTOR_PREPASS
|
|
@group(0) @binding(27) var motion_vector_prepass_texture: texture_multisampled_2d<f32>;
|
|
#endif // MOTION_VECTOR_PREPASS
|
|
|
|
#else // MULTISAMPLED
|
|
|
|
#ifdef DEPTH_PREPASS
|
|
@group(0) @binding(25) var depth_prepass_texture: texture_depth_2d;
|
|
#endif // DEPTH_PREPASS
|
|
#ifdef NORMAL_PREPASS
|
|
@group(0) @binding(26) var normal_prepass_texture: texture_2d<f32>;
|
|
#endif // NORMAL_PREPASS
|
|
#ifdef MOTION_VECTOR_PREPASS
|
|
@group(0) @binding(27) var motion_vector_prepass_texture: texture_2d<f32>;
|
|
#endif // MOTION_VECTOR_PREPASS
|
|
|
|
#endif // MULTISAMPLED
|
|
|
|
#ifdef DEFERRED_PREPASS
|
|
@group(0) @binding(28) var deferred_prepass_texture: texture_2d<u32>;
|
|
#endif // DEFERRED_PREPASS
|
|
|
|
@group(0) @binding(29) var view_transmission_texture: texture_2d<f32>;
|
|
@group(0) @binding(30) var view_transmission_sampler: sampler;
|