Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Fix dependency of shadow mapping on the optional PrepassPlugin #7878

Closed
wants to merge 9 commits into from
7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
7 changes: 5 additions & 2 deletions crates/bevy_pbr/src/material.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -213,6 +213,9 @@ where
.add_system(queue_material_meshes::<M>.in_set(RenderSet::Queue));
}

// PrepassPipelinePlugin is required for shadow mapping and the optional PrepassPlugin
app.add_plugin(PrepassPipelinePlugin::<M>::default());

if self.prepass_enabled {
app.add_plugin(PrepassPlugin::<M>::default());
}
Expand Down
41 changes: 34 additions & 7 deletions crates/bevy_pbr/src/prepass/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,18 @@ 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<M: Material>(PhantomData<M>);
/// Sets up everything required to use the prepass pipeline.
///
/// This does not add the actual prepasses, see [`PrepassPipeline`] for that.
geieredgar marked this conversation as resolved.
Show resolved Hide resolved
pub struct PrepassPipelinePlugin<M: Material>(PhantomData<M>);

impl<M: Material> Default for PrepassPlugin<M> {
impl<M: Material> Default for PrepassPipelinePlugin<M> {
fn default() -> Self {
Self(Default::default())
}
}

impl<M: Material> Plugin for PrepassPlugin<M>
impl<M: Material> Plugin for PrepassPipelinePlugin<M>
where
M::Data: PartialEq + Eq + Hash + Clone,
{
Expand All @@ -93,6 +96,34 @@ 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::<M>.in_set(RenderSet::Queue))
.init_resource::<PrepassPipeline<M>>()
.init_resource::<PrepassViewBindGroup>()
.init_resource::<SpecializedMeshPipelines<PrepassPipeline<M>>>();
}
}

/// Sets up the prepasses for a [`Material`].
///
/// This depends on the [`PrepassPipelinePlugin`].
pub struct PrepassPlugin<M: Material>(PhantomData<M>);

impl<M: Material> Default for PrepassPlugin<M> {
fn default() -> Self {
Self(Default::default())
}
}

impl<M: Material> Plugin for PrepassPlugin<M>
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;
};
Expand All @@ -104,15 +135,11 @@ where
.in_set(RenderSet::Prepare)
.after(bevy_render::view::prepare_windows),
)
.add_system(queue_prepass_view_bind_group::<M>.in_set(RenderSet::Queue))
.add_system(queue_prepass_material_meshes::<M>.in_set(RenderSet::Queue))
.add_system(sort_phase_system::<Opaque3dPrepass>.in_set(RenderSet::PhaseSort))
.add_system(sort_phase_system::<AlphaMask3dPrepass>.in_set(RenderSet::PhaseSort))
.init_resource::<PrepassPipeline<M>>()
.init_resource::<DrawFunctions<Opaque3dPrepass>>()
.init_resource::<DrawFunctions<AlphaMask3dPrepass>>()
.init_resource::<PrepassViewBindGroup>()
.init_resource::<SpecializedMeshPipelines<PrepassPipeline<M>>>()
.add_render_command::<Opaque3dPrepass, DrawPrepass<M>>()
.add_render_command::<AlphaMask3dPrepass, DrawPrepass<M>>();
}
Expand Down
7 changes: 7 additions & 0 deletions crates/bevy_pbr/src/prepass/prepass.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ fn vertex(vertex: Vertex) -> VertexOutput {
}

#ifdef NORMAL_PREPASS

struct FragmentInput {
@location(1) world_normal: vec3<f32>,
}
Expand All @@ -81,4 +82,10 @@ struct FragmentInput {
fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {
return vec4(in.world_normal * 0.5 + vec3(0.5), 1.0);
}

#else // NORMAL_PREPASS

@fragment
fn fragment(in: VertexOutput) {}
geieredgar marked this conversation as resolved.
Show resolved Hide resolved

#endif // NORMAL_PREPASS
11 changes: 11 additions & 0 deletions tests/3d/no_prepass.rs
Original file line number Diff line number Diff line change
@@ -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();
}