Skip to content

Commit

Permalink
Fix CameraProjection panic and improve CameraProjectionPlugin (#1…
Browse files Browse the repository at this point in the history
…1808)

# Objective

Fix #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
#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`
  • Loading branch information
doonv authored Apr 26, 2024
1 parent 75f1c5d commit de9dc9c
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 50 deletions.
34 changes: 28 additions & 6 deletions crates/bevy_pbr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
},
Expand All @@ -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),
Expand Down Expand Up @@ -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())
}
}
26 changes: 20 additions & 6 deletions crates/bevy_render/src/camera/projection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@ 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};
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>,
);
Expand All @@ -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),
),
);
}
}
Expand Down
43 changes: 5 additions & 38 deletions crates/bevy_render/src/view/visibility/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
};
Expand Down Expand Up @@ -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,
Expand All @@ -261,38 +254,14 @@ impl Plugin for VisibilityPlugin {

app.configure_sets(
PostUpdate,
(
CalculateBounds,
UpdateOrthographicFrusta,
UpdatePerspectiveFrusta,
UpdateProjectionFrusta,
VisibilityPropagate,
)
(CalculateBounds, UpdateFrusta, VisibilityPropagate)
.before(CheckVisibility)
.after(TransformSystem::TransformPropagate),
)
.add_systems(
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),
),
Expand Down Expand Up @@ -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),
Expand Down

0 comments on commit de9dc9c

Please sign in to comment.