Skip to content

Commit 2a01689

Browse files
committed
Convert RenderTarget to Component
1 parent 170f150 commit 2a01689

File tree

22 files changed

+113
-141
lines changed

22 files changed

+113
-141
lines changed

crates/bevy_camera/src/camera.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,8 @@ pub enum ViewportConversionError {
338338
CameraMainTextureUsages,
339339
VisibleEntities,
340340
Transform,
341-
Visibility
341+
Visibility,
342+
RenderTarget
342343
)]
343344
pub struct Camera {
344345
/// If set, this camera will render to the given [`Viewport`] rectangle within the configured [`RenderTarget`].
@@ -351,8 +352,6 @@ pub struct Camera {
351352
/// Computed values for this camera, such as the projection matrix and the render target size.
352353
#[reflect(ignore, clone)]
353354
pub computed: ComputedCameraValues,
354-
/// The "target" that this camera will render to.
355-
pub target: RenderTarget,
356355
// todo: reflect this when #6042 lands
357356
/// The [`CameraOutputMode`] for this camera.
358357
#[reflect(ignore, clone)]
@@ -375,7 +374,6 @@ impl Default for Camera {
375374
order: 0,
376375
viewport: None,
377376
computed: Default::default(),
378-
target: Default::default(),
379377
output_mode: Default::default(),
380378
msaa_writeback: true,
381379
clear_color: Default::default(),
@@ -798,7 +796,7 @@ impl Default for CameraOutputMode {
798796

799797
/// The "target" that a [`Camera`] will render to. For example, this could be a `Window`
800798
/// swapchain or an [`Image`].
801-
#[derive(Debug, Clone, Reflect, From)]
799+
#[derive(Component, Debug, Clone, Reflect, From)]
802800
#[reflect(Clone)]
803801
pub enum RenderTarget {
804802
/// Window to which the camera's view is rendered.

crates/bevy_core_pipeline/src/oit/mod.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Order Independent Transparency (OIT) for 3d rendering. See [`OrderIndependentTransparencyPlugin`] for more details.
22
33
use bevy_app::prelude::*;
4-
use bevy_camera::{Camera, Camera3d};
4+
use bevy_camera::{Camera3d, RenderTarget};
55
use bevy_ecs::{component::*, lifecycle::ComponentHook, prelude::*};
66
use bevy_math::UVec2;
77
use bevy_platform::collections::HashSet;
@@ -135,8 +135,8 @@ impl Plugin for OrderIndependentTransparencyPlugin {
135135
// bevy reuses the same depth texture so we need to set this on all cameras with the same render target.
136136
fn configure_depth_texture_usages(
137137
p: Query<Entity, With<PrimaryWindow>>,
138-
cameras: Query<(&Camera, Has<OrderIndependentTransparencySettings>)>,
139-
mut new_cameras: Query<(&mut Camera3d, &Camera), Added<Camera3d>>,
138+
cameras: Query<(&RenderTarget, Has<OrderIndependentTransparencySettings>)>,
139+
mut new_cameras: Query<(&mut Camera3d, &RenderTarget), Added<Camera3d>>,
140140
) {
141141
if new_cameras.is_empty() {
142142
return;
@@ -145,15 +145,15 @@ fn configure_depth_texture_usages(
145145
// Find all the render target that potentially uses OIT
146146
let primary_window = p.single().ok();
147147
let mut render_target_has_oit = <HashSet<_>>::default();
148-
for (camera, has_oit) in &cameras {
148+
for (render_target, has_oit) in &cameras {
149149
if has_oit {
150-
render_target_has_oit.insert(camera.target.normalize(primary_window));
150+
render_target_has_oit.insert(render_target.normalize(primary_window));
151151
}
152152
}
153153

154154
// Update the depth texture usage for cameras with a render target that has OIT
155-
for (mut camera_3d, camera) in &mut new_cameras {
156-
if render_target_has_oit.contains(&camera.target.normalize(primary_window)) {
155+
for (mut camera_3d, render_target) in &mut new_cameras {
156+
if render_target_has_oit.contains(&render_target.normalize(primary_window)) {
157157
let mut usages = TextureUsages::from(camera_3d.depth_texture_usages);
158158
usages |= TextureUsages::RENDER_ATTACHMENT | TextureUsages::TEXTURE_BINDING;
159159
camera_3d.depth_texture_usages = usages.into();

crates/bevy_dev_tools/src/picking_debug.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use bevy_app::prelude::*;
44
use bevy_camera::visibility::Visibility;
5-
use bevy_camera::Camera;
5+
use bevy_camera::{Camera, RenderTarget};
66
use bevy_color::prelude::*;
77
use bevy_ecs::prelude::*;
88
use bevy_picking::backend::HitData;
@@ -243,7 +243,7 @@ pub fn update_debug_data(
243243
/// Draw text on each cursor with debug info
244244
pub fn debug_draw(
245245
mut commands: Commands,
246-
camera_query: Query<(Entity, &Camera)>,
246+
camera_query: Query<(Entity, &Camera, &RenderTarget)>,
247247
primary_window: Query<Entity, With<bevy_window::PrimaryWindow>>,
248248
pointers: Query<(Entity, &PointerId, &PointerDebug)>,
249249
scale: Res<UiScale>,
@@ -254,17 +254,16 @@ pub fn debug_draw(
254254
};
255255
let text = format!("{id:?}\n{debug}");
256256

257-
for (camera, _) in camera_query.iter().filter(|(_, camera)| {
258-
camera
259-
.target
257+
for (camera, _, _) in camera_query.iter().filter(|(_, _, render_target)| {
258+
render_target
260259
.normalize(primary_window.single().ok())
261260
.is_some_and(|target| target == pointer_location.target)
262261
}) {
263262
let mut pointer_pos = pointer_location.position;
264263
if let Some(viewport) = camera_query
265264
.get(camera)
266265
.ok()
267-
.and_then(|(_, camera)| camera.logical_viewport_rect())
266+
.and_then(|(_, camera, _)| camera.logical_viewport_rect())
268267
{
269268
pointer_pos -= viewport.min;
270269
}

crates/bevy_picking/src/backend.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ pub mod ray {
129129
//! Types and systems for constructing rays from cameras and pointers.
130130
131131
use crate::backend::prelude::{PointerId, PointerLocation};
132-
use bevy_camera::Camera;
132+
use bevy_camera::{Camera, RenderTarget};
133133
use bevy_ecs::prelude::*;
134134
use bevy_math::Ray3d;
135135
use bevy_platform::collections::{hash_map::Iter, HashMap};
@@ -196,20 +196,24 @@ pub mod ray {
196196
pub fn repopulate(
197197
mut ray_map: ResMut<Self>,
198198
primary_window_entity: Query<Entity, With<PrimaryWindow>>,
199-
cameras: Query<(Entity, &Camera, &GlobalTransform)>,
199+
cameras: Query<(Entity, &Camera, &RenderTarget, &GlobalTransform)>,
200200
pointers: Query<(&PointerId, &PointerLocation)>,
201201
) {
202202
ray_map.map.clear();
203203

204-
for (camera_entity, camera, camera_tfm) in &cameras {
204+
for (camera_entity, camera, render_target, camera_tfm) in &cameras {
205205
if !camera.is_active {
206206
continue;
207207
}
208208

209209
for (&pointer_id, pointer_loc) in &pointers {
210-
if let Some(ray) =
211-
make_ray(&primary_window_entity, camera, camera_tfm, pointer_loc)
212-
{
210+
if let Some(ray) = make_ray(
211+
&primary_window_entity,
212+
camera,
213+
render_target,
214+
camera_tfm,
215+
pointer_loc,
216+
) {
213217
ray_map
214218
.map
215219
.insert(RayId::new(camera_entity, pointer_id), ray);
@@ -222,11 +226,12 @@ pub mod ray {
222226
fn make_ray(
223227
primary_window_entity: &Query<Entity, With<PrimaryWindow>>,
224228
camera: &Camera,
229+
render_target: &RenderTarget,
225230
camera_tfm: &GlobalTransform,
226231
pointer_loc: &PointerLocation,
227232
) -> Option<Ray3d> {
228233
let pointer_loc = pointer_loc.location()?;
229-
if !pointer_loc.is_in_viewport(camera, primary_window_entity) {
234+
if !pointer_loc.is_in_viewport(camera, render_target, primary_window_entity) {
230235
return None;
231236
}
232237
camera

crates/bevy_picking/src/pointer.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
//! The purpose of this module is primarily to provide a common interface that can be
99
//! driven by lower-level input devices and consumed by higher-level interaction systems.
1010
11-
use bevy_camera::Camera;
1211
use bevy_camera::NormalizedRenderTarget;
12+
use bevy_camera::{Camera, RenderTarget};
1313
use bevy_ecs::prelude::*;
1414
use bevy_input::mouse::MouseScrollUnit;
1515
use bevy_math::Vec2;
@@ -223,10 +223,10 @@ impl Location {
223223
pub fn is_in_viewport(
224224
&self,
225225
camera: &Camera,
226+
render_target: &RenderTarget,
226227
primary_window: &Query<Entity, With<PrimaryWindow>>,
227228
) -> bool {
228-
if camera
229-
.target
229+
if render_target
230230
.normalize(Some(match primary_window.single() {
231231
Ok(w) => w,
232232
Err(_) => return false,

crates/bevy_render/src/camera.rs

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use bevy_camera::{
2121
visibility::{self, RenderLayers, VisibleEntities},
2222
Camera, Camera2d, Camera3d, CameraMainTextureUsages, CameraOutputMode, CameraUpdateSystems,
2323
ClearColor, ClearColorConfig, Exposure, ManualTextureViewHandle, NormalizedRenderTarget,
24-
Projection, RenderTargetInfo, Viewport,
24+
Projection, RenderTarget, RenderTargetInfo, Viewport,
2525
};
2626
use bevy_derive::{Deref, DerefMut};
2727
use bevy_ecs::{
@@ -311,7 +311,7 @@ pub fn camera_system(
311311
windows: Query<(Entity, &Window)>,
312312
images: Res<Assets<Image>>,
313313
manual_texture_views: Res<ManualTextureViews>,
314-
mut cameras: Query<(&mut Camera, &mut Projection)>,
314+
mut cameras: Query<(&mut Camera, &RenderTarget, &mut Projection)>,
315315
) -> Result<(), BevyError> {
316316
let primary_window = primary_window.iter().next();
317317

@@ -332,13 +332,13 @@ pub fn camera_system(
332332
})
333333
.collect();
334334

335-
for (mut camera, mut camera_projection) in &mut cameras {
335+
for (mut camera, render_target, mut camera_projection) in &mut cameras {
336336
let mut viewport_size = camera
337337
.viewport
338338
.as_ref()
339339
.map(|viewport| viewport.physical_size);
340340

341-
if let Some(normalized_target) = &camera.target.normalize(primary_window)
341+
if let Some(normalized_target) = render_target.normalize(primary_window)
342342
&& (normalized_target.is_changed(&changed_window_ids, &changed_image_handles)
343343
|| camera.is_added()
344344
|| camera_projection.is_changed()
@@ -422,18 +422,21 @@ pub fn extract_cameras(
422422
Entity,
423423
RenderEntity,
424424
&Camera,
425+
&RenderTarget,
425426
&CameraRenderGraph,
426427
&GlobalTransform,
427428
&VisibleEntities,
428429
&Frustum,
429-
Has<Hdr>,
430-
Option<&ColorGrading>,
431-
Option<&Exposure>,
432-
Option<&TemporalJitter>,
433-
Option<&MipBias>,
434-
Option<&RenderLayers>,
435-
Option<&Projection>,
436-
Has<NoIndirectDrawing>,
430+
(
431+
Has<Hdr>,
432+
Option<&ColorGrading>,
433+
Option<&Exposure>,
434+
Option<&TemporalJitter>,
435+
Option<&MipBias>,
436+
Option<&RenderLayers>,
437+
Option<&Projection>,
438+
Has<NoIndirectDrawing>,
439+
),
437440
)>,
438441
>,
439442
primary_window: Extract<Query<Entity, With<PrimaryWindow>>>,
@@ -456,18 +459,21 @@ pub fn extract_cameras(
456459
main_entity,
457460
render_entity,
458461
camera,
462+
render_target,
459463
camera_render_graph,
460464
transform,
461465
visible_entities,
462466
frustum,
463-
hdr,
464-
color_grading,
465-
exposure,
466-
temporal_jitter,
467-
mip_bias,
468-
render_layers,
469-
projection,
470-
no_indirect_drawing,
467+
(
468+
hdr,
469+
color_grading,
470+
exposure,
471+
temporal_jitter,
472+
mip_bias,
473+
render_layers,
474+
projection,
475+
no_indirect_drawing,
476+
),
471477
) in query.iter()
472478
{
473479
if !camera.is_active {
@@ -522,7 +528,7 @@ pub fn extract_cameras(
522528
let mut commands = commands.entity(render_entity);
523529
commands.insert((
524530
ExtractedCamera {
525-
target: camera.target.normalize(primary_window),
531+
target: render_target.normalize(primary_window),
526532
viewport: camera.viewport.clone(),
527533
physical_viewport_size: Some(viewport_size),
528534
physical_target_size: Some(target_size),

crates/bevy_sprite/src/picking_backend.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use crate::{Anchor, Sprite};
1414
use bevy_app::prelude::*;
1515
use bevy_asset::prelude::*;
16-
use bevy_camera::{visibility::ViewVisibility, Camera, Projection};
16+
use bevy_camera::{visibility::ViewVisibility, Camera, Projection, RenderTarget};
1717
use bevy_color::Alpha;
1818
use bevy_ecs::prelude::*;
1919
use bevy_image::prelude::*;
@@ -85,6 +85,7 @@ fn sprite_picking(
8585
cameras: Query<(
8686
Entity,
8787
&Camera,
88+
&RenderTarget,
8889
&GlobalTransform,
8990
&Projection,
9091
Has<SpritePickingCamera>,
@@ -125,16 +126,15 @@ fn sprite_picking(
125126
pointer_location.location().map(|loc| (pointer, loc))
126127
}) {
127128
let mut blocked = false;
128-
let Some((cam_entity, camera, cam_transform, Projection::Orthographic(cam_ortho), _)) =
129+
let Some((cam_entity, camera, _, cam_transform, Projection::Orthographic(cam_ortho), _)) =
129130
cameras
130131
.iter()
131-
.filter(|(_, camera, _, _, cam_can_pick)| {
132+
.filter(|(_, camera, _, _, _, cam_can_pick)| {
132133
let marker_requirement = !settings.require_markers || *cam_can_pick;
133134
camera.is_active && marker_requirement
134135
})
135-
.find(|(_, camera, _, _, _)| {
136-
camera
137-
.target
136+
.find(|(_, _, render_target, _, _, _)| {
137+
render_target
138138
.normalize(primary_window)
139139
.is_some_and(|x| x == location.target)
140140
})

crates/bevy_ui/src/focus.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::{
22
ui_transform::UiGlobalTransform, ComputedNode, ComputedUiTargetCamera, Node, OverrideClip,
33
UiStack,
44
};
5-
use bevy_camera::{visibility::InheritedVisibility, Camera, NormalizedRenderTarget};
5+
use bevy_camera::{visibility::InheritedVisibility, Camera, NormalizedRenderTarget, RenderTarget};
66
use bevy_ecs::{
77
change_detection::DetectChangesMut,
88
entity::{ContainsEntity, Entity},
@@ -148,7 +148,7 @@ pub struct NodeQuery {
148148
/// Entities with a hidden [`InheritedVisibility`] are always treated as released.
149149
pub fn ui_focus_system(
150150
mut state: Local<State>,
151-
camera_query: Query<(Entity, &Camera)>,
151+
camera_query: Query<(Entity, &Camera, &RenderTarget)>,
152152
primary_window: Query<Entity, With<PrimaryWindow>>,
153153
windows: Query<&Window>,
154154
mouse_button_input: Res<ButtonInput<MouseButton>>,
@@ -188,10 +188,10 @@ pub fn ui_focus_system(
188188

189189
let camera_cursor_positions: HashMap<Entity, Vec2> = camera_query
190190
.iter()
191-
.filter_map(|(entity, camera)| {
191+
.filter_map(|(entity, camera, render_target)| {
192192
// Interactions are only supported for cameras rendering to a window.
193193
let Some(NormalizedRenderTarget::Window(window_ref)) =
194-
camera.target.normalize(primary_window)
194+
render_target.normalize(primary_window)
195195
else {
196196
return None;
197197
};

0 commit comments

Comments
 (0)