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;
use bevy_color::{Color, LinearRgba};
use std::marker::PhantomData;
pub use bundle::*;
pub use extended_material::*;
pub use fog::*;
@ -91,7 +93,10 @@ use bevy_core_pipeline::core_3d::graph::{Core3d, Node3d};
use bevy_ecs::prelude::*;
use bevy_render::{
alpha::AlphaMode,
camera::{CameraUpdateSystem, Projection},
camera::{
CameraProjection, CameraUpdateSystem, OrthographicProjection, PerspectiveProjection,
Projection,
},
extract_component::ExtractComponentPlugin,
extract_resource::ExtractResourcePlugin,
render_asset::prepare_assets,
@ -303,6 +308,9 @@ impl Plugin for PbrPlugin {
ExtractComponentPlugin::<ShadowFilteringMethod>::default(),
LightmapPlugin,
LightProbePlugin,
PbrProjectionPlugin::<Projection>::default(),
PbrProjectionPlugin::<PerspectiveProjection>::default(),
PbrProjectionPlugin::<OrthographicProjection>::default(),
GpuMeshPreprocessPlugin {
use_gpu_instance_buffer_builder: self.use_gpu_instance_buffer_builder,
},
@ -324,11 +332,7 @@ impl Plugin for PbrPlugin {
.after(TransformSystem::TransformPropagate)
.after(VisibilitySystems::CheckVisibility)
.after(CameraUpdateSystem),
(
clear_directional_light_cascades,
build_directional_light_cascades::<Projection>,
)
.chain()
clear_directional_light_cascades
.in_set(SimulationLightSystems::UpdateDirectionalLightCascades)
.after(TransformSystem::TransformPropagate)
.after(CameraUpdateSystem),
@ -414,3 +418,21 @@ impl Plugin for PbrPlugin {
.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 crate::primitives::Frustum;
use crate::view::VisibilitySystems;
use bevy_app::{App, Plugin, PostStartup, PostUpdate};
use bevy_ecs::prelude::*;
use bevy_math::{AspectRatio, Mat4, Rect, Vec2, Vec3A};
@ -9,9 +10,12 @@ use bevy_reflect::{
std_traits::ReflectDefault, GetTypeRegistration, Reflect, ReflectDeserialize, ReflectSerialize,
};
use bevy_transform::components::GlobalTransform;
use bevy_transform::TransformSystem;
use serde::{Deserialize, Serialize};
/// 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>(
PhantomData<T>,
);
@ -29,12 +33,22 @@ impl<T: CameraProjection + Component + GetTypeRegistration> Plugin for CameraPro
)
.add_systems(
PostUpdate,
crate::camera::camera_system::<T>
.in_set(CameraUpdateSystem)
// We assume that each camera will only have one projection,
// so we can ignore ambiguities with all other monomorphizations.
// FIXME: Add an archetype invariant for this https://github.com/bevyengine/bevy/issues/1481.
.ambiguous_with(CameraUpdateSystem),
(
crate::camera::camera_system::<T>
.in_set(CameraUpdateSystem)
// We assume that each camera will only have one projection,
// so we can ignore ambiguities with all other monomorphizations.
// 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 crate::{
camera::{
camera_system, Camera, CameraProjection, OrthographicProjection, PerspectiveProjection,
Projection,
},
camera::{Camera, CameraProjection},
mesh::Mesh,
primitives::{Aabb, Frustum, Sphere},
};
@ -239,12 +236,8 @@ pub enum VisibilitySystems {
/// Label for the [`calculate_bounds`], `calculate_bounds_2d` and `calculate_bounds_text2d` systems,
/// calculating and inserting an [`Aabb`] to relevant entities.
CalculateBounds,
/// Label for the [`update_frusta<OrthographicProjection>`] system.
UpdateOrthographicFrusta,
/// Label for the [`update_frusta<PerspectiveProjection>`] system.
UpdatePerspectiveFrusta,
/// Label for the [`update_frusta<Projection>`] system.
UpdateProjectionFrusta,
/// Label for [`update_frusta`] in [`CameraProjectionPlugin`](crate::camera::CameraProjectionPlugin).
UpdateFrusta,
/// Label for the system propagating the [`InheritedVisibility`] in a
/// [`hierarchy`](bevy_hierarchy).
VisibilityPropagate,
@ -261,13 +254,7 @@ impl Plugin for VisibilityPlugin {
app.configure_sets(
PostUpdate,
(
CalculateBounds,
UpdateOrthographicFrusta,
UpdatePerspectiveFrusta,
UpdateProjectionFrusta,
VisibilityPropagate,
)
(CalculateBounds, UpdateFrusta, VisibilityPropagate)
.before(CheckVisibility)
.after(TransformSystem::TransformPropagate),
)
@ -275,24 +262,6 @@ impl Plugin for VisibilityPlugin {
PostUpdate,
(
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),
check_visibility::<WithMesh>.in_set(CheckVisibility),
),
@ -320,9 +289,7 @@ pub fn calculate_bounds(
/// Updates [`Frustum`].
///
/// This system is used in system sets [`VisibilitySystems::UpdateProjectionFrusta`],
/// [`VisibilitySystems::UpdatePerspectiveFrusta`], and
/// [`VisibilitySystems::UpdateOrthographicFrusta`].
/// This system is used in [`CameraProjectionPlugin`](crate::camera::CameraProjectionPlugin).
pub fn update_frusta<T: Component + CameraProjection + Send + Sync + 'static>(
mut views: Query<
(&GlobalTransform, &T, &mut Frustum),