From 6b4986f952c8fa694b7039d792fbf601ac79d1fb Mon Sep 17 00:00:00 2001 From: Emerson Coskey Date: Thu, 17 Apr 2025 21:03:55 -0700 Subject: [PATCH 01/10] split camera.hdr into own component --- .../src/auto_exposure/settings.rs | 3 ++- crates/bevy_core_pipeline/src/bloom/settings.rs | 14 +++++++++----- crates/bevy_pbr/src/atmosphere/mod.rs | 3 ++- crates/bevy_pbr/src/atmosphere/resources.rs | 9 ++------- crates/bevy_render/src/camera/camera.rs | 12 +++++------- crates/bevy_render/src/view/mod.rs | 9 +++++++++ crates/bevy_ui/src/render/mod.rs | 7 ++++--- 7 files changed, 33 insertions(+), 24 deletions(-) diff --git a/crates/bevy_core_pipeline/src/auto_exposure/settings.rs b/crates/bevy_core_pipeline/src/auto_exposure/settings.rs index cf6fdd4e24d81..ae359a8a01dd4 100644 --- a/crates/bevy_core_pipeline/src/auto_exposure/settings.rs +++ b/crates/bevy_core_pipeline/src/auto_exposure/settings.rs @@ -5,7 +5,7 @@ use bevy_asset::Handle; use bevy_ecs::{prelude::Component, reflect::ReflectComponent}; use bevy_image::Image; use bevy_reflect::{std_traits::ReflectDefault, Reflect}; -use bevy_render::extract_component::ExtractComponent; +use bevy_render::{extract_component::ExtractComponent, view::Hdr}; use bevy_utils::default; /// Component that enables auto exposure for an HDR-enabled 2d or 3d camera. @@ -25,6 +25,7 @@ use bevy_utils::default; /// **Auto Exposure requires compute shaders and is not compatible with WebGL2.** #[derive(Component, Clone, Reflect, ExtractComponent)] #[reflect(Component, Default, Clone)] +#[require(Hdr)] pub struct AutoExposure { /// The range of exposure values for the histogram. /// diff --git a/crates/bevy_core_pipeline/src/bloom/settings.rs b/crates/bevy_core_pipeline/src/bloom/settings.rs index f6ee8dbd1e358..195c2eb4c0b53 100644 --- a/crates/bevy_core_pipeline/src/bloom/settings.rs +++ b/crates/bevy_core_pipeline/src/bloom/settings.rs @@ -1,8 +1,12 @@ use super::downsampling_pipeline::BloomUniforms; -use bevy_ecs::{prelude::Component, query::QueryItem, reflect::ReflectComponent}; +use bevy_ecs::{ + prelude::Component, + query::{QueryItem, With}, + reflect::ReflectComponent, +}; use bevy_math::{AspectRatio, URect, UVec4, Vec2, Vec4}; use bevy_reflect::{std_traits::ReflectDefault, Reflect}; -use bevy_render::{extract_component::ExtractComponent, prelude::Camera}; +use bevy_render::{extract_component::ExtractComponent, prelude::Camera, view::Hdr}; /// Applies a bloom effect to an HDR-enabled 2d or 3d camera. /// @@ -26,6 +30,7 @@ use bevy_render::{extract_component::ExtractComponent, prelude::Camera}; /// used in Bevy as well as a visualization of the curve's respective scattering profile. #[derive(Component, Reflect, Clone)] #[reflect(Component, Default, Clone)] +#[require(Hdr)] pub struct Bloom { /// Controls the baseline of how much the image is scattered (default: 0.15). /// @@ -219,7 +224,7 @@ pub enum BloomCompositeMode { impl ExtractComponent for Bloom { type QueryData = (&'static Self, &'static Camera); - type QueryFilter = (); + type QueryFilter = With; type Out = (Self, BloomUniforms); fn extract_component((bloom, camera): QueryItem<'_, Self::QueryData>) -> Option { @@ -228,9 +233,8 @@ impl ExtractComponent for Bloom { camera.physical_viewport_size(), camera.physical_target_size(), camera.is_active, - camera.hdr, ) { - (Some(URect { min: origin, .. }), Some(size), Some(target_size), true, true) + (Some(URect { min: origin, .. }), Some(size), Some(target_size), true) if size.x != 0 && size.y != 0 => { let threshold = bloom.prefilter.threshold; diff --git a/crates/bevy_pbr/src/atmosphere/mod.rs b/crates/bevy_pbr/src/atmosphere/mod.rs index e7f17f0e1e855..1dd9038494f47 100644 --- a/crates/bevy_pbr/src/atmosphere/mod.rs +++ b/crates/bevy_pbr/src/atmosphere/mod.rs @@ -50,6 +50,7 @@ use bevy_reflect::{std_traits::ReflectDefault, Reflect}; use bevy_render::{ extract_component::UniformComponentPlugin, render_resource::{DownlevelFlags, ShaderType, SpecializedRenderPipelines}, + view::Hdr, }; use bevy_render::{ extract_component::{ExtractComponent, ExtractComponentPlugin}, @@ -246,7 +247,7 @@ impl Plugin for AtmospherePlugin { /// from the planet's surface, ozone only exists in a band centered at a fairly /// high altitude. #[derive(Clone, Component, Reflect, ShaderType)] -#[require(AtmosphereSettings)] +#[require(AtmosphereSettings, Hdr)] #[reflect(Clone, Default)] pub struct Atmosphere { /// Radius of the planet diff --git a/crates/bevy_pbr/src/atmosphere/resources.rs b/crates/bevy_pbr/src/atmosphere/resources.rs index b872916619830..9f6e4801da161 100644 --- a/crates/bevy_pbr/src/atmosphere/resources.rs +++ b/crates/bevy_pbr/src/atmosphere/resources.rs @@ -325,7 +325,6 @@ pub(crate) struct RenderSkyPipelineId(pub CachedRenderPipelineId); #[derive(Copy, Clone, Hash, PartialEq, Eq)] pub(crate) struct RenderSkyPipelineKey { pub msaa_samples: u32, - pub hdr: bool, pub dual_source_blending: bool, } @@ -338,9 +337,6 @@ impl SpecializedRenderPipeline for RenderSkyBindGroupLayouts { if key.msaa_samples > 1 { shader_defs.push("MULTISAMPLED".into()); } - if key.hdr { - shader_defs.push("TONEMAP_IN_SHADER".into()); - } if key.dual_source_blending { shader_defs.push("DUAL_SOURCE_BLENDING".into()); } @@ -394,20 +390,19 @@ impl SpecializedRenderPipeline for RenderSkyBindGroupLayouts { } pub(super) fn queue_render_sky_pipelines( - views: Query<(Entity, &Camera, &Msaa), With>, + views: Query<(Entity, &Msaa), (With, With)>, pipeline_cache: Res, layouts: Res, mut specializer: ResMut>, render_device: Res, mut commands: Commands, ) { - for (entity, camera, msaa) in &views { + for (entity, msaa) in &views { let id = specializer.specialize( &pipeline_cache, &layouts, RenderSkyPipelineKey { msaa_samples: msaa.samples(), - hdr: camera.hdr, dual_source_blending: render_device .features() .contains(WgpuFeatures::DUAL_SOURCE_BLENDING), diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index 7bbfb8a60ef5c..3f9fddcb6a196 100644 --- a/crates/bevy_render/src/camera/camera.rs +++ b/crates/bevy_render/src/camera/camera.rs @@ -13,7 +13,7 @@ use crate::{ sync_world::{RenderEntity, SyncToRenderWorld}, texture::GpuImage, view::{ - ColorGrading, ExtractedView, ExtractedWindows, Msaa, NoIndirectDrawing, RenderLayers, + ColorGrading, ExtractedView, ExtractedWindows, Hdr, Msaa, NoIndirectDrawing, RenderLayers, RenderVisibleEntities, RetainedViewEntity, ViewUniformOffset, Visibility, VisibleEntities, }, Extract, @@ -356,9 +356,6 @@ pub struct Camera { pub computed: ComputedCameraValues, /// The "target" that this camera will render to. pub target: RenderTarget, - /// If this is set to `true`, the camera will use an intermediate "high dynamic range" render texture. - /// This allows rendering with a wider range of lighting values. - pub hdr: bool, // todo: reflect this when #6042 lands /// The [`CameraOutputMode`] for this camera. #[reflect(ignore, clone)] @@ -389,7 +386,6 @@ impl Default for Camera { computed: Default::default(), target: Default::default(), output_mode: Default::default(), - hdr: false, msaa_writeback: true, clear_color: Default::default(), sub_camera_view: None, @@ -1101,6 +1097,7 @@ pub fn extract_cameras( &GlobalTransform, &VisibleEntities, &Frustum, + Has, Option<&ColorGrading>, Option<&Exposure>, Option<&TemporalJitter>, @@ -1122,6 +1119,7 @@ pub fn extract_cameras( transform, visible_entities, frustum, + hdr, color_grading, exposure, temporal_jitter, @@ -1200,14 +1198,14 @@ pub fn extract_cameras( exposure: exposure .map(Exposure::exposure) .unwrap_or_else(|| Exposure::default().exposure()), - hdr: camera.hdr, + hdr, }, ExtractedView { retained_view_entity: RetainedViewEntity::new(main_entity.into(), None, 0), clip_from_view: camera.clip_from_view(), world_from_view: *transform, clip_from_world: None, - hdr: camera.hdr, + hdr, viewport: UVec4::new( viewport_origin.x, viewport_origin.y, diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index b91eafeb2de3c..3200771b753df 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -114,6 +114,7 @@ impl Plugin for ViewPlugin { .register_type::() // NOTE: windows.is_changed() handles cases where a window was resized .add_plugins(( + ExtractComponentPlugin::::default(), ExtractComponentPlugin::::default(), ExtractComponentPlugin::::default(), VisibilityPlugin, @@ -199,6 +200,14 @@ impl Msaa { } } +/// If this component is added to a camera, the camera will use an intermediate "high dynamic range" render texture. +/// This allows rendering with a wider range of lighting values. +#[derive( + Component, Default, Copy, Clone, ExtractComponent, Reflect, PartialEq, Eq, Hash, Debug, +)] +#[reflect(Component, Default, PartialEq, Hash, Debug)] +pub struct Hdr; + /// An identifier for a view that is stable across frames. /// /// We can't use [`Entity`] for this because render world entities aren't diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index 6f691d4163686..6dfb028236206 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -27,7 +27,7 @@ use bevy_render::render_phase::ViewSortedRenderPhases; use bevy_render::renderer::RenderContext; use bevy_render::sync_world::MainEntity; use bevy_render::texture::TRANSPARENT_IMAGE_HANDLE; -use bevy_render::view::RetainedViewEntity; +use bevy_render::view::{Hdr, RetainedViewEntity}; use bevy_render::{ camera::Camera, render_asset::RenderAssets, @@ -613,6 +613,7 @@ pub fn extract_ui_camera_view( Entity, RenderEntity, &Camera, + Has, Option<&UiAntiAlias>, Option<&BoxShadowSamples>, ), @@ -623,7 +624,7 @@ pub fn extract_ui_camera_view( ) { live_entities.clear(); - for (main_entity, render_entity, camera, ui_anti_alias, shadow_samples) in &query { + for (main_entity, render_entity, camera, hdr, ui_anti_alias, shadow_samples) in &query { // ignore inactive cameras if !camera.is_active { commands @@ -659,7 +660,7 @@ pub fn extract_ui_camera_view( UI_CAMERA_FAR + UI_CAMERA_TRANSFORM_OFFSET, ), clip_from_world: None, - hdr: camera.hdr, + hdr, viewport: UVec4::from(( physical_viewport_rect.min, physical_viewport_rect.size(), From c630886d214ab468ee96142beb7782a8e891e09f Mon Sep 17 00:00:00 2001 From: Emerson Coskey Date: Thu, 17 Apr 2025 21:03:59 -0700 Subject: [PATCH 02/10] migrate examples --- examples/2d/bloom_2d.rs | 1 - examples/3d/anti_aliasing.rs | 6 ++---- examples/3d/atmosphere.rs | 8 ++------ examples/3d/auto_exposure.rs | 4 ---- examples/3d/bloom_3d.rs | 1 - examples/3d/clearcoat.rs | 6 ++---- examples/3d/color_grading.rs | 6 ++---- examples/3d/deferred_rendering.rs | 5 ----- examples/3d/depth_of_field.rs | 4 ---- examples/3d/fog_volumes.rs | 6 ++---- examples/3d/mesh_ray_cast.rs | 4 ---- examples/3d/post_processing.rs | 6 ++---- examples/3d/reflection_probes.rs | 6 ++---- examples/3d/rotate_environment_map.rs | 6 ++---- examples/3d/scrolling_fog.rs | 4 ---- examples/3d/specular_tint.rs | 6 ++---- examples/3d/spotlight.rs | 6 ++---- examples/3d/ssao.rs | 6 ++---- examples/3d/ssr.rs | 6 ++---- examples/3d/tonemapping.rs | 6 ++---- examples/3d/transmission.rs | 4 ---- examples/3d/volumetric_fog.rs | 4 ---- examples/animation/animation_events.rs | 2 +- examples/camera/2d_top_down_camera.rs | 9 +-------- examples/math/sampling_primitives.rs | 2 +- examples/testbed/2d.rs | 4 ---- examples/testbed/3d.rs | 4 ---- 27 files changed, 29 insertions(+), 103 deletions(-) diff --git a/examples/2d/bloom_2d.rs b/examples/2d/bloom_2d.rs index fd90210d6fbc7..9d9be1e5c7f10 100644 --- a/examples/2d/bloom_2d.rs +++ b/examples/2d/bloom_2d.rs @@ -25,7 +25,6 @@ fn setup( commands.spawn(( Camera2d, Camera { - hdr: true, // 1. HDR is required for bloom clear_color: ClearColorConfig::Custom(Color::BLACK), ..default() }, diff --git a/examples/3d/anti_aliasing.rs b/examples/3d/anti_aliasing.rs index e29574588c71f..a26e9b3700518 100644 --- a/examples/3d/anti_aliasing.rs +++ b/examples/3d/anti_aliasing.rs @@ -19,6 +19,7 @@ use bevy::{ render_resource::{Extent3d, TextureDimension, TextureFormat}, }, }; +use bevy_render::view::Hdr; fn main() { App::new() @@ -300,10 +301,7 @@ fn setup( // Camera commands.spawn(( Camera3d::default(), - Camera { - hdr: true, - ..default() - }, + Hdr, Transform::from_xyz(0.7, 0.7, 1.0).looking_at(Vec3::new(0.0, 0.3, 0.0), Vec3::Y), ContrastAdaptiveSharpening { enabled: false, diff --git a/examples/3d/atmosphere.rs b/examples/3d/atmosphere.rs index 53c5c91dfa687..04e12fe3653f6 100644 --- a/examples/3d/atmosphere.rs +++ b/examples/3d/atmosphere.rs @@ -8,6 +8,7 @@ use bevy::{ prelude::*, render::camera::Exposure, }; +use bevy_render::view::Hdr; fn main() { App::new() @@ -20,11 +21,6 @@ fn main() { fn setup_camera_fog(mut commands: Commands) { commands.spawn(( Camera3d::default(), - // HDR is required for atmospheric scattering to be properly applied to the scene - Camera { - hdr: true, - ..default() - }, Transform::from_xyz(-1.2, 0.15, 0.0).looking_at(Vec3::Y * 0.1, Vec3::Y), // This is the component that enables atmospheric scattering for a camera Atmosphere::EARTH, @@ -36,7 +32,7 @@ fn setup_camera_fog(mut commands: Commands) { scene_units_to_m: 1e+4, ..Default::default() }, - // The directional light illuminance used in this scene + // The directional light illuminance used in this scene // (the one recommended for use with this feature) is // quite bright, so raising the exposure compensation helps // bring the scene to a nicer brightness range. diff --git a/examples/3d/auto_exposure.rs b/examples/3d/auto_exposure.rs index 79fece61c8e36..62c875dc5dc8a 100644 --- a/examples/3d/auto_exposure.rs +++ b/examples/3d/auto_exposure.rs @@ -40,10 +40,6 @@ fn setup( commands.spawn(( Camera3d::default(), - Camera { - hdr: true, - ..default() - }, Transform::from_xyz(1.0, 0.0, 0.0).looking_at(Vec3::ZERO, Vec3::Y), AutoExposure { metering_mask: metering_mask.clone(), diff --git a/examples/3d/bloom_3d.rs b/examples/3d/bloom_3d.rs index fd87928283a70..a54847b241be3 100644 --- a/examples/3d/bloom_3d.rs +++ b/examples/3d/bloom_3d.rs @@ -29,7 +29,6 @@ fn setup_scene( commands.spawn(( Camera3d::default(), Camera { - hdr: true, // 1. HDR is required for bloom clear_color: ClearColorConfig::Custom(Color::BLACK), ..default() }, diff --git a/examples/3d/clearcoat.rs b/examples/3d/clearcoat.rs index c04b12d5814ed..5d283878395e6 100644 --- a/examples/3d/clearcoat.rs +++ b/examples/3d/clearcoat.rs @@ -26,6 +26,7 @@ use bevy::{ math::vec3, prelude::*, }; +use bevy_render::view::Hdr; /// The size of each sphere. const SPHERE_SCALE: f32 = 0.9; @@ -191,10 +192,7 @@ fn spawn_camera(commands: &mut Commands, asset_server: &AssetServer) { commands .spawn(( Camera3d::default(), - Camera { - hdr: true, - ..default() - }, + Hdr, Projection::Perspective(PerspectiveProjection { fov: 27.0 / 180.0 * PI, ..default() diff --git a/examples/3d/color_grading.rs b/examples/3d/color_grading.rs index 0b2616c1879b5..869382ea07e66 100644 --- a/examples/3d/color_grading.rs +++ b/examples/3d/color_grading.rs @@ -11,6 +11,7 @@ use bevy::{ prelude::*, render::view::{ColorGrading, ColorGradingGlobal, ColorGradingSection}, }; +use bevy_render::view::Hdr; use std::fmt::Display; static FONT_PATH: &str = "fonts/FiraMono-Medium.ttf"; @@ -334,10 +335,7 @@ fn add_text<'a>( fn add_camera(commands: &mut Commands, asset_server: &AssetServer, color_grading: ColorGrading) { commands.spawn(( Camera3d::default(), - Camera { - hdr: true, - ..default() - }, + Hdr, Transform::from_xyz(0.7, 0.7, 1.0).looking_at(Vec3::new(0.0, 0.3, 0.0), Vec3::Y), color_grading, DistanceFog { diff --git a/examples/3d/deferred_rendering.rs b/examples/3d/deferred_rendering.rs index d6e58fe5058a8..6f51cff8c20ec 100644 --- a/examples/3d/deferred_rendering.rs +++ b/examples/3d/deferred_rendering.rs @@ -33,11 +33,6 @@ fn setup( ) { commands.spawn(( Camera3d::default(), - Camera { - // Deferred both supports both hdr: true and hdr: false - hdr: false, - ..default() - }, Transform::from_xyz(0.7, 0.7, 1.0).looking_at(Vec3::new(0.0, 0.3, 0.0), Vec3::Y), // MSAA needs to be off for Deferred rendering Msaa::Off, diff --git a/examples/3d/depth_of_field.rs b/examples/3d/depth_of_field.rs index d6ca77bbde0ca..1ecfb3e247bfb 100644 --- a/examples/3d/depth_of_field.rs +++ b/examples/3d/depth_of_field.rs @@ -73,10 +73,6 @@ fn setup(mut commands: Commands, asset_server: Res, app_settings: R let mut camera = commands.spawn(( Camera3d::default(), Transform::from_xyz(0.0, 4.5, 8.25).looking_at(Vec3::ZERO, Vec3::Y), - Camera { - hdr: true, - ..default() - }, Tonemapping::TonyMcMapface, Bloom::NATURAL, )); diff --git a/examples/3d/fog_volumes.rs b/examples/3d/fog_volumes.rs index 68fc6d0ea783e..792aa0eb5a036 100644 --- a/examples/3d/fog_volumes.rs +++ b/examples/3d/fog_volumes.rs @@ -10,6 +10,7 @@ use bevy::{ pbr::{FogVolume, VolumetricFog, VolumetricLight}, prelude::*, }; +use bevy_render::view::Hdr; /// Entry point. fn main() { @@ -58,10 +59,7 @@ fn setup(mut commands: Commands, asset_server: Res) { commands.spawn(( Camera3d::default(), Transform::from_xyz(-0.75, 1.0, 2.0).looking_at(vec3(0.0, 0.0, 0.0), Vec3::Y), - Camera { - hdr: true, - ..default() - }, + Hdr, VolumetricFog { // Make this relatively high in order to increase the fog quality. step_count: 64, diff --git a/examples/3d/mesh_ray_cast.rs b/examples/3d/mesh_ray_cast.rs index 85985f75a900a..8093a873a728e 100644 --- a/examples/3d/mesh_ray_cast.rs +++ b/examples/3d/mesh_ray_cast.rs @@ -104,10 +104,6 @@ fn setup( // Camera commands.spawn(( Camera3d::default(), - Camera { - hdr: true, - ..default() - }, Transform::from_xyz(1.5, 1.5, 1.5).looking_at(Vec3::ZERO, Vec3::Y), Tonemapping::TonyMcMapface, Bloom::default(), diff --git a/examples/3d/post_processing.rs b/examples/3d/post_processing.rs index 54a9e9089f163..ea6e6dc3e05bc 100644 --- a/examples/3d/post_processing.rs +++ b/examples/3d/post_processing.rs @@ -7,6 +7,7 @@ use std::f32::consts::PI; use bevy::{ core_pipeline::post_process::ChromaticAberration, pbr::CascadeShadowConfigBuilder, prelude::*, }; +use bevy_render::view::Hdr; /// The number of units per frame to add to or subtract from intensity when the /// arrow keys are held. @@ -60,10 +61,7 @@ fn setup(mut commands: Commands, asset_server: Res, app_settings: R fn spawn_camera(commands: &mut Commands, asset_server: &AssetServer) { commands.spawn(( Camera3d::default(), - Camera { - hdr: true, - ..default() - }, + Hdr, Transform::from_xyz(0.7, 0.7, 1.0).looking_at(Vec3::new(0.0, 0.3, 0.0), Vec3::Y), DistanceFog { color: Color::srgb_u8(43, 44, 47), diff --git a/examples/3d/reflection_probes.rs b/examples/3d/reflection_probes.rs index e2e3ea60b4f99..a2f56414c7bb2 100644 --- a/examples/3d/reflection_probes.rs +++ b/examples/3d/reflection_probes.rs @@ -7,6 +7,7 @@ //! Reflection probes don't work on WebGL 2 or WebGPU. use bevy::{core_pipeline::Skybox, prelude::*}; +use bevy_render::view::Hdr; use std::{ f32::consts::PI, @@ -105,11 +106,8 @@ fn spawn_scene(commands: &mut Commands, asset_server: &AssetServer) { fn spawn_camera(commands: &mut Commands) { commands.spawn(( Camera3d::default(), - Camera { - hdr: true, - ..default() - }, Transform::from_xyz(-6.483, 0.325, 4.381).looking_at(Vec3::ZERO, Vec3::Y), + Hdr, )); } diff --git a/examples/3d/rotate_environment_map.rs b/examples/3d/rotate_environment_map.rs index 68ecceeccf7de..5d399e0a20d22 100644 --- a/examples/3d/rotate_environment_map.rs +++ b/examples/3d/rotate_environment_map.rs @@ -8,6 +8,7 @@ use bevy::{ image::ImageLoaderSettings, prelude::*, }; +use bevy_render::view::Hdr; /// Entry point. pub fn main() { @@ -95,10 +96,7 @@ fn spawn_camera(commands: &mut Commands, asset_server: &AssetServer) { commands .spawn(( Camera3d::default(), - Camera { - hdr: true, - ..default() - }, + Hdr, Projection::Perspective(PerspectiveProjection { fov: 27.0 / 180.0 * PI, ..default() diff --git a/examples/3d/scrolling_fog.rs b/examples/3d/scrolling_fog.rs index f65b4131701cd..3438417fb4bf6 100644 --- a/examples/3d/scrolling_fog.rs +++ b/examples/3d/scrolling_fog.rs @@ -49,10 +49,6 @@ fn setup( commands.spawn(( Camera3d::default(), Transform::from_xyz(0.0, 2.0, 0.0).looking_at(Vec3::new(-5.0, 3.5, -6.0), Vec3::Y), - Camera { - hdr: true, - ..default() - }, Msaa::Off, TemporalAntiAliasing::default(), Bloom::default(), diff --git a/examples/3d/specular_tint.rs b/examples/3d/specular_tint.rs index 5dc362b9c12e6..ff2e3bb42c6f8 100644 --- a/examples/3d/specular_tint.rs +++ b/examples/3d/specular_tint.rs @@ -3,6 +3,7 @@ use std::f32::consts::PI; use bevy::{color::palettes::css::WHITE, core_pipeline::Skybox, prelude::*}; +use bevy_render::view::Hdr; /// The camera rotation speed in radians per frame. const ROTATION_SPEED: f32 = 0.005; @@ -82,10 +83,7 @@ fn setup( // Spawns a camera. commands.spawn(( Transform::from_xyz(-2.0, 0.0, 3.5).looking_at(Vec3::ZERO, Vec3::Y), - Camera { - hdr: true, - ..default() - }, + Hdr, Camera3d::default(), Skybox { image: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"), diff --git a/examples/3d/spotlight.rs b/examples/3d/spotlight.rs index c92843404ef37..1a7a4ec1dbfc7 100644 --- a/examples/3d/spotlight.rs +++ b/examples/3d/spotlight.rs @@ -8,6 +8,7 @@ use bevy::{ pbr::NotShadowCaster, prelude::*, }; +use bevy_render::view::Hdr; use rand::{Rng, SeedableRng}; use rand_chacha::ChaCha8Rng; @@ -119,10 +120,7 @@ fn setup( // camera commands.spawn(( Camera3d::default(), - Camera { - hdr: true, - ..default() - }, + Hdr, Transform::from_xyz(-4.0, 5.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y), )); diff --git a/examples/3d/ssao.rs b/examples/3d/ssao.rs index d036fb805dd03..9e962bdd1d478 100644 --- a/examples/3d/ssao.rs +++ b/examples/3d/ssao.rs @@ -7,6 +7,7 @@ use bevy::{ prelude::*, render::camera::TemporalJitter, }; +use bevy_render::view::Hdr; use std::f32::consts::PI; fn main() { @@ -28,11 +29,8 @@ fn setup( ) { commands.spawn(( Camera3d::default(), - Camera { - hdr: true, - ..default() - }, Transform::from_xyz(-2.0, 2.0, -2.0).looking_at(Vec3::ZERO, Vec3::Y), + Hdr, Msaa::Off, ScreenSpaceAmbientOcclusion::default(), TemporalAntiAliasing::default(), diff --git a/examples/3d/ssr.rs b/examples/3d/ssr.rs index a4d2c1b742c0f..dfab1b36a0917 100644 --- a/examples/3d/ssr.rs +++ b/examples/3d/ssr.rs @@ -18,6 +18,7 @@ use bevy::{ prelude::*, render::render_resource::{AsBindGroup, ShaderRef, ShaderType}, }; +use bevy_render::view::Hdr; /// This example uses a shader source file from the assets subdirectory const SHADER_ASSET_PATH: &str = "shaders/water_material.wgsl"; @@ -227,10 +228,7 @@ fn spawn_camera(commands: &mut Commands, asset_server: &AssetServer) { .spawn(( Camera3d::default(), Transform::from_translation(vec3(-1.25, 2.25, 4.5)).looking_at(Vec3::ZERO, Vec3::Y), - Camera { - hdr: true, - ..default() - }, + Hdr, Msaa::Off, )) .insert(EnvironmentMapLight { diff --git a/examples/3d/tonemapping.rs b/examples/3d/tonemapping.rs index e68e0d837c3f3..36b5b71afc5a9 100644 --- a/examples/3d/tonemapping.rs +++ b/examples/3d/tonemapping.rs @@ -11,6 +11,7 @@ use bevy::{ view::{ColorGrading, ColorGradingGlobal, ColorGradingSection}, }, }; +use bevy_render::view::Hdr; use std::f32::consts::PI; /// This example uses a shader source file from the assets subdirectory @@ -59,10 +60,7 @@ fn setup( // camera commands.spawn(( Camera3d::default(), - Camera { - hdr: true, - ..default() - }, + Hdr, camera_transform.0, DistanceFog { color: Color::srgb_u8(43, 44, 47), diff --git a/examples/3d/transmission.rs b/examples/3d/transmission.rs index e4df69b3d96fa..09f7c85fce3c2 100644 --- a/examples/3d/transmission.rs +++ b/examples/3d/transmission.rs @@ -303,10 +303,6 @@ fn setup( // Camera commands.spawn(( Camera3d::default(), - Camera { - hdr: true, - ..default() - }, Transform::from_xyz(1.0, 1.8, 7.0).looking_at(Vec3::ZERO, Vec3::Y), ColorGrading { global: ColorGradingGlobal { diff --git a/examples/3d/volumetric_fog.rs b/examples/3d/volumetric_fog.rs index 9cfef624c6594..1d13e333c9d31 100644 --- a/examples/3d/volumetric_fog.rs +++ b/examples/3d/volumetric_fog.rs @@ -65,10 +65,6 @@ fn setup(mut commands: Commands, asset_server: Res, app_settings: R commands .spawn(( Camera3d::default(), - Camera { - hdr: true, - ..default() - }, Transform::from_xyz(-1.7, 1.5, 4.5).looking_at(vec3(-1.5, 1.7, 3.5), Vec3::Y), Tonemapping::TonyMcMapface, Bloom::default(), diff --git a/examples/animation/animation_events.rs b/examples/animation/animation_events.rs index 177fa2f47f300..81df9233ecc2a 100644 --- a/examples/animation/animation_events.rs +++ b/examples/animation/animation_events.rs @@ -5,6 +5,7 @@ use bevy::{ core_pipeline::bloom::Bloom, prelude::*, }; +use bevy_render::view::Hdr; fn main() { App::new() @@ -44,7 +45,6 @@ fn setup( Camera2d, Camera { clear_color: ClearColorConfig::Custom(BLACK.into()), - hdr: true, ..Default::default() }, Bloom { diff --git a/examples/camera/2d_top_down_camera.rs b/examples/camera/2d_top_down_camera.rs index 98bf0bcaf4180..2ab89c8c3872a 100644 --- a/examples/camera/2d_top_down_camera.rs +++ b/examples/camera/2d_top_down_camera.rs @@ -61,14 +61,7 @@ fn setup_instructions(mut commands: Commands) { } fn setup_camera(mut commands: Commands) { - commands.spawn(( - Camera2d, - Camera { - hdr: true, // HDR is required for the bloom effect - ..default() - }, - Bloom::NATURAL, - )); + commands.spawn((Camera2d, Bloom::NATURAL)); } /// Update the camera position by tracking the player. diff --git a/examples/math/sampling_primitives.rs b/examples/math/sampling_primitives.rs index 446f6c911fe06..9601ac3d317dc 100644 --- a/examples/math/sampling_primitives.rs +++ b/examples/math/sampling_primitives.rs @@ -8,6 +8,7 @@ use bevy::{ math::prelude::*, prelude::*, }; +use bevy_render::view::Hdr; use rand::{seq::SliceRandom, Rng, SeedableRng}; use rand_chacha::ChaCha8Rng; @@ -340,7 +341,6 @@ fn setup( commands.spawn(( Camera3d::default(), Camera { - hdr: true, // HDR is required for bloom clear_color: ClearColorConfig::Custom(SKY_COLOR), ..default() }, diff --git a/examples/testbed/2d.rs b/examples/testbed/2d.rs index 5dca64236d83e..4282bcf2c4bcd 100644 --- a/examples/testbed/2d.rs +++ b/examples/testbed/2d.rs @@ -121,10 +121,6 @@ mod bloom { ) { commands.spawn(( Camera2d, - Camera { - hdr: true, - ..default() - }, Tonemapping::TonyMcMapface, Bloom::default(), StateScoped(super::Scene::Bloom), diff --git a/examples/testbed/3d.rs b/examples/testbed/3d.rs index 6a07f6fae9cb2..316f13dca8859 100644 --- a/examples/testbed/3d.rs +++ b/examples/testbed/3d.rs @@ -155,10 +155,6 @@ mod bloom { ) { commands.spawn(( Camera3d::default(), - Camera { - hdr: true, - ..default() - }, Tonemapping::TonyMcMapface, Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y), Bloom::NATURAL, From 61f490e78b81d6ace23b23f4b7adf530618615d4 Mon Sep 17 00:00:00 2001 From: Emerson Coskey Date: Sat, 19 Apr 2025 13:21:59 -0700 Subject: [PATCH 03/10] fix imports --- examples/3d/anti_aliasing.rs | 2 +- examples/3d/atmosphere.rs | 3 +-- examples/3d/clearcoat.rs | 2 +- examples/3d/color_grading.rs | 3 +-- examples/3d/fog_volumes.rs | 2 +- examples/3d/post_processing.rs | 2 +- examples/3d/reflection_probes.rs | 3 +-- examples/3d/rotate_environment_map.rs | 2 +- examples/3d/specular_tint.rs | 3 +-- examples/3d/spotlight.rs | 2 +- examples/3d/ssao.rs | 3 +-- examples/3d/ssr.rs | 6 ++++-- examples/3d/tonemapping.rs | 3 +-- examples/animation/animation_events.rs | 2 +- examples/math/sampling_primitives.rs | 2 +- 15 files changed, 18 insertions(+), 22 deletions(-) diff --git a/examples/3d/anti_aliasing.rs b/examples/3d/anti_aliasing.rs index a26e9b3700518..1f693ce23886a 100644 --- a/examples/3d/anti_aliasing.rs +++ b/examples/3d/anti_aliasing.rs @@ -17,9 +17,9 @@ use bevy::{ camera::TemporalJitter, render_asset::RenderAssetUsages, render_resource::{Extent3d, TextureDimension, TextureFormat}, + view::Hdr, }, }; -use bevy_render::view::Hdr; fn main() { App::new() diff --git a/examples/3d/atmosphere.rs b/examples/3d/atmosphere.rs index 04e12fe3653f6..2a31824c6e525 100644 --- a/examples/3d/atmosphere.rs +++ b/examples/3d/atmosphere.rs @@ -6,9 +6,8 @@ use bevy::{ core_pipeline::{bloom::Bloom, tonemapping::Tonemapping}, pbr::{light_consts::lux, Atmosphere, AtmosphereSettings, CascadeShadowConfigBuilder}, prelude::*, - render::camera::Exposure, + render::{camera::Exposure, view::Hdr}, }; -use bevy_render::view::Hdr; fn main() { App::new() diff --git a/examples/3d/clearcoat.rs b/examples/3d/clearcoat.rs index 5d283878395e6..9337906c37f87 100644 --- a/examples/3d/clearcoat.rs +++ b/examples/3d/clearcoat.rs @@ -25,8 +25,8 @@ use bevy::{ image::ImageLoaderSettings, math::vec3, prelude::*, + render::view::Hdr, }; -use bevy_render::view::Hdr; /// The size of each sphere. const SPHERE_SCALE: f32 = 0.9; diff --git a/examples/3d/color_grading.rs b/examples/3d/color_grading.rs index 869382ea07e66..735efb9ef1563 100644 --- a/examples/3d/color_grading.rs +++ b/examples/3d/color_grading.rs @@ -9,9 +9,8 @@ use bevy::{ ecs::system::EntityCommands, pbr::CascadeShadowConfigBuilder, prelude::*, - render::view::{ColorGrading, ColorGradingGlobal, ColorGradingSection}, + render::view::{ColorGrading, ColorGradingGlobal, ColorGradingSection, Hdr}, }; -use bevy_render::view::Hdr; use std::fmt::Display; static FONT_PATH: &str = "fonts/FiraMono-Medium.ttf"; diff --git a/examples/3d/fog_volumes.rs b/examples/3d/fog_volumes.rs index 792aa0eb5a036..63804ee9dea82 100644 --- a/examples/3d/fog_volumes.rs +++ b/examples/3d/fog_volumes.rs @@ -9,8 +9,8 @@ use bevy::{ math::vec3, pbr::{FogVolume, VolumetricFog, VolumetricLight}, prelude::*, + render::view::Hdr, }; -use bevy_render::view::Hdr; /// Entry point. fn main() { diff --git a/examples/3d/post_processing.rs b/examples/3d/post_processing.rs index ea6e6dc3e05bc..e539d94b3093c 100644 --- a/examples/3d/post_processing.rs +++ b/examples/3d/post_processing.rs @@ -6,8 +6,8 @@ use std::f32::consts::PI; use bevy::{ core_pipeline::post_process::ChromaticAberration, pbr::CascadeShadowConfigBuilder, prelude::*, + render::view::Hdr, }; -use bevy_render::view::Hdr; /// The number of units per frame to add to or subtract from intensity when the /// arrow keys are held. diff --git a/examples/3d/reflection_probes.rs b/examples/3d/reflection_probes.rs index a2f56414c7bb2..6b2db9d39ca2c 100644 --- a/examples/3d/reflection_probes.rs +++ b/examples/3d/reflection_probes.rs @@ -6,8 +6,7 @@ //! //! Reflection probes don't work on WebGL 2 or WebGPU. -use bevy::{core_pipeline::Skybox, prelude::*}; -use bevy_render::view::Hdr; +use bevy::{core_pipeline::Skybox, prelude::*, render::view::Hdr}; use std::{ f32::consts::PI, diff --git a/examples/3d/rotate_environment_map.rs b/examples/3d/rotate_environment_map.rs index 5d399e0a20d22..71a4fd751315c 100644 --- a/examples/3d/rotate_environment_map.rs +++ b/examples/3d/rotate_environment_map.rs @@ -7,8 +7,8 @@ use bevy::{ core_pipeline::{tonemapping::Tonemapping::AcesFitted, Skybox}, image::ImageLoaderSettings, prelude::*, + render::view::Hdr, }; -use bevy_render::view::Hdr; /// Entry point. pub fn main() { diff --git a/examples/3d/specular_tint.rs b/examples/3d/specular_tint.rs index ff2e3bb42c6f8..148f11ba5caf6 100644 --- a/examples/3d/specular_tint.rs +++ b/examples/3d/specular_tint.rs @@ -2,8 +2,7 @@ use std::f32::consts::PI; -use bevy::{color::palettes::css::WHITE, core_pipeline::Skybox, prelude::*}; -use bevy_render::view::Hdr; +use bevy::{color::palettes::css::WHITE, core_pipeline::Skybox, prelude::*, render::view::Hdr}; /// The camera rotation speed in radians per frame. const ROTATION_SPEED: f32 = 0.005; diff --git a/examples/3d/spotlight.rs b/examples/3d/spotlight.rs index 1a7a4ec1dbfc7..3885f47e65fbf 100644 --- a/examples/3d/spotlight.rs +++ b/examples/3d/spotlight.rs @@ -7,8 +7,8 @@ use bevy::{ math::ops, pbr::NotShadowCaster, prelude::*, + render::view::Hdr, }; -use bevy_render::view::Hdr; use rand::{Rng, SeedableRng}; use rand_chacha::ChaCha8Rng; diff --git a/examples/3d/ssao.rs b/examples/3d/ssao.rs index 9e962bdd1d478..b33ab42090233 100644 --- a/examples/3d/ssao.rs +++ b/examples/3d/ssao.rs @@ -5,9 +5,8 @@ use bevy::{ math::ops, pbr::{ScreenSpaceAmbientOcclusion, ScreenSpaceAmbientOcclusionQualityLevel}, prelude::*, - render::camera::TemporalJitter, + render::{camera::TemporalJitter, view::Hdr}, }; -use bevy_render::view::Hdr; use std::f32::consts::PI; fn main() { diff --git a/examples/3d/ssr.rs b/examples/3d/ssr.rs index dfab1b36a0917..9deb9ee2c2eed 100644 --- a/examples/3d/ssr.rs +++ b/examples/3d/ssr.rs @@ -16,9 +16,11 @@ use bevy::{ DefaultOpaqueRendererMethod, ExtendedMaterial, MaterialExtension, ScreenSpaceReflections, }, prelude::*, - render::render_resource::{AsBindGroup, ShaderRef, ShaderType}, + render::{ + render_resource::{AsBindGroup, ShaderRef, ShaderType}, + view::Hdr, + }, }; -use bevy_render::view::Hdr; /// This example uses a shader source file from the assets subdirectory const SHADER_ASSET_PATH: &str = "shaders/water_material.wgsl"; diff --git a/examples/3d/tonemapping.rs b/examples/3d/tonemapping.rs index 2d49090d8e6b0..fbad93e29fe0d 100644 --- a/examples/3d/tonemapping.rs +++ b/examples/3d/tonemapping.rs @@ -8,10 +8,9 @@ use bevy::{ reflect::TypePath, render::{ render_resource::{AsBindGroup, ShaderRef}, - view::{ColorGrading, ColorGradingGlobal, ColorGradingSection}, + view::{ColorGrading, ColorGradingGlobal, ColorGradingSection, Hdr}, }, }; -use bevy_render::view::Hdr; use std::f32::consts::PI; /// This example uses a shader source file from the assets subdirectory diff --git a/examples/animation/animation_events.rs b/examples/animation/animation_events.rs index 81df9233ecc2a..2d1188c7a6826 100644 --- a/examples/animation/animation_events.rs +++ b/examples/animation/animation_events.rs @@ -4,8 +4,8 @@ use bevy::{ color::palettes::css::{ALICE_BLUE, BLACK, CRIMSON}, core_pipeline::bloom::Bloom, prelude::*, + render::view::Hdr, }; -use bevy_render::view::Hdr; fn main() { App::new() diff --git a/examples/math/sampling_primitives.rs b/examples/math/sampling_primitives.rs index 9601ac3d317dc..d3d6b973898e9 100644 --- a/examples/math/sampling_primitives.rs +++ b/examples/math/sampling_primitives.rs @@ -7,8 +7,8 @@ use bevy::{ input::mouse::{AccumulatedMouseMotion, AccumulatedMouseScroll, MouseButtonInput}, math::prelude::*, prelude::*, + render::view::Hdr, }; -use bevy_render::view::Hdr; use rand::{seq::SliceRandom, Rng, SeedableRng}; use rand_chacha::ChaCha8Rng; From 694c41ac6e9aefcaa5068a6c908c49b15ca9627a Mon Sep 17 00:00:00 2001 From: Emerson Coskey Date: Sat, 19 Apr 2025 13:27:04 -0700 Subject: [PATCH 04/10] fix imports --- examples/3d/atmosphere.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/3d/atmosphere.rs b/examples/3d/atmosphere.rs index 2a31824c6e525..edc6d04dab7b0 100644 --- a/examples/3d/atmosphere.rs +++ b/examples/3d/atmosphere.rs @@ -6,7 +6,7 @@ use bevy::{ core_pipeline::{bloom::Bloom, tonemapping::Tonemapping}, pbr::{light_consts::lux, Atmosphere, AtmosphereSettings, CascadeShadowConfigBuilder}, prelude::*, - render::{camera::Exposure, view::Hdr}, + render::camera::Exposure, }; fn main() { From 65ee8d388e9122007babd5a2f19abd1eeccc8103 Mon Sep 17 00:00:00 2001 From: Emerson Coskey Date: Sat, 19 Apr 2025 13:41:40 -0700 Subject: [PATCH 05/10] add migration guide --- release-content/migration-guides/camera_restructure.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 release-content/migration-guides/camera_restructure.md diff --git a/release-content/migration-guides/camera_restructure.md b/release-content/migration-guides/camera_restructure.md new file mode 100644 index 0000000000000..087850cb47103 --- /dev/null +++ b/release-content/migration-guides/camera_restructure.md @@ -0,0 +1,10 @@ +--- +title: Camera Restructure +pull_requests: [18873] +--- + +As part of the rendering crate reorganization, we've been working to simplify Bevy `Camera`s: + +- `Camera.hdr` has been split out into a new marker component, `Hdr` + - before: `commands.spawn((Camera3d, Camera { hdr: true, ..default() });` + - after: `commands.spawn((Camera3d, Hdr));` From 7e6768a1f9e06d14ca3108be3bb7459eaa374ede Mon Sep 17 00:00:00 2001 From: Emerson Coskey Date: Tue, 22 Apr 2025 14:15:50 -0700 Subject: [PATCH 06/10] address review comments --- examples/3d/bloom_3d.rs | 6 +++--- examples/math/sampling_primitives.rs | 1 - release-content/migration-guides/camera_restructure.md | 1 + 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/3d/bloom_3d.rs b/examples/3d/bloom_3d.rs index a54847b241be3..113fb95b1b3cc 100644 --- a/examples/3d/bloom_3d.rs +++ b/examples/3d/bloom_3d.rs @@ -32,13 +32,13 @@ fn setup_scene( clear_color: ClearColorConfig::Custom(Color::BLACK), ..default() }, - Tonemapping::TonyMcMapface, // 2. Using a tonemapper that desaturates to white is recommended + Tonemapping::TonyMcMapface, // 1. Using a tonemapper that desaturates to white is recommended Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y), - Bloom::NATURAL, // 3. Enable bloom for the camera + Bloom::NATURAL, // 2. Enable bloom for the camera )); let material_emissive1 = materials.add(StandardMaterial { - emissive: LinearRgba::rgb(0.0, 0.0, 150.0), // 4. Put something bright in a dark environment to see the effect + emissive: LinearRgba::rgb(0.0, 0.0, 150.0), // 3. Put something bright in a dark environment to see the effect ..default() }); let material_emissive2 = materials.add(StandardMaterial { diff --git a/examples/math/sampling_primitives.rs b/examples/math/sampling_primitives.rs index d3d6b973898e9..8a227123ab84a 100644 --- a/examples/math/sampling_primitives.rs +++ b/examples/math/sampling_primitives.rs @@ -7,7 +7,6 @@ use bevy::{ input::mouse::{AccumulatedMouseMotion, AccumulatedMouseScroll, MouseButtonInput}, math::prelude::*, prelude::*, - render::view::Hdr, }; use rand::{seq::SliceRandom, Rng, SeedableRng}; use rand_chacha::ChaCha8Rng; diff --git a/release-content/migration-guides/camera_restructure.md b/release-content/migration-guides/camera_restructure.md index 087850cb47103..abd0e7e27b7b6 100644 --- a/release-content/migration-guides/camera_restructure.md +++ b/release-content/migration-guides/camera_restructure.md @@ -8,3 +8,4 @@ As part of the rendering crate reorganization, we've been working to simplify Be - `Camera.hdr` has been split out into a new marker component, `Hdr` - before: `commands.spawn((Camera3d, Camera { hdr: true, ..default() });` - after: `commands.spawn((Camera3d, Hdr));` + - rendering effects can now `#[require(Hdr)]` if they only function with an HDR camera. From bd3808d614980461112311fc8c6db4e436ee8e5d Mon Sep 17 00:00:00 2001 From: Emerson Coskey Date: Sat, 26 Apr 2025 17:43:26 -0700 Subject: [PATCH 07/10] fix blend_modes --- examples/3d/blend_modes.rs | 26 +++++++++++++++---- .../migration-guides/camera_restructure.md | 1 + 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/examples/3d/blend_modes.rs b/examples/3d/blend_modes.rs index 830acfdb34160..5c0e97e41efa1 100644 --- a/examples/3d/blend_modes.rs +++ b/examples/3d/blend_modes.rs @@ -10,7 +10,7 @@ //! | `Spacebar` | Toggle Unlit | //! | `C` | Randomize Colors | -use bevy::{color::palettes::css::ORANGE, prelude::*}; +use bevy::{color::palettes::css::ORANGE, prelude::*, render::view::Hdr}; use rand::random; fn main() { @@ -149,6 +149,7 @@ fn setup( commands.spawn(( Camera3d::default(), Transform::from_xyz(0.0, 2.5, 10.0).looking_at(Vec3::ZERO, Vec3::Y), + Hdr, // Unfortunately, MSAA and HDR are not supported simultaneously under WebGL. // Since this example uses HDR, we must disable MSAA for Wasm builds, at least // until WebGPU is ready and no longer behind a feature flag in Web browsers. @@ -249,13 +250,23 @@ impl Default for ExampleState { fn example_control_system( mut materials: ResMut>, controllable: Query<(&MeshMaterial3d, &ExampleControls)>, - camera: Single<(&mut Camera, &mut Transform, &GlobalTransform), With>, + camera: Single< + ( + Entity, + &mut Camera, + &mut Transform, + &GlobalTransform, + Has, + ), + With, + >, mut labels: Query<(&mut Node, &ExampleLabel)>, mut display: Single<&mut Text, With>, labeled: Query<&GlobalTransform>, mut state: Local, time: Res