Fix CameraProjection panic and improve CameraProjectionPlugin (#11808)

# Objective

Fix https://github.com/bevyengine/bevy/issues/11799 and improve
`CameraProjectionPlugin`

## Solution

`CameraProjectionPlugin` is now an all-in-one plugin for adding a custom
`CameraProjection`. I also added `PbrProjectionPlugin` which is like
`CameraProjectionPlugin` but for PBR.

P.S. I'd like to get this merged after
https://github.com/bevyengine/bevy/pull/11766.

---

## Changelog

- Changed `CameraProjectionPlugin` to be an all-in-one plugin for adding
a `CameraProjection`
- Removed `VisibilitySystems::{UpdateOrthographicFrusta,
UpdatePerspectiveFrusta, UpdateProjectionFrusta}`, now replaced with
`VisibilitySystems::UpdateFrusta`
- Added `PbrProjectionPlugin` for projection-specific PBR functionality.

## Migration Guide

`VisibilitySystems`'s `UpdateOrthographicFrusta`,
`UpdatePerspectiveFrusta`, and `UpdateProjectionFrusta` variants were
removed, they were replaced with `VisibilitySystems::UpdateFrusta`
This commit is contained in:
Doonv 2024-04-27 02:52:09 +03:00 committed by GitHub
parent 75f1c5df7d
commit de9dc9c204
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 53 additions and 50 deletions

View File

@ -36,6 +36,8 @@ mod render;
mod ssao; mod ssao;
use bevy_color::{Color, LinearRgba}; use bevy_color::{Color, LinearRgba};
use std::marker::PhantomData;
pub use bundle::*; pub use bundle::*;
pub use extended_material::*; pub use extended_material::*;
pub use fog::*; pub use fog::*;
@ -91,7 +93,10 @@ use bevy_core_pipeline::core_3d::graph::{Core3d, Node3d};
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use bevy_render::{ use bevy_render::{
alpha::AlphaMode, alpha::AlphaMode,
camera::{CameraUpdateSystem, Projection}, camera::{
CameraProjection, CameraUpdateSystem, OrthographicProjection, PerspectiveProjection,
Projection,
},
extract_component::ExtractComponentPlugin, extract_component::ExtractComponentPlugin,
extract_resource::ExtractResourcePlugin, extract_resource::ExtractResourcePlugin,
render_asset::prepare_assets, render_asset::prepare_assets,
@ -303,6 +308,9 @@ impl Plugin for PbrPlugin {
ExtractComponentPlugin::<ShadowFilteringMethod>::default(), ExtractComponentPlugin::<ShadowFilteringMethod>::default(),
LightmapPlugin, LightmapPlugin,
LightProbePlugin, LightProbePlugin,
PbrProjectionPlugin::<Projection>::default(),
PbrProjectionPlugin::<PerspectiveProjection>::default(),
PbrProjectionPlugin::<OrthographicProjection>::default(),
GpuMeshPreprocessPlugin { GpuMeshPreprocessPlugin {
use_gpu_instance_buffer_builder: self.use_gpu_instance_buffer_builder, use_gpu_instance_buffer_builder: self.use_gpu_instance_buffer_builder,
}, },
@ -324,11 +332,7 @@ impl Plugin for PbrPlugin {
.after(TransformSystem::TransformPropagate) .after(TransformSystem::TransformPropagate)
.after(VisibilitySystems::CheckVisibility) .after(VisibilitySystems::CheckVisibility)
.after(CameraUpdateSystem), .after(CameraUpdateSystem),
( clear_directional_light_cascades
clear_directional_light_cascades,
build_directional_light_cascades::<Projection>,
)
.chain()
.in_set(SimulationLightSystems::UpdateDirectionalLightCascades) .in_set(SimulationLightSystems::UpdateDirectionalLightCascades)
.after(TransformSystem::TransformPropagate) .after(TransformSystem::TransformPropagate)
.after(CameraUpdateSystem), .after(CameraUpdateSystem),
@ -414,3 +418,21 @@ impl Plugin for PbrPlugin {
.init_resource::<GlobalLightMeta>(); .init_resource::<GlobalLightMeta>();
} }
} }
/// [`CameraProjection`] specific PBR functionality.
pub struct PbrProjectionPlugin<T: CameraProjection + Component>(PhantomData<T>);
impl<T: CameraProjection + Component> Plugin for PbrProjectionPlugin<T> {
fn build(&self, app: &mut App) {
app.add_systems(
PostUpdate,
build_directional_light_cascades::<T>
.in_set(SimulationLightSystems::UpdateDirectionalLightCascades)
.after(clear_directional_light_cascades),
);
}
}
impl<T: CameraProjection + Component> Default for PbrProjectionPlugin<T> {
fn default() -> Self {
Self(Default::default())
}
}

View File

@ -2,6 +2,7 @@ use std::marker::PhantomData;
use std::ops::{Div, DivAssign, Mul, MulAssign}; use std::ops::{Div, DivAssign, Mul, MulAssign};
use crate::primitives::Frustum; use crate::primitives::Frustum;
use crate::view::VisibilitySystems;
use bevy_app::{App, Plugin, PostStartup, PostUpdate}; use bevy_app::{App, Plugin, PostStartup, PostUpdate};
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use bevy_math::{AspectRatio, Mat4, Rect, Vec2, Vec3A}; use bevy_math::{AspectRatio, Mat4, Rect, Vec2, Vec3A};
@ -9,9 +10,12 @@ use bevy_reflect::{
std_traits::ReflectDefault, GetTypeRegistration, Reflect, ReflectDeserialize, ReflectSerialize, std_traits::ReflectDefault, GetTypeRegistration, Reflect, ReflectDeserialize, ReflectSerialize,
}; };
use bevy_transform::components::GlobalTransform; use bevy_transform::components::GlobalTransform;
use bevy_transform::TransformSystem;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// Adds [`Camera`](crate::camera::Camera) driver systems for a given projection type. /// Adds [`Camera`](crate::camera::Camera) driver systems for a given projection type.
///
/// If you are using `bevy_pbr`, then you need to add `PbrProjectionPlugin` along with this.
pub struct CameraProjectionPlugin<T: CameraProjection + Component + GetTypeRegistration>( pub struct CameraProjectionPlugin<T: CameraProjection + Component + GetTypeRegistration>(
PhantomData<T>, PhantomData<T>,
); );
@ -29,12 +33,22 @@ impl<T: CameraProjection + Component + GetTypeRegistration> Plugin for CameraPro
) )
.add_systems( .add_systems(
PostUpdate, PostUpdate,
crate::camera::camera_system::<T> (
.in_set(CameraUpdateSystem) crate::camera::camera_system::<T>
// We assume that each camera will only have one projection, .in_set(CameraUpdateSystem)
// so we can ignore ambiguities with all other monomorphizations. // We assume that each camera will only have one projection,
// FIXME: Add an archetype invariant for this https://github.com/bevyengine/bevy/issues/1481. // so we can ignore ambiguities with all other monomorphizations.
.ambiguous_with(CameraUpdateSystem), // FIXME: Add an archetype invariant for this https://github.com/bevyengine/bevy/issues/1481.
.ambiguous_with(CameraUpdateSystem),
crate::view::update_frusta::<T>
.in_set(VisibilitySystems::UpdateFrusta)
.after(crate::camera::camera_system::<T>)
.after(TransformSystem::TransformPropagate)
// We assume that no camera will have more than one projection component,
// so these systems will run independently of one another.
// FIXME: Add an archetype invariant for this https://github.com/bevyengine/bevy/issues/1481.
.ambiguous_with(VisibilitySystems::UpdateFrusta),
),
); );
} }
} }

