From de9dc9c20451f13a0ad0d3f122b46c84a45c2c18 Mon Sep 17 00:00:00 2001 From: Doonv <58695417+doonv@users.noreply.github.com> Date: Sat, 27 Apr 2024 02:52:09 +0300 Subject: [PATCH] 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` --- crates/bevy_pbr/src/lib.rs | 34 ++++++++++++--- crates/bevy_render/src/camera/projection.rs | 26 ++++++++--- crates/bevy_render/src/view/visibility/mod.rs | 43 +++---------------- 3 files changed, 53 insertions(+), 50 deletions(-) diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index 2904b5bb54357..8c5078f1fe245 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -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::::default(), LightmapPlugin, LightProbePlugin, + PbrProjectionPlugin::::default(), + PbrProjectionPlugin::::default(), + PbrProjectionPlugin::::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::, - ) - .chain() + clear_directional_light_cascades .in_set(SimulationLightSystems::UpdateDirectionalLightCascades) .after(TransformSystem::TransformPropagate) .after(CameraUpdateSystem), @@ -414,3 +418,21 @@ impl Plugin for PbrPlugin { .init_resource::(); } } + +/// [`CameraProjection`] specific PBR functionality. +pub struct PbrProjectionPlugin(PhantomData); +impl Plugin for PbrProjectionPlugin { + fn build(&self, app: &mut App) { + app.add_systems( + PostUpdate, + build_directional_light_cascades:: + .in_set(SimulationLightSystems::UpdateDirectionalLightCascades) + .after(clear_directional_light_cascades), + ); + } +} +impl Default for PbrProjectionPlugin { + fn default() -> Self { + Self(Default::default()) + } +} diff --git a/crates/bevy_render/src/camera/projection.rs b/crates/bevy_render/src/camera/projection.rs index 225fd15b7750b..2ea1dc5535fcd 100644 --- a/crates/bevy_render/src/camera/projection.rs +++ b/crates/bevy_render/src/camera/projection.rs @@ -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( PhantomData, ); @@ -29,12 +33,22 @@ impl Plugin for CameraPro ) .add_systems( PostUpdate, - crate::camera::camera_system:: - .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:: + .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:: + .in_set(VisibilitySystems::UpdateFrusta) + .after(crate::camera::camera_system::) + .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), + ), ); } } diff --git a/crates/bevy_render/src/view/visibility/mod.rs b/crates/bevy_render/src/view/visibility/mod.rs index aa2982ca423a1..72ba3c16a8681 100644 --- a/crates/bevy_render/src/view/visibility/mod.rs +++ b/crates/bevy_render/src/view/visibility/mod.rs @@ -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`] system. - UpdateOrthographicFrusta, - /// Label for the [`update_frusta`] system. - UpdatePerspectiveFrusta, - /// Label for the [`update_frusta`] 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:: - .in_set(UpdateOrthographicFrusta) - .after(camera_system::) - // 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::) - .ambiguous_with(update_frusta::), - update_frusta:: - .in_set(UpdatePerspectiveFrusta) - .after(camera_system::) - // 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::), - update_frusta:: - .in_set(UpdateProjectionFrusta) - .after(camera_system::), (visibility_propagate_system, reset_view_visibility).in_set(VisibilityPropagate), check_visibility::.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( mut views: Query< (&GlobalTransform, &T, &mut Frustum),