diff --git a/_release-content/migration-guides/skybox_image.md b/_release-content/migration-guides/skybox_image.md new file mode 100644 index 0000000000000..58e7f91b99b23 --- /dev/null +++ b/_release-content/migration-guides/skybox_image.md @@ -0,0 +1,42 @@ +--- +title: "`Skybox` `image` is now optional" +pull_requests: [23691] +--- + +The `image` field of the `Skybox` component now has the type `Option>` instead of `Handle`. +A `Skybox` component without an image will not draw anything, just like it was not present. + +If you were creating a skybox with an image, wrap the image handle in `Some`: + +```rust +// 0.18 +Skybox { + image: my_skybox, + brightness: 1000.0, + ..default() +} + +// 0.19 +Skybox { + image: Some(my_skybox), + brightness: 1000.0, + ..default() +} +``` + +If you were previously creating a `Skybox` component with a placeholder image to be changed later, you can now remove the placeholder: + +```rust +// 0.18 +Skybox { + image: cubemap_image_that_will_not_actually_be_seen, + brightness: 1000.0, + ..default() +} + +// 0.19 +Skybox { + brightness: 1000.0, + ..default() +} +``` diff --git a/crates/bevy_core_pipeline/src/skybox/mod.rs b/crates/bevy_core_pipeline/src/skybox/mod.rs index d2f1abb1830aa..b2d2411d74a19 100644 --- a/crates/bevy_core_pipeline/src/skybox/mod.rs +++ b/crates/bevy_core_pipeline/src/skybox/mod.rs @@ -227,17 +227,18 @@ fn prepare_skybox_bind_groups( views: Query<(Entity, &Skybox, &DynamicUniformIndex)>, ) { for (entity, skybox, skybox_uniform_index) in &views { - if let (Some(skybox), Some(view_uniforms), Some(skybox_uniforms)) = ( - images.get(&skybox.image), + if let (Some(image_handle), Some(view_uniforms), Some(skybox_uniforms)) = ( + &skybox.image, view_uniforms.uniforms.binding(), skybox_uniforms.binding(), - ) { + ) && let Some(image) = images.get(image_handle) + { let bind_group = render_device.create_bind_group( "skybox_bind_group", &pipeline_cache.get_bind_group_layout(&pipeline.bind_group_layout), &BindGroupEntries::sequential(( - &skybox.texture_view, - &skybox.sampler, + &image.texture_view, + &image.sampler, view_uniforms, skybox_uniforms, )), @@ -246,6 +247,8 @@ fn prepare_skybox_bind_groups( commands .entity(entity) .insert(SkyboxBindGroup((bind_group, skybox_uniform_index.index()))); + } else { + commands.entity(entity).remove::(); } } } diff --git a/crates/bevy_light/src/probe.rs b/crates/bevy_light/src/probe.rs index be02d510f502c..66ee5cd72c55d 100644 --- a/crates/bevy_light/src/probe.rs +++ b/crates/bevy_light/src/probe.rs @@ -1,7 +1,8 @@ -use bevy_asset::{Assets, Handle, RenderAssetUsages}; +use bevy_asset::{Assets, Handle, HandleTemplate, RenderAssetUsages}; use bevy_camera::visibility::{self, ViewVisibility, Visibility, VisibilityClass}; use bevy_color::{Color, ColorToComponents, Srgba}; use bevy_ecs::prelude::*; +use bevy_ecs::template::{FromTemplate, OptionTemplate}; use bevy_image::Image; use bevy_math::{Quat, UVec2, Vec3}; use bevy_reflect::prelude::*; @@ -224,7 +225,12 @@ impl Default for EnvironmentMapLight { #[reflect(Component, Default, Clone)] pub struct Skybox { /// The cubemap to use. - pub image: Handle, + /// + /// If this is [`None`], the skybox will not be rendered, as if it does not exist. + /// This allows `Skybox` to implement [`Default`]. + #[template(OptionTemplate>)] + pub image: Option>, + /// Scale factor applied to the skybox image. /// After applying this multiplier to the image samples, the resulting values should /// be in units of [cd/m^2](https://en.wikipedia.org/wiki/Candela_per_square_metre). @@ -239,7 +245,7 @@ pub struct Skybox { impl Default for Skybox { fn default() -> Self { Skybox { - image: Handle::default(), + image: None, brightness: 0.0, rotation: Quat::IDENTITY, } diff --git a/examples/3d/anisotropy.rs b/examples/3d/anisotropy.rs index d2d4ef9175ec4..3ada5c9b8b650 100644 --- a/examples/3d/anisotropy.rs +++ b/examples/3d/anisotropy.rs @@ -305,7 +305,7 @@ fn add_skybox_and_environment_map( .entity(entity) .insert(Skybox { brightness: 5000.0, - image: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"), + image: Some(asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2")), ..default() }) .insert(EnvironmentMapLight { diff --git a/examples/3d/auto_exposure.rs b/examples/3d/auto_exposure.rs index 6b92b124fe0a1..0e640fa0c7e77 100644 --- a/examples/3d/auto_exposure.rs +++ b/examples/3d/auto_exposure.rs @@ -46,7 +46,7 @@ fn setup( ..default() }, Skybox { - image: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"), + image: Some(asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2")), brightness: light_consts::lux::DIRECT_SUNLIGHT, ..default() }, diff --git a/examples/3d/clearcoat.rs b/examples/3d/clearcoat.rs index ef4abe793cb8e..996f5063b5068 100644 --- a/examples/3d/clearcoat.rs +++ b/examples/3d/clearcoat.rs @@ -203,7 +203,7 @@ fn spawn_camera(commands: &mut Commands, asset_server: &AssetServer) { )) .insert(Skybox { brightness: 5000.0, - image: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"), + image: Some(asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2")), ..default() }) .insert(EnvironmentMapLight { diff --git a/examples/3d/contact_shadows.rs b/examples/3d/contact_shadows.rs index 330add440e31e..bb3dc82903b17 100644 --- a/examples/3d/contact_shadows.rs +++ b/examples/3d/contact_shadows.rs @@ -117,7 +117,7 @@ fn setup(mut commands: Commands, asset_server: Res) { Hdr, Skybox { brightness: 1000.0, - image: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"), + image: Some(asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2")), ..default() }, EnvironmentMapLight { diff --git a/examples/3d/irradiance_volumes.rs b/examples/3d/irradiance_volumes.rs index 43c150f271309..ac1c837ddc237 100644 --- a/examples/3d/irradiance_volumes.rs +++ b/examples/3d/irradiance_volumes.rs @@ -236,7 +236,7 @@ fn spawn_camera(commands: &mut Commands, assets: &ExampleAssets) { Camera3d::default(), Transform::from_xyz(-10.012, 4.8605, 13.281).looking_at(Vec3::ZERO, Vec3::Y), Skybox { - image: assets.skybox.clone(), + image: Some(assets.skybox.clone()), brightness: 150.0, ..default() }, diff --git a/examples/3d/pcss.rs b/examples/3d/pcss.rs index 4a41f25c76e44..92ac0905f5535 100644 --- a/examples/3d/pcss.rs +++ b/examples/3d/pcss.rs @@ -177,7 +177,7 @@ fn spawn_camera(commands: &mut Commands, asset_server: &AssetServer) { .insert(MotionVectorPrepass) // Add a nice skybox. .insert(Skybox { - image: asset_server.load("environment_maps/sky_skybox.ktx2"), + image: Some(asset_server.load("environment_maps/sky_skybox.ktx2")), brightness: 500.0, rotation: Quat::IDENTITY, }); diff --git a/examples/3d/reflection_probes.rs b/examples/3d/reflection_probes.rs index 3f34e50fcfe1e..e216af22d5a17 100644 --- a/examples/3d/reflection_probes.rs +++ b/examples/3d/reflection_probes.rs @@ -197,7 +197,7 @@ fn add_environment_map_to_camera( .entity(camera_entity) .insert(create_camera_environment_map_light(&cubemaps)) .insert(Skybox { - image: cubemaps.specular_environment_map.clone(), + image: Some(cubemaps.specular_environment_map.clone()), brightness: ENV_MAP_INTENSITY, ..default() }); diff --git a/examples/3d/rotate_environment_map.rs b/examples/3d/rotate_environment_map.rs index 9bbf8092ae31a..fa024e2839031 100644 --- a/examples/3d/rotate_environment_map.rs +++ b/examples/3d/rotate_environment_map.rs @@ -107,7 +107,7 @@ fn spawn_camera(commands: &mut Commands, asset_server: &AssetServer) { )) .insert(Skybox { brightness: 5000.0, - image: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"), + image: Some(asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2")), ..default() }) .insert(EnvironmentMapLight { diff --git a/examples/3d/skybox.rs b/examples/3d/skybox.rs index ed2f8e6edbae4..94ac4b98e001c 100644 --- a/examples/3d/skybox.rs +++ b/examples/3d/skybox.rs @@ -79,7 +79,7 @@ fn setup(mut commands: Commands, asset_server: Res) { Transform::from_xyz(0.0, 0.0, 8.0).looking_at(Vec3::ZERO, Vec3::Y), FreeCamera::default(), Skybox { - image: skybox_handle.clone(), + image: Some(skybox_handle.clone()), brightness: 1000.0, ..default() }, @@ -168,7 +168,7 @@ fn asset_loaded( } for mut skybox in &mut skyboxes { - skybox.image = cubemap.image_handle.clone(); + skybox.image = Some(cubemap.image_handle.clone()); } cubemap.is_loaded = true; diff --git a/examples/3d/specular_tint.rs b/examples/3d/specular_tint.rs index 185dfbbbc2c43..81655cfebd570 100644 --- a/examples/3d/specular_tint.rs +++ b/examples/3d/specular_tint.rs @@ -85,7 +85,7 @@ fn setup( Hdr, Camera3d::default(), Skybox { - image: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"), + image: Some(asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2")), brightness: 3000.0, ..default() }, diff --git a/examples/3d/ssr.rs b/examples/3d/ssr.rs index 2ed5e8d9b5856..b068a26733e10 100644 --- a/examples/3d/ssr.rs +++ b/examples/3d/ssr.rs @@ -432,7 +432,7 @@ fn spawn_camera(commands: &mut Commands, asset_server: &AssetServer, app_setting ..default() }, Skybox { - image: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"), + image: Some(asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2")), brightness: 5000.0, ..default() }, diff --git a/examples/3d/volumetric_fog.rs b/examples/3d/volumetric_fog.rs index 0e6015f144d75..968e68658f80a 100644 --- a/examples/3d/volumetric_fog.rs +++ b/examples/3d/volumetric_fog.rs @@ -73,7 +73,7 @@ fn setup(mut commands: Commands, asset_server: Res, app_settings: R Bloom::default(), )) .insert(Skybox { - image: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"), + image: Some(asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2")), brightness: 1000.0, ..default() }) diff --git a/examples/testbed/3d.rs b/examples/testbed/3d.rs index 4677833972dde..9c77dafe651da 100644 --- a/examples/testbed/3d.rs +++ b/examples/testbed/3d.rs @@ -586,7 +586,7 @@ mod white_furnace_solid_color_light { ..OrthographicProjection::default_3d() }), Skybox { - image: white_cubemap_handle, + image: Some(white_cubemap_handle), // middle gray brightness: 500.0, ..default() @@ -701,7 +701,7 @@ mod white_furnace_environment_map_light { ..OrthographicProjection::default_3d() }), Skybox { - image: white_cubemap_handle, + image: Some(white_cubemap_handle), // middle gray brightness: 500.0, ..default()