mirror of
https://github.com/bevyengine/bevy
synced 2024-09-20 06:22:01 +00:00
allow DeferredPrepass to work without other prepass markers (#10223)
# Objective fix crash / misbehaviour when `DeferredPrepass` is used without `DepthPrepass`. - Deferred lighting requires the depth prepass texture to be present, so that the depth texture is available for binding. without it the deferred lighting pass will use 0 for depth of all meshes. - When `DeferredPrepass` is used without other prepass markers, and with any materials that use `OpaqueRenderMode::Forward`, those entities will try to queue to the `Opaque3dPrepass` render phase, which doesn't exist, causing a crash. ## Solution - check if the prepass phases exist before queueing - generate prepass textures if `Opaque3dDeferred` is present - add a note to the DeferredPrepass marker to note that DepthPrepass is also required by the default deferred lighting pass - also changed some `With<T>.is_some()`s to `Has<T>`s
This commit is contained in:
parent
74b5073f75
commit
5cc3352f5b
3 changed files with 30 additions and 33 deletions
|
@ -450,10 +450,10 @@ pub fn extract_camera_prepass_phase(
|
||||||
(
|
(
|
||||||
Entity,
|
Entity,
|
||||||
&Camera,
|
&Camera,
|
||||||
Option<&DepthPrepass>,
|
Has<DepthPrepass>,
|
||||||
Option<&NormalPrepass>,
|
Has<NormalPrepass>,
|
||||||
Option<&MotionVectorPrepass>,
|
Has<MotionVectorPrepass>,
|
||||||
Option<&DeferredPrepass>,
|
Has<DeferredPrepass>,
|
||||||
),
|
),
|
||||||
With<Camera3d>,
|
With<Camera3d>,
|
||||||
>,
|
>,
|
||||||
|
@ -465,33 +465,30 @@ pub fn extract_camera_prepass_phase(
|
||||||
if camera.is_active {
|
if camera.is_active {
|
||||||
let mut entity = commands.get_or_spawn(entity);
|
let mut entity = commands.get_or_spawn(entity);
|
||||||
|
|
||||||
if depth_prepass.is_some()
|
if depth_prepass || normal_prepass || motion_vector_prepass {
|
||||||
|| normal_prepass.is_some()
|
|
||||||
|| motion_vector_prepass.is_some()
|
|
||||||
{
|
|
||||||
entity.insert((
|
entity.insert((
|
||||||
RenderPhase::<Opaque3dPrepass>::default(),
|
RenderPhase::<Opaque3dPrepass>::default(),
|
||||||
RenderPhase::<AlphaMask3dPrepass>::default(),
|
RenderPhase::<AlphaMask3dPrepass>::default(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if deferred_prepass.is_some() {
|
if deferred_prepass {
|
||||||
entity.insert((
|
entity.insert((
|
||||||
RenderPhase::<Opaque3dDeferred>::default(),
|
RenderPhase::<Opaque3dDeferred>::default(),
|
||||||
RenderPhase::<AlphaMask3dDeferred>::default(),
|
RenderPhase::<AlphaMask3dDeferred>::default(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if depth_prepass.is_some() {
|
if depth_prepass {
|
||||||
entity.insert(DepthPrepass);
|
entity.insert(DepthPrepass);
|
||||||
}
|
}
|
||||||
if normal_prepass.is_some() {
|
if normal_prepass {
|
||||||
entity.insert(NormalPrepass);
|
entity.insert(NormalPrepass);
|
||||||
}
|
}
|
||||||
if motion_vector_prepass.is_some() {
|
if motion_vector_prepass {
|
||||||
entity.insert(MotionVectorPrepass);
|
entity.insert(MotionVectorPrepass);
|
||||||
}
|
}
|
||||||
if deferred_prepass.is_some() {
|
if deferred_prepass {
|
||||||
entity.insert(DeferredPrepass);
|
entity.insert(DeferredPrepass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -685,15 +682,17 @@ pub fn prepare_prepass_textures(
|
||||||
(
|
(
|
||||||
Entity,
|
Entity,
|
||||||
&ExtractedCamera,
|
&ExtractedCamera,
|
||||||
Option<&DepthPrepass>,
|
Has<DepthPrepass>,
|
||||||
Option<&NormalPrepass>,
|
Has<NormalPrepass>,
|
||||||
Option<&MotionVectorPrepass>,
|
Has<MotionVectorPrepass>,
|
||||||
Option<&DeferredPrepass>,
|
Has<DeferredPrepass>,
|
||||||
),
|
),
|
||||||
(
|
Or<(
|
||||||
With<RenderPhase<Opaque3dPrepass>>,
|
With<RenderPhase<Opaque3dPrepass>>,
|
||||||
With<RenderPhase<AlphaMask3dPrepass>>,
|
With<RenderPhase<AlphaMask3dPrepass>>,
|
||||||
),
|
With<RenderPhase<Opaque3dDeferred>>,
|
||||||
|
With<RenderPhase<AlphaMask3dDeferred>>,
|
||||||
|
)>,
|
||||||
>,
|
>,
|
||||||
) {
|
) {
|
||||||
let mut depth_textures = HashMap::default();
|
let mut depth_textures = HashMap::default();
|
||||||
|
@ -714,7 +713,7 @@ pub fn prepare_prepass_textures(
|
||||||
height: physical_target_size.y,
|
height: physical_target_size.y,
|
||||||
};
|
};
|
||||||
|
|
||||||
let cached_depth_texture = depth_prepass.is_some().then(|| {
|
let cached_depth_texture = depth_prepass.then(|| {
|
||||||
depth_textures
|
depth_textures
|
||||||
.entry(camera.target.clone())
|
.entry(camera.target.clone())
|
||||||
.or_insert_with(|| {
|
.or_insert_with(|| {
|
||||||
|
@ -735,7 +734,7 @@ pub fn prepare_prepass_textures(
|
||||||
.clone()
|
.clone()
|
||||||
});
|
});
|
||||||
|
|
||||||
let cached_normals_texture = normal_prepass.is_some().then(|| {
|
let cached_normals_texture = normal_prepass.then(|| {
|
||||||
normal_textures
|
normal_textures
|
||||||
.entry(camera.target.clone())
|
.entry(camera.target.clone())
|
||||||
.or_insert_with(|| {
|
.or_insert_with(|| {
|
||||||
|
@ -757,7 +756,7 @@ pub fn prepare_prepass_textures(
|
||||||
.clone()
|
.clone()
|
||||||
});
|
});
|
||||||
|
|
||||||
let cached_motion_vectors_texture = motion_vector_prepass.is_some().then(|| {
|
let cached_motion_vectors_texture = motion_vector_prepass.then(|| {
|
||||||
motion_vectors_textures
|
motion_vectors_textures
|
||||||
.entry(camera.target.clone())
|
.entry(camera.target.clone())
|
||||||
.or_insert_with(|| {
|
.or_insert_with(|| {
|
||||||
|
@ -779,7 +778,7 @@ pub fn prepare_prepass_textures(
|
||||||
.clone()
|
.clone()
|
||||||
});
|
});
|
||||||
|
|
||||||
let cached_deferred_texture = deferred_prepass.is_some().then(|| {
|
let cached_deferred_texture = deferred_prepass.then(|| {
|
||||||
deferred_textures
|
deferred_textures
|
||||||
.entry(camera.target.clone())
|
.entry(camera.target.clone())
|
||||||
.or_insert_with(|| {
|
.or_insert_with(|| {
|
||||||
|
@ -801,7 +800,7 @@ pub fn prepare_prepass_textures(
|
||||||
.clone()
|
.clone()
|
||||||
});
|
});
|
||||||
|
|
||||||
let deferred_lighting_pass_id_texture = deferred_prepass.is_some().then(|| {
|
let deferred_lighting_pass_id_texture = deferred_prepass.then(|| {
|
||||||
deferred_lighting_id_textures
|
deferred_lighting_id_textures
|
||||||
.entry(camera.target.clone())
|
.entry(camera.target.clone())
|
||||||
.or_insert_with(|| {
|
.or_insert_with(|| {
|
||||||
|
|
|
@ -55,6 +55,7 @@ pub struct NormalPrepass;
|
||||||
pub struct MotionVectorPrepass;
|
pub struct MotionVectorPrepass;
|
||||||
|
|
||||||
/// If added to a [`crate::prelude::Camera3d`] then deferred materials will be rendered to the deferred gbuffer texture and will be available to subsequent passes.
|
/// If added to a [`crate::prelude::Camera3d`] then deferred materials will be rendered to the deferred gbuffer texture and will be available to subsequent passes.
|
||||||
|
/// Note the default deferred lighting plugin also requires `DepthPrepass` to work correctly.
|
||||||
#[derive(Component, Default, Reflect)]
|
#[derive(Component, Default, Reflect)]
|
||||||
pub struct DeferredPrepass;
|
pub struct DeferredPrepass;
|
||||||
|
|
||||||
|
|
|
@ -784,9 +784,6 @@ pub fn queue_prepass_material_meshes<M: Material>(
|
||||||
view_key |= MeshPipelineKey::MOTION_VECTOR_PREPASS;
|
view_key |= MeshPipelineKey::MOTION_VECTOR_PREPASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut opaque_phase_deferred = opaque_deferred_phase.as_mut();
|
|
||||||
let mut alpha_mask_phase_deferred = alpha_mask_deferred_phase.as_mut();
|
|
||||||
|
|
||||||
let rangefinder = view.rangefinder3d();
|
let rangefinder = view.rangefinder3d();
|
||||||
|
|
||||||
for visible_entity in &visible_entities.entities {
|
for visible_entity in &visible_entities.entities {
|
||||||
|
@ -859,7 +856,7 @@ pub fn queue_prepass_material_meshes<M: Material>(
|
||||||
match alpha_mode {
|
match alpha_mode {
|
||||||
AlphaMode::Opaque => {
|
AlphaMode::Opaque => {
|
||||||
if deferred {
|
if deferred {
|
||||||
opaque_phase_deferred
|
opaque_deferred_phase
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.add(Opaque3dDeferred {
|
.add(Opaque3dDeferred {
|
||||||
|
@ -870,8 +867,8 @@ pub fn queue_prepass_material_meshes<M: Material>(
|
||||||
batch_range: 0..1,
|
batch_range: 0..1,
|
||||||
dynamic_offset: None,
|
dynamic_offset: None,
|
||||||
});
|
});
|
||||||
} else {
|
} else if let Some(opaque_phase) = opaque_phase.as_mut() {
|
||||||
opaque_phase.as_mut().unwrap().add(Opaque3dPrepass {
|
opaque_phase.add(Opaque3dPrepass {
|
||||||
entity: *visible_entity,
|
entity: *visible_entity,
|
||||||
draw_function: opaque_draw_prepass,
|
draw_function: opaque_draw_prepass,
|
||||||
pipeline_id,
|
pipeline_id,
|
||||||
|
@ -883,7 +880,7 @@ pub fn queue_prepass_material_meshes<M: Material>(
|
||||||
}
|
}
|
||||||
AlphaMode::Mask(_) => {
|
AlphaMode::Mask(_) => {
|
||||||
if deferred {
|
if deferred {
|
||||||
alpha_mask_phase_deferred
|
alpha_mask_deferred_phase
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.add(AlphaMask3dDeferred {
|
.add(AlphaMask3dDeferred {
|
||||||
|
@ -894,8 +891,8 @@ pub fn queue_prepass_material_meshes<M: Material>(
|
||||||
batch_range: 0..1,
|
batch_range: 0..1,
|
||||||
dynamic_offset: None,
|
dynamic_offset: None,
|
||||||
});
|
});
|
||||||
} else {
|
} else if let Some(alpha_mask_phase) = alpha_mask_phase.as_mut() {
|
||||||
alpha_mask_phase.as_mut().unwrap().add(AlphaMask3dPrepass {
|
alpha_mask_phase.add(AlphaMask3dPrepass {
|
||||||
entity: *visible_entity,
|
entity: *visible_entity,
|
||||||
draw_function: alpha_mask_draw_prepass,
|
draw_function: alpha_mask_draw_prepass,
|
||||||
pipeline_id,
|
pipeline_id,
|
||||||
|
|
Loading…
Reference in a new issue