Move Camera3d/2d to bevy_camera (#19953)

# Objective

- define scenes without bevy_render

## Solution

- Move Camera2d/3d components out of bevy_core_pipeline

## Testing

- 3d_scene runs fine

Note: no breaking changes thanks to re-exports
This commit is contained in:
atlv 2025-07-05 09:24:28 -04:00 committed by GitHub
parent bfbc6c3d11
commit 1b09c4051e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 63 additions and 59 deletions

View File

@ -1,39 +1,33 @@
use crate::{ use crate::{primitives::Frustum, Camera, CameraProjection, OrthographicProjection, Projection};
core_3d::graph::Core3d,
tonemapping::{DebandDither, Tonemapping},
};
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use bevy_reflect::{std_traits::ReflectDefault, Reflect, ReflectDeserialize, ReflectSerialize}; use bevy_reflect::{std_traits::ReflectDefault, Reflect, ReflectDeserialize, ReflectSerialize};
use bevy_render::{ use bevy_transform::prelude::{GlobalTransform, Transform};
camera::{Camera, CameraRenderGraph, Exposure, Projection},
extract_component::ExtractComponent,
render_resource::{LoadOp, TextureUsages},
view::ColorGrading,
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use wgpu_types::{LoadOp, TextureUsages};
/// A 2D camera component. Enables the 2D render graph for a [`Camera`].
#[derive(Component, Default, Reflect, Clone)]
#[reflect(Component, Default, Clone)]
#[require(
Camera,
Projection::Orthographic(OrthographicProjection::default_2d()),
Frustum = OrthographicProjection::default_2d().compute_frustum(&GlobalTransform::from(Transform::default())),
)]
pub struct Camera2d;
/// A 3D camera component. Enables the main 3D render graph for a [`Camera`]. /// A 3D camera component. Enables the main 3D render graph for a [`Camera`].
/// ///
/// The camera coordinate space is right-handed X-right, Y-up, Z-back. /// The camera coordinate space is right-handed X-right, Y-up, Z-back.
/// This means "forward" is -Z. /// This means "forward" is -Z.
#[derive(Component, Reflect, Clone, ExtractComponent)] #[derive(Component, Reflect, Clone)]
#[extract_component_filter(With<Camera>)]
#[reflect(Component, Default, Clone)] #[reflect(Component, Default, Clone)]
#[require( #[require(Camera, Projection)]
Camera,
DebandDither::Enabled,
CameraRenderGraph::new(Core3d),
Projection,
Tonemapping,
ColorGrading,
Exposure
)]
pub struct Camera3d { pub struct Camera3d {
/// The depth clear operation to perform for the main 3d pass. /// The depth clear operation to perform for the main 3d pass.
pub depth_load_op: Camera3dDepthLoadOp, pub depth_load_op: Camera3dDepthLoadOp,
/// The texture usages for the depth texture created for the main 3d pass. /// The texture usages for the depth texture created for the main 3d pass.
pub depth_texture_usages: Camera3dDepthTextureUsage, pub depth_texture_usages: Camera3dDepthTextureUsage,
/// How many individual steps should be performed in the [`Transmissive3d`](crate::core_3d::Transmissive3d) pass. /// How many individual steps should be performed in the `Transmissive3d` pass.
/// ///
/// Roughly corresponds to how many “layers of transparency” are rendered for screen space /// Roughly corresponds to how many “layers of transparency” are rendered for screen space
/// specular transmissive objects. Each step requires making one additional /// specular transmissive objects. Each step requires making one additional

View File

@ -1,12 +1,14 @@
#![expect(missing_docs, reason = "Not all docs are written yet, see #3492.")] #![expect(missing_docs, reason = "Not all docs are written yet, see #3492.")]
mod camera; mod camera;
mod clear_color; mod clear_color;
mod components;
pub mod primitives; pub mod primitives;
mod projection; mod projection;
pub mod visibility; pub mod visibility;
pub use camera::*; pub use camera::*;
pub use clear_color::*; pub use clear_color::*;
pub use components::*;
pub use projection::*; pub use projection::*;
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};

View File

@ -27,6 +27,7 @@ bevy_derive = { path = "../bevy_derive", version = "0.17.0-dev" }
bevy_diagnostic = { path = "../bevy_diagnostic", version = "0.17.0-dev" } bevy_diagnostic = { path = "../bevy_diagnostic", version = "0.17.0-dev" }
bevy_ecs = { path = "../bevy_ecs", version = "0.17.0-dev" } bevy_ecs = { path = "../bevy_ecs", version = "0.17.0-dev" }
bevy_image = { path = "../bevy_image", version = "0.17.0-dev" } bevy_image = { path = "../bevy_image", version = "0.17.0-dev" }
bevy_camera = { path = "../bevy_camera", version = "0.17.0-dev" }
bevy_reflect = { path = "../bevy_reflect", version = "0.17.0-dev" } bevy_reflect = { path = "../bevy_reflect", version = "0.17.0-dev" }
bevy_render = { path = "../bevy_render", version = "0.17.0-dev" } bevy_render = { path = "../bevy_render", version = "0.17.0-dev" }
bevy_transform = { path = "../bevy_transform", version = "0.17.0-dev" } bevy_transform = { path = "../bevy_transform", version = "0.17.0-dev" }

View File

@ -1,26 +0,0 @@
use crate::{
core_2d::graph::Core2d,
tonemapping::{DebandDither, Tonemapping},
};
use bevy_ecs::prelude::*;
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_render::{
camera::{Camera, CameraProjection, CameraRenderGraph, OrthographicProjection, Projection},
extract_component::ExtractComponent,
primitives::Frustum,
};
use bevy_transform::prelude::{GlobalTransform, Transform};
/// A 2D camera component. Enables the 2D render graph for a [`Camera`].
#[derive(Component, Default, Reflect, Clone, ExtractComponent)]
#[extract_component_filter(With<Camera>)]
#[reflect(Component, Default, Clone)]
#[require(
Camera,
DebandDither,
CameraRenderGraph::new(Core2d),
Projection::Orthographic(OrthographicProjection::default_2d()),
Frustum = OrthographicProjection::default_2d().compute_frustum(&GlobalTransform::from(Transform::default())),
Tonemapping::None,
)]
pub struct Camera2d;

