Split Camera.hdr out into a new component (#18873)

# Objective

- Simplify `Camera` initialization
- allow effects to require HDR

## Solution

- Split out `Camera.hdr` into a marker `Hdr` component

## Testing

- ran `bloom_3d` example

---

## Showcase

```rs
// before
commands.spawn((
  Camera3d
  Camera {
    hdr: true
    ..Default::default()
  }
))

// after
commands.spawn((Camera3d, Hdr));

// other rendering components can require that the camera enables hdr!
// currently implemented for Bloom, AutoExposure, and Atmosphere.
#[require(Hdr)]
pub struct Bloom;
```
This commit is contained in:
Emerson Coskey 2025-05-26 12:24:45 -07:00 committed by GitHub
parent cedf8d357a
commit 7ab00ca185
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
36 changed files with 109 additions and 153 deletions

View File

@ -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.
///

View File

@ -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<Hdr>;
type Out = (Self, BloomUniforms);
fn extract_component((bloom, camera): QueryItem<'_, Self::QueryData>) -> Option<Self::Out> {
@ -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;

View File

@ -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

View File

@ -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<Atmosphere>>,
views: Query<(Entity, &Msaa), (With<Camera>, With<Atmosphere>)>,
pipeline_cache: Res<PipelineCache>,
layouts: Res<RenderSkyBindGroupLayouts>,
mut specializer: ResMut<SpecializedRenderPipelines<RenderSkyBindGroupLayouts>>,
render_device: Res<RenderDevice>,
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),

View File

@ -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<Hdr>,
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,

View File

@ -114,6 +114,7 @@ impl Plugin for ViewPlugin {
.register_type::<OcclusionCulling>()
// NOTE: windows.is_changed() handles cases where a window was resized
.add_plugins((
ExtractComponentPlugin::<Hdr>::default(),
ExtractComponentPlugin::<Msaa>::default(),
ExtractComponentPlugin::<OcclusionCulling>::default(),
VisibilityPlugin,
@ -199,6 +200,16 @@ 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. However, this does *not* affect
/// whether the camera will render with hdr display output (which bevy does not support currently)
/// and only affects the intermediate render texture.
#[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

View File

@ -28,7 +28,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,
@ -662,6 +662,7 @@ pub fn extract_ui_camera_view(
Entity,
RenderEntity,
&Camera,
Has<Hdr>,
Option<&UiAntiAlias>,
Option<&BoxShadowSamples>,
),
@ -672,7 +673,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
@ -708,7 +709,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(),

View File

@ -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()
},

View File

@ -17,6 +17,7 @@ use bevy::{
camera::TemporalJitter,
render_asset::RenderAssetUsages,
render_resource::{Extent3d, TextureDimension, TextureFormat},
view::Hdr,
},
};
@ -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,

View File

@ -20,11 +20,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 +31,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.

View File

@ -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(),

View File

@ -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<Assets<StandardMaterial>>,
controllable: Query<(&MeshMaterial3d<StandardMaterial>, &ExampleControls)>,
camera: Single<(&mut Camera, &mut Transform, &GlobalTransform), With<Camera3d>>,
camera: Single<
(
Entity,
&mut Camera,
&mut Transform,
&GlobalTransform,
Has<Hdr>,
),
With<Camera3d>,
>,
mut labels: Query<(&mut Node, &ExampleLabel)>,
mut display: Single<&mut Text, With<ExampleDisplay>>,
labeled: Query<&GlobalTransform>,
mut state: Local<ExampleState>,
time: Res<Time>,
input: Res<ButtonInput<KeyCode>>,
mut commands: Commands,
) {
if input.pressed(KeyCode::ArrowUp) {
state.alpha = (state.alpha + time.delta_secs()).min(1.0);
@ -289,10 +300,14 @@ fn example_control_system(
}
}
let (mut camera, mut camera_transform, camera_global_transform) = camera.into_inner();
let (entity, camera, mut camera_transform, camera_global_transform, hdr) = camera.into_inner();
if input.just_pressed(KeyCode::KeyH) {
camera.hdr = !camera.hdr;
if hdr {
commands.entity(entity).remove::<Hdr>();
} else {
commands.entity(entity).insert(Hdr);
}
}
let rotation = if input.pressed(KeyCode::ArrowLeft) {
@ -318,7 +333,7 @@ fn example_control_system(
display.0 = format!(
" HDR: {}\nAlpha: {:.2}",
if camera.hdr { "ON " } else { "OFF" },
if hdr { "ON " } else { "OFF" },
state.alpha
);
}

View File

@ -29,17 +29,16 @@ fn setup_scene(
commands.spawn((
Camera3d::default(),
Camera {
hdr: true, // 1. HDR is required for bloom
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 {

View File

@ -25,6 +25,7 @@ use bevy::{
image::ImageLoaderSettings,
math::vec3,
prelude::*,
render::view::Hdr,
};
/// The size of each sphere.
@ -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()

View File

@ -9,7 +9,7 @@ use bevy::{
ecs::system::EntityCommands,
pbr::CascadeShadowConfigBuilder,
prelude::*,
render::view::{ColorGrading, ColorGradingGlobal, ColorGradingSection},
render::view::{ColorGrading, ColorGradingGlobal, ColorGradingSection, Hdr},
};
use std::fmt::Display;
@ -334,10 +334,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 {

View File

@ -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,

View File

@ -74,10 +74,6 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, 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,
));

View File

@ -9,6 +9,7 @@ use bevy::{
math::vec3,
pbr::{FogVolume, VolumetricFog, VolumetricLight},
prelude::*,
render::view::Hdr,
};
/// Entry point.
@ -58,10 +59,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
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,

View File

@ -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(),

View File

@ -6,6 +6,7 @@ use std::f32::consts::PI;
use bevy::{
core_pipeline::post_process::ChromaticAberration, pbr::CascadeShadowConfigBuilder, prelude::*,
render::view::Hdr,
};
/// The number of units per frame to add to or subtract from intensity when the
@ -60,10 +61,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, 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),

View File

@ -6,7 +6,7 @@
//!
//! Reflection probes don't work on WebGL 2 or WebGPU.
use bevy::{core_pipeline::Skybox, prelude::*};
use bevy::{core_pipeline::Skybox, prelude::*, render::view::Hdr};
use std::{
f32::consts::PI,
@ -105,11 +105,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,
));
}

View File

@ -7,6 +7,7 @@ use bevy::{
core_pipeline::{tonemapping::Tonemapping::AcesFitted, Skybox},
image::ImageLoaderSettings,
prelude::*,
render::view::Hdr,
};
/// Entry point.
@ -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()

View File

@ -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(),

View File

@ -2,7 +2,7 @@
use std::f32::consts::PI;
use bevy::{color::palettes::css::WHITE, core_pipeline::Skybox, prelude::*};
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;
@ -82,10 +82,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"),

View File

@ -7,6 +7,7 @@ use bevy::{
math::ops,
pbr::NotShadowCaster,
prelude::*,
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),
));

View File

@ -5,7 +5,7 @@ use bevy::{
math::ops,
pbr::{ScreenSpaceAmbientOcclusion, ScreenSpaceAmbientOcclusionQualityLevel},
prelude::*,
render::camera::TemporalJitter,
render::{camera::TemporalJitter, view::Hdr},
};
use std::f32::consts::PI;
@ -28,11 +28,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(),

View File

@ -16,7 +16,10 @@ use bevy::{
DefaultOpaqueRendererMethod, ExtendedMaterial, MaterialExtension, ScreenSpaceReflections,
},
prelude::*,
render::render_resource::{AsBindGroup, ShaderRef, ShaderType},
render::{
render_resource::{AsBindGroup, ShaderRef, ShaderType},
view::Hdr,
},
};
/// This example uses a shader source file from the assets subdirectory
@ -227,10 +230,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 {

View File

@ -9,7 +9,7 @@ use bevy::{
reflect::TypePath,
render::{
render_resource::{AsBindGroup, ShaderRef},
view::{ColorGrading, ColorGradingGlobal, ColorGradingSection},
view::{ColorGrading, ColorGradingGlobal, ColorGradingSection, Hdr},
},
};
use std::f32::consts::PI;
@ -65,10 +65,7 @@ fn setup(
// camera
commands.spawn((
Camera3d::default(),
Camera {
hdr: true,
..default()
},
Hdr,
camera_transform.0,
DistanceFog {
color: Color::srgb_u8(43, 44, 47),

View File

@ -31,7 +31,7 @@ use bevy::{
prelude::*,
render::{
camera::{Exposure, TemporalJitter},
view::{ColorGrading, ColorGradingGlobal},
view::{ColorGrading, ColorGradingGlobal, Hdr},
},
};
@ -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 {
@ -387,11 +383,11 @@ fn example_control_system(
camera: Single<
(
Entity,
&mut Camera,
&mut Camera3d,
&mut Transform,
Option<&DepthPrepass>,
Option<&TemporalJitter>,
Has<Hdr>,
),
With<Camera3d>,
>,
@ -458,17 +454,15 @@ fn example_control_system(
}
}
let (
camera_entity,
mut camera,
mut camera_3d,
mut camera_transform,
depth_prepass,
temporal_jitter,
) = camera.into_inner();
let (camera_entity, mut camera_3d, mut camera_transform, depth_prepass, temporal_jitter, hdr) =
camera.into_inner();
if input.just_pressed(KeyCode::KeyH) {
camera.hdr = !camera.hdr;
if hdr {
commands.entity(camera_entity).remove::<Hdr>();
} else {
commands.entity(camera_entity).insert(Hdr);
}
}
#[cfg(any(feature = "webgpu", not(target_arch = "wasm32")))]
@ -571,7 +565,7 @@ fn example_control_system(
state.ior,
state.perceptual_roughness,
state.reflectance,
if camera.hdr { "ON " } else { "OFF" },
if hdr { "ON " } else { "OFF" },
if cfg!(any(feature = "webgpu", not(target_arch = "wasm32"))) {
if depth_prepass.is_some() {
"ON "

View File

@ -65,10 +65,6 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, 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(),

View File

@ -44,7 +44,6 @@ fn setup(
Camera2d,
Camera {
clear_color: ClearColorConfig::Custom(BLACK.into()),
hdr: true,
..Default::default()
},
Bloom {

View File

@ -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.

View File

@ -340,7 +340,6 @@ fn setup(
commands.spawn((
Camera3d::default(),
Camera {
hdr: true, // HDR is required for bloom
clear_color: ClearColorConfig::Custom(SKY_COLOR),
..default()
},

View File

@ -121,10 +121,6 @@ mod bloom {
) {
commands.spawn((
Camera2d,
Camera {
hdr: true,
..default()
},
Tonemapping::TonyMcMapface,
Bloom::default(),
DespawnOnExitState(super::Scene::Bloom),

View File

@ -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,

View File

@ -0,0 +1,12 @@
---
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));`
- rendering effects can now `#[require(Hdr)]` if they only function with an HDR camera.
This is currently implemented for `Bloom`, `AutoExposure`, and `Atmosphere`