Skip to content

Commit d6c3871

Browse files
geieredgarProfLander
authored andcommitted
Use prepass shaders for shadows (bevyengine#7784)
# Objective - Fixes bevyengine#4372. ## Solution - Use the prepass shaders for the shadow passes. - Move `DEPTH_CLAMP_ORTHO` from `ShadowPipelineKey` to `MeshPipelineKey` and the associated clamp operation from `depth.wgsl` to `prepass.wgsl`. - Remove `depth.wgsl` . - Replace `ShadowPipeline` with `ShadowSamplers`. Instead of running the custom `ShadowPipeline` we run the `PrepassPipeline` with the `DEPTH_PREPASS` flag and additionally the `DEPTH_CLAMP_ORTHO` flag for directional lights as well as the `ALPHA_MASK` flag for materials that use `AlphaMode::Mask(_)`.
1 parent 9b7a206 commit d6c3871

File tree

8 files changed

+125
-260
lines changed

8 files changed

+125
-260
lines changed

crates/bevy_pbr/src/lib.rs

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ use bevy_render::{
5252
extract_resource::ExtractResourcePlugin,
5353
prelude::Color,
5454
render_graph::RenderGraph,
55-
render_phase::{sort_phase_system, AddRenderCommand, DrawFunctions},
56-
render_resource::{Shader, SpecializedMeshPipelines},
55+
render_phase::sort_phase_system,
56+
render_resource::Shader,
5757
view::{ViewSet, VisibilitySystems},
5858
ExtractSchedule, RenderApp, RenderSet,
5959
};
@@ -80,8 +80,6 @@ pub const PBR_FUNCTIONS_HANDLE: HandleUntyped =
8080
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 16550102964439850292);
8181
pub const PBR_AMBIENT_HANDLE: HandleUntyped =
8282
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 2441520459096337034);
83-
pub const SHADOW_SHADER_HANDLE: HandleUntyped =
84-
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 1836745567947005696);
8583

8684
/// Sets up the entire PBR infrastructure of bevy.
8785
pub struct PbrPlugin {
@@ -144,12 +142,6 @@ impl Plugin for PbrPlugin {
144142
Shader::from_wgsl
145143
);
146144
load_internal_asset!(app, PBR_SHADER_HANDLE, "render/pbr.wgsl", Shader::from_wgsl);
147-
load_internal_asset!(
148-
app,
149-
SHADOW_SHADER_HANDLE,
150-
"render/depth.wgsl",
151-
Shader::from_wgsl
152-
);
153145
load_internal_asset!(
154146
app,
155147
PBR_PREPASS_SHADER_HANDLE,
@@ -293,17 +285,12 @@ impl Plugin for PbrPlugin {
293285
.after(render::prepare_lights)
294286
.in_set(RenderLightSystems::PrepareClusters),
295287
)
296-
.add_system(render::queue_shadows.in_set(RenderLightSystems::QueueShadows))
297-
.add_system(render::queue_shadow_view_bind_group.in_set(RenderSet::Queue))
298288
.add_system(sort_phase_system::<Shadow>.in_set(RenderSet::PhaseSort))
299-
.init_resource::<ShadowPipeline>()
300-
.init_resource::<DrawFunctions<Shadow>>()
289+
.init_resource::<ShadowSamplers>()
301290
.init_resource::<LightMeta>()
302-
.init_resource::<GlobalLightMeta>()
303-
.init_resource::<SpecializedMeshPipelines<ShadowPipeline>>();
291+
.init_resource::<GlobalLightMeta>();
304292

305293
let shadow_pass_node = ShadowPassNode::new(&mut render_app.world);
306-
render_app.add_render_command::<Shadow, DrawShadowMesh>();
307294
let mut graph = render_app.world.resource_mut::<RenderGraph>();
308295
let draw_3d_graph = graph
309296
.get_sub_graph_mut(bevy_core_pipeline::core_3d::graph::NAME)

crates/bevy_pbr/src/material.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::{
2-
AlphaMode, DrawMesh, EnvironmentMapLight, MeshPipeline, MeshPipelineKey, MeshUniform,
3-
PrepassPlugin, SetMeshBindGroup, SetMeshViewBindGroup,
2+
queue_mesh_view_bind_groups, render, AlphaMode, DrawMesh, DrawPrepass, EnvironmentMapLight,
3+
MeshPipeline, MeshPipelineKey, MeshUniform, PrepassPlugin, RenderLightSystems,
4+
SetMeshBindGroup, SetMeshViewBindGroup, Shadow,
45
};
56
use bevy_app::{App, IntoSystemAppConfig, Plugin};
67
use bevy_asset::{AddAsset, AssetEvent, AssetServer, Assets, Handle};
@@ -188,6 +189,8 @@ where
188189

189190
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
190191
render_app
192+
.init_resource::<DrawFunctions<Shadow>>()
193+
.add_render_command::<Shadow, DrawPrepass<M>>()
191194
.add_render_command::<Transparent3d, DrawMaterial<M>>()
192195
.add_render_command::<Opaque3d, DrawMaterial<M>>()
193196
.add_render_command::<AlphaMask3d, DrawMaterial<M>>()
@@ -201,6 +204,12 @@ where
201204
.in_set(RenderSet::Prepare)
202205
.after(PrepareAssetSet::PreAssetPrepare),
203206
)
207+
.add_system(render::queue_shadows::<M>.in_set(RenderLightSystems::QueueShadows))
208+
.add_system(
209+
render::queue_shadow_view_bind_group::<M>
210+
.in_set(RenderSet::Queue)
211+
.ambiguous_with(queue_mesh_view_bind_groups), // queue_mesh_view_bind_groups does not read `shadow_view_bind_group`),
212+
)
204213
.add_system(queue_material_meshes::<M>.in_set(RenderSet::Queue));
205214
}
206215