View File

@ -15,10 +15,7 @@ use bevy_transform::{components::GlobalTransform, TransformSystem};
use bevy_utils::{Parallel, TypeIdMap}; use bevy_utils::{Parallel, TypeIdMap};
use crate::{ use crate::{
camera::{ camera::{Camera, CameraProjection},
camera_system, Camera, CameraProjection, OrthographicProjection, PerspectiveProjection,
Projection,
},
mesh::Mesh, mesh::Mesh,
primitives::{Aabb, Frustum, Sphere}, primitives::{Aabb, Frustum, Sphere},
}; };
@ -239,12 +236,8 @@ pub enum VisibilitySystems {
/// Label for the [`calculate_bounds`], `calculate_bounds_2d` and `calculate_bounds_text2d` systems, /// Label for the [`calculate_bounds`], `calculate_bounds_2d` and `calculate_bounds_text2d` systems,
/// calculating and inserting an [`Aabb`] to relevant entities. /// calculating and inserting an [`Aabb`] to relevant entities.
CalculateBounds, CalculateBounds,
/// Label for the [`update_frusta<OrthographicProjection>`] system. /// Label for [`update_frusta`] in [`CameraProjectionPlugin`](crate::camera::CameraProjectionPlugin).
UpdateOrthographicFrusta, UpdateFrusta,
/// Label for the [`update_frusta<PerspectiveProjection>`] system.
UpdatePerspectiveFrusta,
/// Label for the [`update_frusta<Projection>`] system.
UpdateProjectionFrusta,
/// Label for the system propagating the [`InheritedVisibility`] in a /// Label for the system propagating the [`InheritedVisibility`] in a
/// [`hierarchy`](bevy_hierarchy). /// [`hierarchy`](bevy_hierarchy).
VisibilityPropagate, VisibilityPropagate,
@ -261,13 +254,7 @@ impl Plugin for VisibilityPlugin {
app.configure_sets( app.configure_sets(
PostUpdate, PostUpdate,
( (CalculateBounds, UpdateFrusta, VisibilityPropagate)
CalculateBounds,
UpdateOrthographicFrusta,
UpdatePerspectiveFrusta,
UpdateProjectionFrusta,
VisibilityPropagate,
)
.before(CheckVisibility) .before(CheckVisibility)
.after(TransformSystem::TransformPropagate), .after(TransformSystem::TransformPropagate),
) )
@ -275,24 +262,6 @@ impl Plugin for VisibilityPlugin {
PostUpdate, PostUpdate,
( (
calculate_bounds.in_set(CalculateBounds), calculate_bounds.in_set(CalculateBounds),
update_frusta::<OrthographicProjection>
.in_set(UpdateOrthographicFrusta)
.after(camera_system::<OrthographicProjection>)
// We assume that no camera will have more than one projection component,
// so these systems will run independently of one another.
// FIXME: Add an archetype invariant for this https://github.com/bevyengine/bevy/issues/1481.
.ambiguous_with(update_frusta::<PerspectiveProjection>)
.ambiguous_with(update_frusta::<Projection>),
update_frusta::<PerspectiveProjection>
.in_set(UpdatePerspectiveFrusta)
.after(camera_system::<PerspectiveProjection>)
// We assume that no camera will have more than one projection component,
// so these systems will run independently of one another.
// FIXME: Add an archetype invariant for this https://github.com/bevyengine/bevy/issues/1481.
.ambiguous_with(update_frusta::<Projection>),
update_frusta::<Projection>
.in_set(UpdateProjectionFrusta)
.after(camera_system::<Projection>),
(visibility_propagate_system, reset_view_visibility).in_set(VisibilityPropagate), (visibility_propagate_system, reset_view_visibility).in_set(VisibilityPropagate),
check_visibility::<WithMesh>.in_set(CheckVisibility), check_visibility::<WithMesh>.in_set(CheckVisibility),
), ),
@ -320,9 +289,7 @@ pub fn calculate_bounds(
/// Updates [`Frustum`]. /// Updates [`Frustum`].
/// ///
/// This system is used in system sets [`VisibilitySystems::UpdateProjectionFrusta`], /// This system is used in [`CameraProjectionPlugin`](crate::camera::CameraProjectionPlugin).
/// [`VisibilitySystems::UpdatePerspectiveFrusta`], and
/// [`VisibilitySystems::UpdateOrthographicFrusta`].
pub fn update_frusta<T: Component + CameraProjection + Send + Sync + 'static>( pub fn update_frusta<T: Component + CameraProjection + Send + Sync + 'static>(
mut views: Query< mut views: Query<
(&GlobalTransform, &T, &mut Frustum), (&GlobalTransform, &T, &mut Frustum),