From f57f672b2facb36d5ba3bd4935c94da3590bc256 Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Thu, 2 Mar 2023 21:18:25 +0100 Subject: [PATCH 1/8] Add regression test for disabling the prepass plugin --- Cargo.toml | 7 +++++++ tests/3d/no_prepass.rs | 11 +++++++++++ 2 files changed, 18 insertions(+) create mode 100644 tests/3d/no_prepass.rs diff --git a/Cargo.toml b/Cargo.toml index aac8ea12e6f46..8068f9ed825ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -651,6 +651,13 @@ description = "Showcases wireframe rendering" category = "3D Rendering" wasm = true +[[example]] +name = "no_prepass" +path = "tests/3d/no_prepass.rs" + +[package.metadata.example.no_prepass] +hidden = true + # Animation [[example]] name = "animated_fox" diff --git a/tests/3d/no_prepass.rs b/tests/3d/no_prepass.rs new file mode 100644 index 0000000000000..589cfaa95caa2 --- /dev/null +++ b/tests/3d/no_prepass.rs @@ -0,0 +1,11 @@ +//! A test to confirm that `bevy` allows disabling the prepass of the standard material. +//! This is run in CI to ensure that this doesn't regress again. +use bevy::{pbr::PbrPlugin, prelude::*}; + +fn main() { + App::new() + .add_plugins(DefaultPlugins.set(PbrPlugin { + prepass_enabled: false, + })) + .run(); +} From e8440dbe0fdacdb741bedda71155548e071ed30a Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Thu, 2 Mar 2023 21:19:11 +0100 Subject: [PATCH 2/8] Split `PrepassPlugin`into `PrepassPlugin` and `PrepassPipelinePlugin` --- crates/bevy_pbr/src/material.rs | 7 ++++-- crates/bevy_pbr/src/prepass/mod.rs | 34 ++++++++++++++++++++++++------ 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 16213b2bb1ce0..cd629c2cf9c55 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -1,7 +1,7 @@ use crate::{ queue_mesh_view_bind_groups, render, AlphaMode, DrawMesh, DrawPrepass, EnvironmentMapLight, - MeshPipeline, MeshPipelineKey, MeshUniform, PrepassPlugin, RenderLightSystems, - SetMeshBindGroup, SetMeshViewBindGroup, Shadow, + MeshPipeline, MeshPipelineKey, MeshUniform, PrepassPipelinePlugin, PrepassPlugin, + RenderLightSystems, SetMeshBindGroup, SetMeshViewBindGroup, Shadow, }; use bevy_app::{App, IntoSystemAppConfig, Plugin}; use bevy_asset::{AddAsset, AssetEvent, AssetServer, Assets, Handle}; @@ -213,6 +213,9 @@ where .add_system(queue_material_meshes::.in_set(RenderSet::Queue)); } + // PrepassPipelinePlugin is required for shadow mapping and the optional PrepassPlugin + app.add_plugin(PrepassPipelinePlugin::::default()); + if self.prepass_enabled { app.add_plugin(PrepassPlugin::::default()); } diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index acfb160dd35c8..fe0719ac7c5ff 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -59,15 +59,15 @@ pub const PREPASS_BINDINGS_SHADER_HANDLE: HandleUntyped = pub const PREPASS_UTILS_SHADER_HANDLE: HandleUntyped = HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 4603948296044544); -pub struct PrepassPlugin(PhantomData); +pub struct PrepassPipelinePlugin(PhantomData); -impl Default for PrepassPlugin { +impl Default for PrepassPipelinePlugin { fn default() -> Self { Self(Default::default()) } } -impl Plugin for PrepassPlugin +impl Plugin for PrepassPipelinePlugin where M::Data: PartialEq + Eq + Hash + Clone, { @@ -93,6 +93,31 @@ where Shader::from_wgsl ); + let Ok(render_app) = app.get_sub_app_mut(RenderApp) else { + return; + }; + + render_app + .add_system(queue_prepass_view_bind_group::.in_set(RenderSet::Queue)) + .init_resource::>() + .init_resource::() + .init_resource::>>(); + } +} + +pub struct PrepassPlugin(PhantomData); + +impl Default for PrepassPlugin { + fn default() -> Self { + Self(Default::default()) + } +} + +impl Plugin for PrepassPlugin +where + M::Data: PartialEq + Eq + Hash + Clone, +{ + fn build(&self, app: &mut bevy_app::App) { let Ok(render_app) = app.get_sub_app_mut(RenderApp) else { return; }; @@ -104,14 +129,11 @@ where .in_set(RenderSet::Prepare) .after(bevy_render::view::prepare_windows), ) - .add_system(queue_prepass_view_bind_group::.in_set(RenderSet::Queue)) .add_system(queue_prepass_material_meshes::.in_set(RenderSet::Queue)) .add_system(sort_phase_system::.in_set(RenderSet::PhaseSort)) .add_system(sort_phase_system::.in_set(RenderSet::PhaseSort)) - .init_resource::>() .init_resource::>() .init_resource::>() - .init_resource::() .init_resource::>>() .add_render_command::>() .add_render_command::>(); From a05160ba5c75c168c980da08045d3940e8ddf9da Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Thu, 2 Mar 2023 21:31:32 +0100 Subject: [PATCH 3/8] Add doc comments --- crates/bevy_pbr/src/prepass/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index fe0719ac7c5ff..4e1ef23fca957 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -59,6 +59,9 @@ pub const PREPASS_BINDINGS_SHADER_HANDLE: HandleUntyped = pub const PREPASS_UTILS_SHADER_HANDLE: HandleUntyped = HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 4603948296044544); +/// Sets up everything required to use the prepass pipeline. +/// +/// This does not add the actual prepasses, see [`PrepassPipeline`] for that. pub struct PrepassPipelinePlugin(PhantomData); impl Default for PrepassPipelinePlugin { @@ -105,6 +108,9 @@ where } } +/// Sets up the prepasses for a [`Material`]. +/// +/// This depends on the [`PrepassPipelinePlugin`]. pub struct PrepassPlugin(PhantomData); impl Default for PrepassPlugin { From 50cb4b238c87840119e0a96ceef38a1d989ba892 Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Thu, 2 Mar 2023 22:49:26 +0100 Subject: [PATCH 4/8] Fix missing fragment entry point in default prepass shader --- crates/bevy_pbr/src/prepass/prepass.wgsl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crates/bevy_pbr/src/prepass/prepass.wgsl b/crates/bevy_pbr/src/prepass/prepass.wgsl index 6e81017dc090e..ebdb76a906e68 100644 --- a/crates/bevy_pbr/src/prepass/prepass.wgsl +++ b/crates/bevy_pbr/src/prepass/prepass.wgsl @@ -73,6 +73,7 @@ fn vertex(vertex: Vertex) -> VertexOutput { } #ifdef NORMAL_PREPASS + struct FragmentInput { @location(1) world_normal: vec3, } @@ -81,4 +82,10 @@ struct FragmentInput { fn fragment(in: FragmentInput) -> @location(0) vec4 { return vec4(in.world_normal * 0.5 + vec3(0.5), 1.0); } + +#else // NORMAL_PREPASS + +@fragment +fn fragment(in: VertexOutput) {} + #endif // NORMAL_PREPASS From 70e47ae99593f1c89ae46ec00931d39b483a57b9 Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Thu, 2 Mar 2023 23:15:26 +0100 Subject: [PATCH 5/8] Don't init `SpecializedMeshPipelines` in `PrepassPipeline` --- crates/bevy_pbr/src/prepass/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 4e1ef23fca957..5248cf07efc1d 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -140,7 +140,6 @@ where .add_system(sort_phase_system::.in_set(RenderSet::PhaseSort)) .init_resource::>() .init_resource::>() - .init_resource::>>() .add_render_command::>() .add_render_command::>(); } From 672486d10ba676ece15f1cd9cc42e6ab85ad44ea Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Fri, 3 Mar 2023 12:21:43 +0100 Subject: [PATCH 6/8] Update crates/bevy_pbr/src/prepass/mod.rs Co-authored-by: Robert Swain --- crates/bevy_pbr/src/prepass/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 5248cf07efc1d..5760c493dfeed 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -61,7 +61,7 @@ pub const PREPASS_UTILS_SHADER_HANDLE: HandleUntyped = /// Sets up everything required to use the prepass pipeline. /// -/// This does not add the actual prepasses, see [`PrepassPipeline`] for that. +/// This does not add the actual prepasses, see [`PrepassPlugin`] for that. pub struct PrepassPipelinePlugin(PhantomData); impl Default for PrepassPipelinePlugin { From 3bb042cd4f99f2f819f1bac36cfacd7b59e63655 Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Fri, 3 Mar 2023 15:03:14 +0100 Subject: [PATCH 7/8] Don't set fragment state for materials relying on the default prepass shader Except if the normal prepass is run. --- crates/bevy_pbr/src/prepass/mod.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 5760c493dfeed..407c357a230e4 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -281,11 +281,12 @@ where let vertex_buffer_layout = layout.get_layout(&vertex_attributes)?; - // The fragment shader is only used when the normal prepass is enabled or the material uses alpha cutoff values - let fragment = if key - .mesh_key - .intersects(MeshPipelineKey::NORMAL_PREPASS | MeshPipelineKey::ALPHA_MASK) - || blend_key == MeshPipelineKey::BLEND_PREMULTIPLIED_ALPHA + // The fragment shader is only used when the normal prepass is enabled + // or the material uses alpha cutoff values and doesn't rely on the standard prepass shader + let fragment = if key.mesh_key.contains(MeshPipelineKey::NORMAL_PREPASS) + || ((key.mesh_key.contains(MeshPipelineKey::ALPHA_MASK) + || blend_key == MeshPipelineKey::BLEND_PREMULTIPLIED_ALPHA) + && self.material_fragment_shader.is_some()) { // Use the fragment shader from the material if present let frag_shader_handle = if let Some(handle) = &self.material_fragment_shader { From 948fc3f44814e79b72a8feda1f7faabbc7291ad9 Mon Sep 17 00:00:00 2001 From: Edgar Geier Date: Fri, 3 Mar 2023 15:04:24 +0100 Subject: [PATCH 8/8] Revert "Fix missing fragment entry point in default prepass shader" This reverts commit 50cb4b238c87840119e0a96ceef38a1d989ba892. --- crates/bevy_pbr/src/prepass/prepass.wgsl | 7 ------- 1 file changed, 7 deletions(-) diff --git a/crates/bevy_pbr/src/prepass/prepass.wgsl b/crates/bevy_pbr/src/prepass/prepass.wgsl index ebdb76a906e68..6e81017dc090e 100644 --- a/crates/bevy_pbr/src/prepass/prepass.wgsl +++ b/crates/bevy_pbr/src/prepass/prepass.wgsl @@ -73,7 +73,6 @@ fn vertex(vertex: Vertex) -> VertexOutput { } #ifdef NORMAL_PREPASS - struct FragmentInput { @location(1) world_normal: vec3, } @@ -82,10 +81,4 @@ struct FragmentInput { fn fragment(in: FragmentInput) -> @location(0) vec4 { return vec4(in.world_normal * 0.5 + vec3(0.5), 1.0); } - -#else // NORMAL_PREPASS - -@fragment -fn fragment(in: VertexOutput) {} - #endif // NORMAL_PREPASS