crates/bevy_pbr/src/prepass/mod.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,13 @@ where
202202
shader_defs.push("ALPHA_MASK".into());
203203
}
204204

205+
let blend_key = key
206+
.mesh_key
207+
.intersection(MeshPipelineKey::BLEND_RESERVED_BITS);
208+
if blend_key == MeshPipelineKey::BLEND_PREMULTIPLIED_ALPHA {
209+
shader_defs.push("BLEND_PREMULTIPLIED_ALPHA".into());
210+
}
211+
205212
if layout.contains(Mesh::ATTRIBUTE_POSITION) {
206213
shader_defs.push("VERTEX_POSITIONS".into());
207214
vertex_attributes.push(Mesh::ATTRIBUTE_POSITION.at_shader_location(0));
@@ -215,6 +222,9 @@ where
215222
"MAX_CASCADES_PER_LIGHT".to_string(),
216223
MAX_CASCADES_PER_LIGHT as i32,
217224
));
225+
if key.mesh_key.contains(MeshPipelineKey::DEPTH_CLAMP_ORTHO) {
226+
shader_defs.push("DEPTH_CLAMP_ORTHO".into());
227+
}
218228

219229
if layout.contains(Mesh::ATTRIBUTE_UV_0) {
220230
shader_defs.push("VERTEX_UVS".into());
@@ -244,9 +254,11 @@ where
244254

245255
let vertex_buffer_layout = layout.get_layout(&vertex_attributes)?;
246256

247-
// The fragment shader is only used when the normal prepass is enabled or the material uses an alpha mask
248-
let fragment = if key.mesh_key.contains(MeshPipelineKey::NORMAL_PREPASS)
249-
|| key.mesh_key.contains(MeshPipelineKey::ALPHA_MASK)
257+
// The fragment shader is only used when the normal prepass is enabled or the material uses alpha cutoff values
258+
let fragment = if key
259+
.mesh_key
260+
.intersects(MeshPipelineKey::NORMAL_PREPASS | MeshPipelineKey::ALPHA_MASK)
261+
|| blend_key == MeshPipelineKey::BLEND_PREMULTIPLIED_ALPHA
250262
{
251263
// Use the fragment shader from the material if present
252264
let frag_shader_handle = if let Some(handle) = &self.material_fragment_shader {

crates/bevy_pbr/src/prepass/prepass.wgsl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ fn vertex(vertex: Vertex) -> VertexOutput {
4949
#endif // SKINNED
5050

5151
out.clip_position = mesh_position_local_to_clip(model, vec4(vertex.position, 1.0));
52+
#ifdef DEPTH_CLAMP_ORTHO
53+
out.clip_position.z = min(out.clip_position.z, 1.0);
54+
#endif // DEPTH_CLAMP_ORTHO
5255

5356
#ifdef VERTEX_UVS
5457
out.uv = vertex.uv;

crates/bevy_pbr/src/render/depth.wgsl

Lines changed: 0 additions & 46 deletions
This file was deleted.

0 commit comments

Comments
 (0)