View File

@ -1,4 +1,3 @@
mod camera_2d;
mod main_opaque_pass_2d_node; mod main_opaque_pass_2d_node;
mod main_transparent_pass_2d_node; mod main_transparent_pass_2d_node;
@ -34,18 +33,22 @@ pub mod graph {
use core::ops::Range; use core::ops::Range;
use bevy_asset::UntypedAssetId; use bevy_asset::UntypedAssetId;
pub use bevy_camera::Camera2d;
use bevy_image::ToExtents; use bevy_image::ToExtents;
use bevy_platform::collections::{HashMap, HashSet}; use bevy_platform::collections::{HashMap, HashSet};
use bevy_render::{ use bevy_render::{
batching::gpu_preprocessing::GpuPreprocessingMode, batching::gpu_preprocessing::GpuPreprocessingMode,
camera::CameraRenderGraph,
render_phase::PhaseItemBatchSetKey, render_phase::PhaseItemBatchSetKey,
view::{ExtractedView, RetainedViewEntity}, view::{ExtractedView, RetainedViewEntity},
}; };
pub use camera_2d::*;
pub use main_opaque_pass_2d_node::*; pub use main_opaque_pass_2d_node::*;
pub use main_transparent_pass_2d_node::*; pub use main_transparent_pass_2d_node::*;
use crate::{tonemapping::TonemappingNode, upscaling::UpscalingNode}; use crate::{
tonemapping::{DebandDither, Tonemapping, TonemappingNode},
upscaling::UpscalingNode,
};
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use bevy_math::FloatOrd; use bevy_math::FloatOrd;
@ -78,6 +81,11 @@ pub struct Core2dPlugin;
impl Plugin for Core2dPlugin { impl Plugin for Core2dPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.register_type::<Camera2d>() app.register_type::<Camera2d>()
.register_required_components::<Camera2d, DebandDither>()
.register_required_components_with::<Camera2d, CameraRenderGraph>(|| {
CameraRenderGraph::new(Core2d)
})
.register_required_components_with::<Camera2d, Tonemapping>(|| Tonemapping::None)
.add_plugins(ExtractComponentPlugin::<Camera2d>::default()); .add_plugins(ExtractComponentPlugin::<Camera2d>::default());
let Some(render_app) = app.get_sub_app_mut(RenderApp) else { let Some(render_app) = app.get_sub_app_mut(RenderApp) else {

View File

@ -1,4 +1,3 @@
mod camera_3d;
mod main_opaque_pass_3d_node; mod main_opaque_pass_3d_node;
mod main_transmissive_pass_3d_node; mod main_transmissive_pass_3d_node;
mod main_transparent_pass_3d_node; mod main_transparent_pass_3d_node;
@ -70,14 +69,17 @@ pub const DEPTH_TEXTURE_SAMPLING_SUPPORTED: bool = true;
use core::ops::Range; use core::ops::Range;
pub use bevy_camera::{
Camera3d, Camera3dDepthLoadOp, Camera3dDepthTextureUsage, ScreenSpaceTransmissionQuality,
};
use bevy_render::{ use bevy_render::{
batching::gpu_preprocessing::{GpuPreprocessingMode, GpuPreprocessingSupport}, batching::gpu_preprocessing::{GpuPreprocessingMode, GpuPreprocessingSupport},
camera::CameraRenderGraph,
experimental::occlusion_culling::OcclusionCulling, experimental::occlusion_culling::OcclusionCulling,
mesh::allocator::SlabId, mesh::allocator::SlabId,
render_phase::PhaseItemBatchSetKey, render_phase::PhaseItemBatchSetKey,
view::{prepare_view_targets, NoIndirectDrawing, RetainedViewEntity}, view::{prepare_view_targets, NoIndirectDrawing, RetainedViewEntity},
}; };
pub use camera_3d::*;
pub use main_opaque_pass_3d_node::*; pub use main_opaque_pass_3d_node::*;
pub use main_transparent_pass_3d_node::*; pub use main_transparent_pass_3d_node::*;
@ -127,7 +129,7 @@ use crate::{
ViewPrepassTextures, MOTION_VECTOR_PREPASS_FORMAT, NORMAL_PREPASS_FORMAT, ViewPrepassTextures, MOTION_VECTOR_PREPASS_FORMAT, NORMAL_PREPASS_FORMAT,
}, },
skybox::SkyboxPlugin, skybox::SkyboxPlugin,
tonemapping::TonemappingNode, tonemapping::{DebandDither, Tonemapping, TonemappingNode},
upscaling::UpscalingNode, upscaling::UpscalingNode,
}; };
@ -139,6 +141,11 @@ impl Plugin for Core3dPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.register_type::<Camera3d>() app.register_type::<Camera3d>()
.register_type::<ScreenSpaceTransmissionQuality>() .register_type::<ScreenSpaceTransmissionQuality>()
.register_required_components_with::<Camera3d, DebandDither>(|| DebandDither::Enabled)
.register_required_components_with::<Camera3d, CameraRenderGraph>(|| {
CameraRenderGraph::new(Core3d)
})
.register_required_components::<Camera3d, Tonemapping>()
.add_plugins((SkyboxPlugin, ExtractComponentPlugin::<Camera3d>::default())) .add_plugins((SkyboxPlugin, ExtractComponentPlugin::<Camera3d>::default()))
.add_systems(PostUpdate, check_msaa); .add_systems(PostUpdate, check_msaa);

View File

@ -29,7 +29,7 @@ use bevy_ecs::{
event::EventReader, event::EventReader,
lifecycle::HookContext, lifecycle::HookContext,
prelude::With, prelude::With,
query::Has, query::{Has, QueryItem},
reflect::ReflectComponent, reflect::ReflectComponent,
resource::Resource, resource::Resource,
schedule::IntoScheduleConfigs, schedule::IntoScheduleConfigs,
@ -59,6 +59,8 @@ impl Plugin for CameraPlugin {
.register_type::<MipBias>() .register_type::<MipBias>()
.register_required_components::<Camera, Msaa>() .register_required_components::<Camera, Msaa>()
.register_required_components::<Camera, SyncToRenderWorld>() .register_required_components::<Camera, SyncToRenderWorld>()
.register_required_components::<Camera3d, ColorGrading>()
.register_required_components::<Camera3d, Exposure>()
.add_plugins(( .add_plugins((
ExtractResourcePlugin::<ClearColor>::default(), ExtractResourcePlugin::<ClearColor>::default(),
ExtractComponentPlugin::<CameraMainTextureUsages>::default(), ExtractComponentPlugin::<CameraMainTextureUsages>::default(),
@ -95,7 +97,7 @@ fn warn_on_no_render_graph(world: DeferredWorld, HookContext { entity, caller, .
} }
impl ExtractResource for ClearColor { impl ExtractResource for ClearColor {
type Source = ClearColor; type Source = Self;
fn extract_resource(source: &Self::Source) -> Self { fn extract_resource(source: &Self::Source) -> Self {
source.clone() source.clone()
@ -106,12 +108,28 @@ impl ExtractComponent for CameraMainTextureUsages {
type QueryFilter = (); type QueryFilter = ();
type Out = Self; type Out = Self;
fn extract_component( fn extract_component(item: QueryItem<Self::QueryData>) -> Option<Self::Out> {
item: bevy_ecs::query::QueryItem<'_, '_, Self::QueryData>,
) -> Option<Self::Out> {
Some(*item) Some(*item)
} }
} }
impl ExtractComponent for Camera2d {
type QueryData = &'static Self;
type QueryFilter = With<Camera>;
type Out = Self;
fn extract_component(item: QueryItem<Self::QueryData>) -> Option<Self::Out> {
Some(item.clone())
}
}
impl ExtractComponent for Camera3d {
type QueryData = &'static Self;
type QueryFilter = With<Camera>;
type Out = Self;
fn extract_component(item: QueryItem<Self::QueryData>) -> Option<Self::Out> {
Some(item.clone())
}
}
/// Configures the [`RenderGraph`] name assigned to be run for a given [`Camera`] entity. /// Configures the [`RenderGraph`] name assigned to be run for a given [`Camera`] entity.
#[derive(Component, Debug, Deref, DerefMut, Reflect, Clone)] #[derive(Component, Debug, Deref, DerefMut, Reflect, Clone)]