From 54701a844e247cf1bd705c77cce177616ffb2229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Mockers?= Date: Thu, 6 Mar 2025 00:08:46 +0100 Subject: [PATCH] Revert "Replace Ambient Lights with Environment Map Lights (#17482)" (#18167) This reverts commit 0b5302d96a7ab6d2bff99c43232a1781a97d51c8. # Objective - Fixes #18158 - #17482 introduced rendering changes and was merged a bit too fast ## Solution - Revert #17482 so that it can be redone and rendering changes discussed before being merged. This will make it easier to compare changes with main in the known "valid" state This is not an issue with the work done in #17482 that is still interesting --- crates/bevy_pbr/src/lib.rs | 22 ++--- crates/bevy_pbr/src/light/ambient_light.rs | 5 -- crates/bevy_pbr/src/light/mod.rs | 59 +------------ .../src/light_probe/environment_map.rs | 85 +------------------ crates/bevy_pbr/src/render/light.rs | 26 ++++-- .../bevy_pbr/src/render/mesh_view_types.wgsl | 1 + crates/bevy_pbr/src/render/pbr_ambient.wgsl | 29 +++++++ crates/bevy_pbr/src/render/pbr_functions.wgsl | 15 ++++ examples/2d/custom_gltf_vertex_attribute.rs | 14 ++- examples/3d/auto_exposure.rs | 10 +-- examples/3d/fog.rs | 4 - examples/3d/fog_volumes.rs | 4 - examples/3d/irradiance_volumes.rs | 34 +++----- examples/3d/lighting.rs | 12 +-- examples/3d/lightmaps.rs | 4 - examples/3d/mixed_lighting.rs | 27 +++--- examples/3d/motion_blur.rs | 11 +-- examples/3d/skybox.rs | 22 +++-- examples/3d/specular_tint.rs | 10 +-- examples/3d/spherical_area_lights.rs | 9 +- examples/3d/spotlight.rs | 9 +- examples/3d/ssao.rs | 9 +- examples/3d/transmission.rs | 9 +- examples/3d/volumetric_fog.rs | 4 - examples/animation/animated_mesh.rs | 10 +-- examples/animation/animated_mesh_control.rs | 10 +-- examples/animation/animated_mesh_events.rs | 10 +-- examples/animation/animated_transform.rs | 10 +-- examples/animation/animation_graph.rs | 10 +-- examples/animation/animation_masks.rs | 12 +-- examples/animation/custom_skinned_mesh.rs | 9 +- examples/animation/gltf_skinned_mesh.rs | 14 ++- examples/animation/morph_targets.rs | 14 ++- examples/asset/multi_asset_sync.rs | 10 +-- examples/math/render_primitives.rs | 17 ++-- 35 files changed, 212 insertions(+), 348 deletions(-) create mode 100644 crates/bevy_pbr/src/render/pbr_ambient.wgsl diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index 75f0458147..543a4665fc 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -71,16 +71,10 @@ pub use volumetric_fog::{FogVolume, VolumetricFog, VolumetricFogPlugin, Volumetr /// /// This includes the most common types in this crate, re-exported for your convenience. pub mod prelude { - #[expect( - deprecated, - reason = "AmbientLight has been replaced by EnvironmentMapLight" - )] - #[doc(hidden)] - pub use crate::light::AmbientLight; #[doc(hidden)] pub use crate::{ fog::{DistanceFog, FogFalloff}, - light::{light_consts, DirectionalLight, PointLight, SpotLight}, + light::{light_consts, AmbientLight, DirectionalLight, PointLight, SpotLight}, light_probe::{environment_map::EnvironmentMapLight, LightProbe}, material::{Material, MaterialPlugin}, mesh_material::MeshMaterial3d, @@ -171,6 +165,7 @@ pub const PBR_PREPASS_SHADER_HANDLE: Handle = weak_handle!("9afeaeab-7c45-43ce-b322-4b97799eaeb9"); pub const PBR_FUNCTIONS_HANDLE: Handle = weak_handle!("815b8618-f557-4a96-91a5-a2fb7e249fb0"); +pub const PBR_AMBIENT_HANDLE: Handle = weak_handle!("4a90b95b-112a-4a10-9145-7590d6f14260"); pub const PARALLAX_MAPPING_SHADER_HANDLE: Handle = weak_handle!("6cf57d9f-222a-429a-bba4-55ba9586e1d4"); pub const VIEW_TRANSFORMATIONS_SHADER_HANDLE: Handle = @@ -285,6 +280,12 @@ impl Plugin for PbrPlugin { "render/rgb9e5.wgsl", Shader::from_wgsl ); + load_internal_asset!( + app, + PBR_AMBIENT_HANDLE, + "render/pbr_ambient.wgsl", + Shader::from_wgsl + ); load_internal_asset!( app, PBR_FRAGMENT_HANDLE, @@ -324,10 +325,6 @@ impl Plugin for PbrPlugin { Shader::from_wgsl ); - #[expect( - deprecated, - reason = "AmbientLight has been replaced by EnvironmentMapLight" - )] app.register_asset_reflect::() .register_type::() .register_type::() @@ -404,9 +401,6 @@ impl Plugin for PbrPlugin { .add_systems( PostUpdate, ( - map_ambient_lights - .in_set(SimulationLightSystems::MapAmbientLights) - .after(CameraUpdateSystem), add_clusters .in_set(SimulationLightSystems::AddClusters) .after(CameraUpdateSystem), diff --git a/crates/bevy_pbr/src/light/ambient_light.rs b/crates/bevy_pbr/src/light/ambient_light.rs index 14ab9a8b1f..f09bab51f6 100644 --- a/crates/bevy_pbr/src/light/ambient_light.rs +++ b/crates/bevy_pbr/src/light/ambient_light.rs @@ -1,8 +1,3 @@ -#![deprecated( - since = "0.16.0", - note = "Use `EnvironmentMapLight::solid_color` instead" -)] - use super::*; /// An ambient light, which lights the entire scene equally. diff --git a/crates/bevy_pbr/src/light/mod.rs b/crates/bevy_pbr/src/light/mod.rs index 68d01ea656..1c9dc61374 100644 --- a/crates/bevy_pbr/src/light/mod.rs +++ b/crates/bevy_pbr/src/light/mod.rs @@ -20,13 +20,9 @@ use bevy_render::{ use bevy_transform::components::{GlobalTransform, Transform}; use bevy_utils::Parallel; -use crate::{prelude::EnvironmentMapLight, *}; +use crate::*; mod ambient_light; -#[expect( - deprecated, - reason = "AmbientLight has been replaced by EnvironmentMapLight" -)] pub use ambient_light::AmbientLight; mod point_light; @@ -513,7 +509,6 @@ pub struct LightVisibilityClass; /// System sets used to run light-related systems. #[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)] pub enum SimulationLightSystems { - MapAmbientLights, AddClusters, AssignLightsToClusters, /// System order ambiguities between systems in this set are ignored: @@ -527,58 +522,6 @@ pub enum SimulationLightSystems { CheckLightVisibility, } -#[derive(Component)] -pub struct EnvironmentMapLightFromAmbientLight; - -#[expect( - deprecated, - reason = "AmbientLight has been replaced by EnvironmentMapLight" -)] -pub fn map_ambient_lights( - mut commands: Commands, - mut image_assets: ResMut>, - ambient_light: Res, - new_views: Query< - (Entity, Option>), - ( - With, - Without, - Without, - ), - >, - mut managed_views: Query< - (&mut EnvironmentMapLight, Option>), - With, - >, -) { - let ambient_light = ambient_light.into(); - for (entity, ambient_override) in new_views.iter() { - let ambient = ambient_override.as_ref().unwrap_or(&ambient_light); - let ambient_required = ambient.brightness > 0.0 && ambient.color != Color::BLACK; - if ambient_required && ambient.is_changed() { - commands - .entity(entity) - .insert(EnvironmentMapLight { - intensity: ambient.brightness, - affects_lightmapped_mesh_diffuse: ambient.affects_lightmapped_meshes, - ..EnvironmentMapLight::solid_color(image_assets.as_mut(), ambient.color) - }) - .insert(EnvironmentMapLightFromAmbientLight); - } - } - for (mut env_map, ambient_override) in managed_views.iter_mut() { - let ambient = ambient_override.as_ref().unwrap_or(&ambient_light); - let ambient_required = ambient.brightness > 0.0 && ambient.color != Color::BLACK; - if ambient_required && ambient.is_changed() { - *env_map = EnvironmentMapLight { - intensity: ambient.brightness, - affects_lightmapped_mesh_diffuse: ambient.affects_lightmapped_meshes, - ..EnvironmentMapLight::solid_color(image_assets.as_mut(), ambient.color) - }; - } - } -} - pub fn update_directional_light_frusta( mut views: Query< ( diff --git a/crates/bevy_pbr/src/light_probe/environment_map.rs b/crates/bevy_pbr/src/light_probe/environment_map.rs index fcc1b64a97..8069f2acac 100644 --- a/crates/bevy_pbr/src/light_probe/environment_map.rs +++ b/crates/bevy_pbr/src/light_probe/environment_map.rs @@ -44,8 +44,7 @@ //! //! [several pre-filtered environment maps]: https://github.com/KhronosGroup/glTF-Sample-Environments -use bevy_asset::{weak_handle, AssetId, Assets, Handle, RenderAssetUsages}; -use bevy_color::{Color, ColorToPacked, Srgba}; +use bevy_asset::{weak_handle, AssetId, Handle}; use bevy_ecs::{ component::Component, query::QueryItem, reflect::ReflectComponent, system::lifetimeless::Read, }; @@ -57,9 +56,8 @@ use bevy_render::{ render_asset::RenderAssets, render_resource::{ binding_types::{self, uniform_buffer}, - BindGroupLayoutEntryBuilder, Extent3d, Sampler, SamplerBindingType, Shader, ShaderStages, - TextureDimension, TextureFormat, TextureSampleType, TextureView, TextureViewDescriptor, - TextureViewDimension, + BindGroupLayoutEntryBuilder, Sampler, SamplerBindingType, Shader, ShaderStages, + TextureSampleType, TextureView, }, renderer::{RenderAdapter, RenderDevice}, texture::{FallbackImage, GpuImage}, @@ -116,83 +114,6 @@ pub struct EnvironmentMapLight { pub affects_lightmapped_mesh_diffuse: bool, } -impl EnvironmentMapLight { - /// An environment map with a uniform color, useful for uniform ambient lighting. - pub fn solid_color(assets: &mut Assets, color: Color) -> Self { - let color: Srgba = color.into(); - let image = Image { - texture_view_descriptor: Some(TextureViewDescriptor { - dimension: Some(TextureViewDimension::Cube), - ..Default::default() - }), - ..Image::new_fill( - Extent3d { - width: 1, - height: 1, - depth_or_array_layers: 6, - }, - TextureDimension::D2, - &color.to_u8_array(), - TextureFormat::Rgba8UnormSrgb, - RenderAssetUsages::RENDER_WORLD, - ) - }; - let handle = assets.add(image); - - Self { - diffuse_map: handle.clone(), - specular_map: handle, - ..Default::default() - } - } - - /// An environment map with a hemispherical gradient, fading between the sky and ground colors - /// at the horizon. Useful as a very simple 'sky'. - pub fn hemispherical_gradient( - assets: &mut Assets, - top_color: Color, - bottom_color: Color, - ) -> Self { - let top_color: Srgba = top_color.into(); - let bottom_color: Srgba = bottom_color.into(); - let mid_color = (top_color + bottom_color) / 2.0; - let image = Image { - texture_view_descriptor: Some(TextureViewDescriptor { - dimension: Some(TextureViewDimension::Cube), - ..Default::default() - }), - ..Image::new( - Extent3d { - width: 1, - height: 1, - depth_or_array_layers: 6, - }, - TextureDimension::D2, - [ - mid_color, - mid_color, - top_color, - bottom_color, - mid_color, - mid_color, - ] - .into_iter() - .flat_map(Srgba::to_u8_array) - .collect(), - TextureFormat::Rgba8UnormSrgb, - RenderAssetUsages::RENDER_WORLD, - ) - }; - let handle = assets.add(image); - - Self { - diffuse_map: handle.clone(), - specular_map: handle, - ..Default::default() - } - } -} - impl Default for EnvironmentMapLight { fn default() -> Self { EnvironmentMapLight { diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index 9b43c33acf..c17b9d9355 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -139,6 +139,7 @@ bitflags::bitflags! { #[derive(Copy, Clone, Debug, ShaderType)] pub struct GpuLights { directional_lights: [GpuDirectionalLight; MAX_DIRECTIONAL_LIGHTS], + ambient_color: Vec4, // xyz are x/y/z cluster dimensions and w is the number of clusters cluster_dimensions: UVec4, // xy are vec2(cluster_dimensions.xy) / vec2(view.width, view.height) @@ -148,6 +149,7 @@ pub struct GpuLights { n_directional_lights: u32, // offset from spot light's light index to spot light's shadow map index spot_light_shadowmap_offset: i32, + ambient_light_affects_lightmapped_meshes: u32, } // NOTE: When running bevy on Adreno GPU chipsets in WebGL, any value above 1 will result in a crash @@ -727,9 +729,11 @@ pub fn prepare_lights( &ExtractedClusterConfig, Option<&RenderLayers>, Has, + Option<&AmbientLight>, ), With, >, + ambient_light: Res, point_light_shadow_map: Res, directional_light_shadow_map: Res, mut shadow_render_phases: ResMut>, @@ -1138,11 +1142,18 @@ pub fn prepare_lights( let mut live_views = EntityHashSet::with_capacity(views_count); // set up light data for each view - for (entity, camera_main_entity, extracted_view, clusters, maybe_layers, no_indirect_drawing) in - sorted_cameras - .0 - .iter() - .filter_map(|sorted_camera| views.get(sorted_camera.entity).ok()) + for ( + entity, + camera_main_entity, + extracted_view, + clusters, + maybe_layers, + no_indirect_drawing, + maybe_ambient_override, + ) in sorted_cameras + .0 + .iter() + .filter_map(|sorted_camera| views.get(sorted_camera.entity).ok()) { live_views.insert(entity); @@ -1164,8 +1175,11 @@ pub fn prepare_lights( ); let n_clusters = clusters.dimensions.x * clusters.dimensions.y * clusters.dimensions.z; + let ambient_light = maybe_ambient_override.unwrap_or(&ambient_light); let mut gpu_lights = GpuLights { directional_lights: gpu_directional_lights, + ambient_color: Vec4::from_slice(&LinearRgba::from(ambient_light.color).to_f32_array()) + * ambient_light.brightness, cluster_factors: Vec4::new( clusters.dimensions.x as f32 / extracted_view.viewport.z as f32, clusters.dimensions.y as f32 / extracted_view.viewport.w as f32, @@ -1180,6 +1194,8 @@ pub fn prepare_lights( // index to shadow map index, we need to subtract point light count and add directional shadowmap count. spot_light_shadowmap_offset: num_directional_cascades_enabled as i32 - point_light_count as i32, + ambient_light_affects_lightmapped_meshes: ambient_light.affects_lightmapped_meshes + as u32, }; // TODO: this should select lights based on relevance to the view instead of the first ones that show up in a query diff --git a/crates/bevy_pbr/src/render/mesh_view_types.wgsl b/crates/bevy_pbr/src/render/mesh_view_types.wgsl index cd46708e74..6db72759df 100644 --- a/crates/bevy_pbr/src/render/mesh_view_types.wgsl +++ b/crates/bevy_pbr/src/render/mesh_view_types.wgsl @@ -50,6 +50,7 @@ const DIRECTIONAL_LIGHT_FLAGS_AFFECTS_LIGHTMAPPED_MESH_DIFFUSE_BIT: u32 = 4u; struct Lights { // NOTE: this array size must be kept in sync with the constants defined in bevy_pbr/src/render/light.rs directional_lights: array, + ambient_color: vec4, // x/y/z dimensions and n_clusters in w cluster_dimensions: vec4, // xy are vec2(cluster_dimensions.xy) / vec2(view.width, view.height) diff --git a/crates/bevy_pbr/src/render/pbr_ambient.wgsl b/crates/bevy_pbr/src/render/pbr_ambient.wgsl new file mode 100644 index 0000000000..7b174da35c --- /dev/null +++ b/crates/bevy_pbr/src/render/pbr_ambient.wgsl @@ -0,0 +1,29 @@ +#define_import_path bevy_pbr::ambient + +#import bevy_pbr::{ + lighting::{EnvBRDFApprox, F_AB}, + mesh_view_bindings::lights, +} + +// A precomputed `NdotV` is provided because it is computed regardless, +// but `world_normal` and the view vector `V` are provided separately for more advanced uses. +fn ambient_light( + world_position: vec4, + world_normal: vec3, + V: vec3, + NdotV: f32, + diffuse_color: vec3, + specular_color: vec3, + perceptual_roughness: f32, + occlusion: vec3, +) -> vec3 { + let diffuse_ambient = EnvBRDFApprox(diffuse_color, F_AB(1.0, NdotV)); + let specular_ambient = EnvBRDFApprox(specular_color, F_AB(perceptual_roughness, NdotV)); + + // No real world material has specular values under 0.02, so we use this range as a + // "pre-baked specular occlusion" that extinguishes the fresnel term, for artistic control. + // See: https://google.github.io/filament/Filament.html#specularocclusion + let specular_occlusion = saturate(dot(specular_color, vec3(50.0 * 0.33))); + + return (diffuse_ambient + specular_ambient * specular_occlusion) * lights.ambient_color.rgb * occlusion; +} diff --git a/crates/bevy_pbr/src/render/pbr_functions.wgsl b/crates/bevy_pbr/src/render/pbr_functions.wgsl index 72d8ed35dc..e9b4e1f1a8 100644 --- a/crates/bevy_pbr/src/render/pbr_functions.wgsl +++ b/crates/bevy_pbr/src/render/pbr_functions.wgsl @@ -561,6 +561,18 @@ fn apply_pbr_lighting( #endif } +#ifdef STANDARD_MATERIAL_DIFFUSE_TRANSMISSION + // NOTE: We use the diffuse transmissive color, the second Lambertian lobe's calculated + // world position, inverted normal and view vectors, and the following simplified + // values for a fully diffuse transmitted light contribution approximation: + // + // perceptual_roughness = 1.0; + // NdotV = 1.0; + // F0 = vec3(0.0) + // diffuse_occlusion = vec3(1.0) + transmitted_light += ambient::ambient_light(diffuse_transmissive_lobe_world_position, -in.N, -in.V, 1.0, diffuse_transmissive_color, vec3(0.0), 1.0, vec3(1.0)); +#endif + // Diffuse indirect lighting can come from a variety of sources. The // priority goes like this: // @@ -632,6 +644,9 @@ fn apply_pbr_lighting( #endif // ENVIRONMENT_MAP + // Ambient light (indirect) + indirect_light += ambient::ambient_light(in.world_position, in.N, in.V, NdotV, diffuse_color, F0, perceptual_roughness, diffuse_occlusion); + // we'll use the specular component of the transmitted environment // light in the call to `specular_transmissive_light()` below var specular_transmitted_environment_light = vec3(0.0); diff --git a/examples/2d/custom_gltf_vertex_attribute.rs b/examples/2d/custom_gltf_vertex_attribute.rs index 903898ce7f..0742e3616f 100644 --- a/examples/2d/custom_gltf_vertex_attribute.rs +++ b/examples/2d/custom_gltf_vertex_attribute.rs @@ -24,6 +24,11 @@ const ATTRIBUTE_BARYCENTRIC: MeshVertexAttribute = fn main() { App::new() + .insert_resource(AmbientLight { + color: Color::WHITE, + brightness: 1.0 / 5.0f32, + ..default() + }) .add_plugins(( DefaultPlugins.set( GltfPlugin::default() @@ -43,7 +48,6 @@ fn setup( mut commands: Commands, asset_server: Res, mut materials: ResMut>, - mut images: ResMut>, ) { // Add a mesh loaded from a glTF file. This mesh has data for `ATTRIBUTE_BARYCENTRIC`. let mesh = asset_server.load( @@ -59,13 +63,7 @@ fn setup( Transform::from_scale(150.0 * Vec3::ONE), )); - commands.spawn(( - Camera2d, - EnvironmentMapLight { - intensity: 1.0 / 5.0, - ..EnvironmentMapLight::solid_color(&mut images, Color::WHITE) - }, - )); + commands.spawn(Camera2d); } /// This custom material uses barycentric coordinates from diff --git a/examples/3d/auto_exposure.rs b/examples/3d/auto_exposure.rs index 027d06fa4f..79fece61c8 100644 --- a/examples/3d/auto_exposure.rs +++ b/examples/3d/auto_exposure.rs @@ -101,11 +101,11 @@ fn setup( } } - #[expect( - deprecated, - reason = "Once AmbientLight is removed, the resource can be removed" - )] - commands.insert_resource(AmbientLight::NONE); + commands.insert_resource(AmbientLight { + color: Color::WHITE, + brightness: 0.0, + ..default() + }); commands.spawn(( PointLight { diff --git a/examples/3d/fog.rs b/examples/3d/fog.rs index 0f713b5cdd..9793ae0ad3 100644 --- a/examples/3d/fog.rs +++ b/examples/3d/fog.rs @@ -21,10 +21,6 @@ use bevy::{ }; fn main() { - #[expect( - deprecated, - reason = "Once AmbientLight is removed, the resource can be removed" - )] App::new() .insert_resource(AmbientLight::NONE) .add_plugins(DefaultPlugins) diff --git a/examples/3d/fog_volumes.rs b/examples/3d/fog_volumes.rs index 189a397894..68fc6d0ea7 100644 --- a/examples/3d/fog_volumes.rs +++ b/examples/3d/fog_volumes.rs @@ -13,10 +13,6 @@ use bevy::{ /// Entry point. fn main() { - #[expect( - deprecated, - reason = "Once AmbientLight is removed, the resource can be removed" - )] App::new() .add_plugins(DefaultPlugins.set(WindowPlugin { primary_window: Some(Window { diff --git a/examples/3d/irradiance_volumes.rs b/examples/3d/irradiance_volumes.rs index dffe5fb9bf..31529c4219 100644 --- a/examples/3d/irradiance_volumes.rs +++ b/examples/3d/irradiance_volumes.rs @@ -157,6 +157,11 @@ fn main() { .add_plugins(MaterialPlugin::::default()) .init_resource::() .init_resource::() + .insert_resource(AmbientLight { + color: Color::WHITE, + brightness: 0.0, + ..default() + }) .add_systems(Startup, setup) .add_systems(PreUpdate, create_cubes) .add_systems(Update, rotate_camera) @@ -211,14 +216,9 @@ fn main() { } // Spawns all the scene objects. -fn setup( - mut commands: Commands, - images: ResMut>, - assets: Res, - app_status: Res, -) { +fn setup(mut commands: Commands, assets: Res, app_status: Res) { spawn_main_scene(&mut commands, &assets); - spawn_camera(&mut commands, images, &assets); + spawn_camera(&mut commands, &assets); spawn_irradiance_volume(&mut commands, &assets); spawn_light(&mut commands); spawn_sphere(&mut commands, &assets); @@ -231,11 +231,7 @@ fn spawn_main_scene(commands: &mut Commands, assets: &ExampleAssets) { commands.spawn(SceneRoot(assets.main_scene.clone())); } -fn spawn_camera( - commands: &mut Commands, - mut images: ResMut>, - assets: &ExampleAssets, -) { +fn spawn_camera(commands: &mut Commands, assets: &ExampleAssets) { commands.spawn(( Camera3d::default(), Transform::from_xyz(-10.012, 4.8605, 13.281).looking_at(Vec3::ZERO, Vec3::Y), @@ -244,10 +240,6 @@ fn spawn_camera( brightness: 150.0, ..default() }, - EnvironmentMapLight { - intensity: 0.0, - ..EnvironmentMapLight::solid_color(&mut images, Color::WHITE) - }, )); } @@ -423,7 +415,7 @@ fn toggle_irradiance_volumes( light_probe_query: Query>, mut app_status: ResMut, assets: Res, - mut ambient_light: Query<&mut EnvironmentMapLight>, + mut ambient_light: ResMut, ) { if !keyboard.just_pressed(KeyCode::Space) { return; @@ -435,9 +427,7 @@ fn toggle_irradiance_volumes( if app_status.irradiance_volume_present { commands.entity(light_probe).remove::(); - for mut light in ambient_light.iter_mut() { - light.intensity = AMBIENT_LIGHT_BRIGHTNESS * IRRADIANCE_VOLUME_INTENSITY; - } + ambient_light.brightness = AMBIENT_LIGHT_BRIGHTNESS * IRRADIANCE_VOLUME_INTENSITY; app_status.irradiance_volume_present = false; } else { commands.entity(light_probe).insert(IrradianceVolume { @@ -445,9 +435,7 @@ fn toggle_irradiance_volumes( intensity: IRRADIANCE_VOLUME_INTENSITY, ..default() }); - for mut light in ambient_light.iter_mut() { - light.intensity = 0.0; - } + ambient_light.brightness = 0.0; app_status.irradiance_volume_present = true; } } diff --git a/examples/3d/lighting.rs b/examples/3d/lighting.rs index 226a8f90b7..b8d7883763 100644 --- a/examples/3d/lighting.rs +++ b/examples/3d/lighting.rs @@ -35,7 +35,6 @@ fn setup( parameters: Res, mut commands: Commands, mut meshes: ResMut>, - mut images: ResMut>, mut materials: ResMut>, asset_server: Res, ) { @@ -111,6 +110,13 @@ fn setup( Movable, )); + // ambient light + commands.insert_resource(AmbientLight { + color: ORANGE_RED.into(), + brightness: 0.02, + ..default() + }); + // red point light commands.spawn(( PointLight { @@ -230,10 +236,6 @@ fn setup( Camera3d::default(), Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y), Exposure::from_physical_camera(**parameters), - EnvironmentMapLight { - intensity: 0.02, - ..EnvironmentMapLight::solid_color(&mut images, ORANGE_RED.into()) - }, )); } diff --git a/examples/3d/lightmaps.rs b/examples/3d/lightmaps.rs index 824b548687..975b37d7f2 100644 --- a/examples/3d/lightmaps.rs +++ b/examples/3d/lightmaps.rs @@ -25,10 +25,6 @@ fn main() { let args: Args = Args::from_args(&[], &[]).unwrap(); let mut app = App::new(); - #[expect( - deprecated, - reason = "Once AmbientLight is removed, the resource can be removed" - )] app.add_plugins(DefaultPlugins) .insert_resource(AmbientLight::NONE); diff --git a/examples/3d/mixed_lighting.rs b/examples/3d/mixed_lighting.rs index 49a1c2f097..f7ebbd5cfc 100644 --- a/examples/3d/mixed_lighting.rs +++ b/examples/3d/mixed_lighting.rs @@ -123,6 +123,11 @@ fn main() { ..default() })) .add_plugins(MeshPickingPlugin) + .insert_resource(AmbientLight { + color: ClearColor::default().0, + brightness: 10000.0, + affects_lightmapped_meshes: true, + }) .init_resource::() .add_event::>() .add_event::() @@ -140,28 +145,18 @@ fn main() { } /// Creates the scene. -fn setup( - mut commands: Commands, - images: ResMut>, - asset_server: Res, - app_status: Res, -) { - spawn_camera(&mut commands, images); +fn setup(mut commands: Commands, asset_server: Res, app_status: Res) { + spawn_camera(&mut commands); spawn_scene(&mut commands, &asset_server); spawn_buttons(&mut commands); spawn_help_text(&mut commands, &app_status); } /// Spawns the 3D camera. -fn spawn_camera(commands: &mut Commands, mut images: ResMut>) { - commands.spawn(( - Camera3d::default(), - Transform::from_xyz(-0.7, 0.7, 1.0).looking_at(vec3(0.0, 0.3, 0.0), Vec3::Y), - EnvironmentMapLight { - intensity: 10000.0, - ..EnvironmentMapLight::solid_color(&mut images, ClearColor::default().0) - }, - )); +fn spawn_camera(commands: &mut Commands) { + commands + .spawn(Camera3d::default()) + .insert(Transform::from_xyz(-0.7, 0.7, 1.0).looking_at(vec3(0.0, 0.3, 0.0), Vec3::Y)); } /// Spawns the scene. diff --git a/examples/3d/motion_blur.rs b/examples/3d/motion_blur.rs index 3d3cbab2c9..68bb556c6b 100644 --- a/examples/3d/motion_blur.rs +++ b/examples/3d/motion_blur.rs @@ -17,7 +17,7 @@ fn main() { .run(); } -fn setup_camera(mut commands: Commands, mut images: ResMut>) { +fn setup_camera(mut commands: Commands) { commands.spawn(( Camera3d::default(), // Add the `MotionBlur` component to a camera to enable motion blur. @@ -32,10 +32,6 @@ fn setup_camera(mut commands: Commands, mut images: ResMut>) { // MSAA and Motion Blur together are not compatible on WebGL #[cfg(all(feature = "webgl2", target_arch = "wasm32", not(feature = "webgpu")))] Msaa::Off, - EnvironmentMapLight { - intensity: 300.0, - ..EnvironmentMapLight::solid_color(&mut images, Color::WHITE) - }, )); } @@ -63,6 +59,11 @@ fn setup_scene( mut meshes: ResMut>, mut materials: ResMut>, ) { + commands.insert_resource(AmbientLight { + color: Color::WHITE, + brightness: 300.0, + ..default() + }); commands.insert_resource(CameraMode::Chase); commands.spawn(( DirectionalLight { diff --git a/examples/3d/skybox.rs b/examples/3d/skybox.rs index 9c009eb8d2..dd797473bf 100644 --- a/examples/3d/skybox.rs +++ b/examples/3d/skybox.rs @@ -57,11 +57,7 @@ struct Cubemap { image_handle: Handle, } -fn setup( - mut commands: Commands, - asset_server: Res, - mut images: ResMut>, -) { +fn setup(mut commands: Commands, asset_server: Res) { // directional 'sun' light commands.spawn(( DirectionalLight { @@ -82,15 +78,17 @@ fn setup( brightness: 1000.0, ..default() }, - // This should ideally be using a convolved environment map for diffuse, but for simplicity - // we're just using a solid color here. - EnvironmentMapLight { - intensity: 1.0, - specular_map: skybox_handle.clone(), - ..EnvironmentMapLight::solid_color(&mut images, Color::srgb_u8(210, 220, 240)) - }, )); + // ambient light + // NOTE: The ambient light is used to scale how bright the environment map is so with a bright + // environment map, use an appropriate color and brightness to match + commands.insert_resource(AmbientLight { + color: Color::srgb_u8(210, 220, 240), + brightness: 1.0, + ..default() + }); + commands.insert_resource(Cubemap { is_loaded: false, index: 0, diff --git a/examples/3d/specular_tint.rs b/examples/3d/specular_tint.rs index 6954a02049..5dc362b9c1 100644 --- a/examples/3d/specular_tint.rs +++ b/examples/3d/specular_tint.rs @@ -49,10 +49,6 @@ enum TintType { /// The entry point. fn main() { - #[expect( - deprecated, - reason = "Once AmbientLight is removed, the resource can be removed" - )] App::new() .add_plugins(DefaultPlugins.set(WindowPlugin { primary_window: Some(Window { @@ -63,7 +59,11 @@ fn main() { })) .init_resource::() .init_resource::() - .insert_resource(AmbientLight::NONE) + .insert_resource(AmbientLight { + color: Color::BLACK, + brightness: 0.0, + ..default() + }) .add_systems(Startup, setup) .add_systems(Update, rotate_camera) .add_systems(Update, (toggle_specular_map, update_text).chain()) diff --git a/examples/3d/spherical_area_lights.rs b/examples/3d/spherical_area_lights.rs index 9c7c1486e8..c3e945a8f3 100644 --- a/examples/3d/spherical_area_lights.rs +++ b/examples/3d/spherical_area_lights.rs @@ -4,6 +4,10 @@ use bevy::prelude::*; fn main() { App::new() + .insert_resource(AmbientLight { + brightness: 60.0, + ..default() + }) .add_plugins(DefaultPlugins) .add_systems(Startup, setup) .run(); @@ -12,17 +16,12 @@ fn main() { fn setup( mut commands: Commands, mut meshes: ResMut>, - mut images: ResMut>, mut materials: ResMut>, ) { // camera commands.spawn(( Camera3d::default(), Transform::from_xyz(0.2, 1.5, 2.5).looking_at(Vec3::ZERO, Vec3::Y), - EnvironmentMapLight { - intensity: 60.0, - ..EnvironmentMapLight::solid_color(&mut images, Color::WHITE) - }, )); // plane diff --git a/examples/3d/spotlight.rs b/examples/3d/spotlight.rs index b713745821..c92843404e 100644 --- a/examples/3d/spotlight.rs +++ b/examples/3d/spotlight.rs @@ -20,6 +20,10 @@ Rotate Camera: Left and Right Arrows"; fn main() { App::new() + .insert_resource(AmbientLight { + brightness: 20.0, + ..default() + }) .add_plugins(DefaultPlugins) .add_systems(Startup, setup) .add_systems(Update, (light_sway, movement, rotation)) @@ -33,7 +37,6 @@ struct Movable; fn setup( mut commands: Commands, mut meshes: ResMut>, - mut images: ResMut>, mut materials: ResMut>, ) { // ground plane @@ -121,10 +124,6 @@ fn setup( ..default() }, Transform::from_xyz(-4.0, 5.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y), - EnvironmentMapLight { - intensity: 20.0, - ..EnvironmentMapLight::solid_color(&mut images, Color::WHITE) - }, )); commands.spawn(( diff --git a/examples/3d/ssao.rs b/examples/3d/ssao.rs index 5e3031afb3..17c54db633 100644 --- a/examples/3d/ssao.rs +++ b/examples/3d/ssao.rs @@ -11,6 +11,10 @@ use std::f32::consts::PI; fn main() { App::new() + .insert_resource(AmbientLight { + brightness: 1000., + ..default() + }) .add_plugins((DefaultPlugins, TemporalAntiAliasPlugin)) .add_systems(Startup, setup) .add_systems(Update, update) @@ -20,7 +24,6 @@ fn main() { fn setup( mut commands: Commands, mut meshes: ResMut>, - mut images: ResMut>, mut materials: ResMut>, ) { commands.spawn(( @@ -33,10 +36,6 @@ fn setup( Msaa::Off, ScreenSpaceAmbientOcclusion::default(), TemporalAntiAliasing::default(), - EnvironmentMapLight { - intensity: 1000.0, - ..EnvironmentMapLight::solid_color(&mut images, Color::WHITE) - }, )); let material = materials.add(StandardMaterial { diff --git a/examples/3d/transmission.rs b/examples/3d/transmission.rs index a0f126fc3c..97f1014c22 100644 --- a/examples/3d/transmission.rs +++ b/examples/3d/transmission.rs @@ -42,14 +42,13 @@ use rand::random; fn main() { let mut app = App::new(); - #[expect( - deprecated, - reason = "Once AmbientLight is removed, the resource can be removed" - )] app.add_plugins(DefaultPlugins) .insert_resource(ClearColor(Color::BLACK)) .insert_resource(PointLightShadowMap { size: 2048 }) - .insert_resource(AmbientLight::NONE) + .insert_resource(AmbientLight { + brightness: 0.0, + ..default() + }) .add_systems(Startup, setup) .add_systems(Update, (example_control_system, flicker_system)); diff --git a/examples/3d/volumetric_fog.rs b/examples/3d/volumetric_fog.rs index 8130c8a3f7..9cfef624c6 100644 --- a/examples/3d/volumetric_fog.rs +++ b/examples/3d/volumetric_fog.rs @@ -37,10 +37,6 @@ struct MoveBackAndForthHorizontally { } fn main() { - #[expect( - deprecated, - reason = "Once AmbientLight is removed, the resource can be removed" - )] App::new() .add_plugins(DefaultPlugins) .insert_resource(ClearColor(Color::Srgba(Srgba { diff --git a/examples/animation/animated_mesh.rs b/examples/animation/animated_mesh.rs index 4ac6cb3fde..ecea86fb17 100644 --- a/examples/animation/animated_mesh.rs +++ b/examples/animation/animated_mesh.rs @@ -9,6 +9,11 @@ const GLTF_PATH: &str = "models/animated/Fox.glb"; fn main() { App::new() + .insert_resource(AmbientLight { + color: Color::WHITE, + brightness: 2000., + ..default() + }) .add_plugins(DefaultPlugins) .add_systems(Startup, setup_mesh_and_animation) .add_systems(Startup, setup_camera_and_environment) @@ -93,17 +98,12 @@ fn play_animation_when_ready( fn setup_camera_and_environment( mut commands: Commands, mut meshes: ResMut>, - mut images: ResMut>, mut materials: ResMut>, ) { // Camera commands.spawn(( Camera3d::default(), Transform::from_xyz(100.0, 100.0, 150.0).looking_at(Vec3::new(0.0, 20.0, 0.0), Vec3::Y), - EnvironmentMapLight { - intensity: 2000.0, - ..EnvironmentMapLight::solid_color(&mut images, Color::WHITE) - }, )); // Plane diff --git a/examples/animation/animated_mesh_control.rs b/examples/animation/animated_mesh_control.rs index 0bf23a42c5..0dafd0de11 100644 --- a/examples/animation/animated_mesh_control.rs +++ b/examples/animation/animated_mesh_control.rs @@ -8,6 +8,11 @@ const FOX_PATH: &str = "models/animated/Fox.glb"; fn main() { App::new() + .insert_resource(AmbientLight { + color: Color::WHITE, + brightness: 2000., + ..default() + }) .add_plugins(DefaultPlugins) .add_systems(Startup, setup) .add_systems(Update, setup_scene_once_loaded) @@ -25,7 +30,6 @@ fn setup( mut commands: Commands, asset_server: Res, mut meshes: ResMut>, - mut images: ResMut>, mut materials: ResMut>, mut graphs: ResMut>, ) { @@ -48,10 +52,6 @@ fn setup( commands.spawn(( Camera3d::default(), Transform::from_xyz(100.0, 100.0, 150.0).looking_at(Vec3::new(0.0, 20.0, 0.0), Vec3::Y), - EnvironmentMapLight { - intensity: 2000.0, - ..EnvironmentMapLight::solid_color(&mut images, Color::WHITE) - }, )); // Plane diff --git a/examples/animation/animated_mesh_events.rs b/examples/animation/animated_mesh_events.rs index 73b9852408..2048f573fd 100644 --- a/examples/animation/animated_mesh_events.rs +++ b/examples/animation/animated_mesh_events.rs @@ -13,6 +13,11 @@ const FOX_PATH: &str = "models/animated/Fox.glb"; fn main() { App::new() + .insert_resource(AmbientLight { + color: Color::WHITE, + brightness: 2000., + ..default() + }) .add_plugins(DefaultPlugins) .init_resource::() .init_resource::() @@ -73,7 +78,6 @@ fn setup( mut commands: Commands, asset_server: Res, mut meshes: ResMut>, - mut images: ResMut>, mut materials: ResMut>, mut graphs: ResMut>, ) { @@ -94,10 +98,6 @@ fn setup( commands.spawn(( Camera3d::default(), Transform::from_xyz(100.0, 100.0, 150.0).looking_at(Vec3::new(0.0, 20.0, 0.0), Vec3::Y), - EnvironmentMapLight { - intensity: 2000.0, - ..EnvironmentMapLight::solid_color(&mut images, Color::WHITE) - }, )); // Plane diff --git a/examples/animation/animated_transform.rs b/examples/animation/animated_transform.rs index 08e7528797..decb3d34a6 100644 --- a/examples/animation/animated_transform.rs +++ b/examples/animation/animated_transform.rs @@ -10,6 +10,11 @@ use bevy::{ fn main() { App::new() .add_plugins(DefaultPlugins) + .insert_resource(AmbientLight { + color: Color::WHITE, + brightness: 150.0, + ..default() + }) .add_systems(Startup, setup) .run(); } @@ -17,7 +22,6 @@ fn main() { fn setup( mut commands: Commands, mut meshes: ResMut>, - mut images: ResMut>, mut materials: ResMut>, mut animations: ResMut>, mut graphs: ResMut>, @@ -26,10 +30,6 @@ fn setup( commands.spawn(( Camera3d::default(), Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y), - EnvironmentMapLight { - intensity: 150.0, - ..EnvironmentMapLight::solid_color(&mut images, Color::WHITE) - }, )); // Light diff --git a/examples/animation/animation_graph.rs b/examples/animation/animation_graph.rs index d063f321d0..76da8a6644 100644 --- a/examples/animation/animation_graph.rs +++ b/examples/animation/animation_graph.rs @@ -88,6 +88,11 @@ fn main() { (handle_weight_drag, update_ui, sync_weights).chain(), ) .insert_resource(args) + .insert_resource(AmbientLight { + color: WHITE.into(), + brightness: 100.0, + ..default() + }) .run(); } @@ -211,16 +216,11 @@ fn setup_scene( mut commands: Commands, asset_server: Res, mut meshes: ResMut>, - mut images: ResMut>, mut materials: ResMut>, ) { commands.spawn(( Camera3d::default(), Transform::from_xyz(-10.0, 5.0, 13.0).looking_at(Vec3::new(0., 1., 0.), Vec3::Y), - EnvironmentMapLight { - intensity: 100.0, - ..EnvironmentMapLight::solid_color(&mut images, Color::WHITE) - }, )); commands.spawn(( diff --git a/examples/animation/animation_masks.rs b/examples/animation/animation_masks.rs index 131656e82e..72408260d6 100644 --- a/examples/animation/animation_masks.rs +++ b/examples/animation/animation_masks.rs @@ -2,7 +2,7 @@ use bevy::{ animation::{AnimationTarget, AnimationTargetId}, - color::palettes::css::LIGHT_GRAY, + color::palettes::css::{LIGHT_GRAY, WHITE}, prelude::*, }; use std::collections::HashSet; @@ -105,6 +105,11 @@ fn main() { .add_systems(Update, setup_animation_graph_once_loaded) .add_systems(Update, handle_button_toggles) .add_systems(Update, update_ui) + .insert_resource(AmbientLight { + color: WHITE.into(), + brightness: 100.0, + ..default() + }) .init_resource::() .run(); } @@ -115,17 +120,12 @@ fn setup_scene( mut commands: Commands, asset_server: Res, mut meshes: ResMut>, - mut images: ResMut>, mut materials: ResMut>, ) { // Spawn the camera. commands.spawn(( Camera3d::default(), Transform::from_xyz(-15.0, 10.0, 20.0).looking_at(Vec3::new(0., 1., 0.), Vec3::Y), - EnvironmentMapLight { - intensity: 100.0, - ..EnvironmentMapLight::solid_color(&mut images, Color::WHITE) - }, )); // Spawn the light. diff --git a/examples/animation/custom_skinned_mesh.rs b/examples/animation/custom_skinned_mesh.rs index d86e98295a..b091f2dd42 100644 --- a/examples/animation/custom_skinned_mesh.rs +++ b/examples/animation/custom_skinned_mesh.rs @@ -20,6 +20,10 @@ use rand_chacha::ChaCha8Rng; fn main() { App::new() .add_plugins(DefaultPlugins) + .insert_resource(AmbientLight { + brightness: 3000.0, + ..default() + }) .add_systems(Startup, setup) .add_systems(Update, joint_animation) .run(); @@ -36,7 +40,6 @@ fn setup( mut commands: Commands, asset_server: Res, mut meshes: ResMut>, - mut images: ResMut>, mut materials: ResMut>, mut skinned_mesh_inverse_bindposes_assets: ResMut>, ) { @@ -44,10 +47,6 @@ fn setup( commands.spawn(( Camera3d::default(), Transform::from_xyz(2.5, 2.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y), - EnvironmentMapLight { - intensity: 3000.0, - ..EnvironmentMapLight::solid_color(&mut images, Color::WHITE) - }, )); // Create inverse bindpose matrices for a skeleton consists of 2 joints diff --git a/examples/animation/gltf_skinned_mesh.rs b/examples/animation/gltf_skinned_mesh.rs index 5f414087fa..48f7cd6f39 100644 --- a/examples/animation/gltf_skinned_mesh.rs +++ b/examples/animation/gltf_skinned_mesh.rs @@ -8,24 +8,20 @@ use bevy::{math::ops, prelude::*, render::mesh::skinning::SkinnedMesh}; fn main() { App::new() .add_plugins(DefaultPlugins) + .insert_resource(AmbientLight { + brightness: 750.0, + ..default() + }) .add_systems(Startup, setup) .add_systems(Update, joint_animation) .run(); } -fn setup( - mut commands: Commands, - asset_server: Res, - mut images: ResMut>, -) { +fn setup(mut commands: Commands, asset_server: Res) { // Create a camera commands.spawn(( Camera3d::default(), Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::new(0.0, 1.0, 0.0), Vec3::Y), - EnvironmentMapLight { - intensity: 750.0, - ..EnvironmentMapLight::solid_color(&mut images, Color::WHITE) - }, )); // Spawn the first scene in `models/SimpleSkin/SimpleSkin.gltf` diff --git a/examples/animation/morph_targets.rs b/examples/animation/morph_targets.rs index 7c2c9a00ac..258059bf55 100644 --- a/examples/animation/morph_targets.rs +++ b/examples/animation/morph_targets.rs @@ -19,6 +19,10 @@ fn main() { }), ..default() })) + .insert_resource(AmbientLight { + brightness: 150.0, + ..default() + }) .add_systems(Startup, setup) .add_systems(Update, (name_morphs, setup_animations)) .run(); @@ -30,11 +34,7 @@ struct MorphData { mesh: Handle, } -fn setup( - asset_server: Res, - mut commands: Commands, - mut images: ResMut>, -) { +fn setup(asset_server: Res, mut commands: Commands) { commands.insert_resource(MorphData { the_wave: asset_server .load(GltfAssetLabel::Animation(2).from_asset("models/animated/MorphStressTest.gltf")), @@ -56,10 +56,6 @@ fn setup( commands.spawn(( Camera3d::default(), Transform::from_xyz(3.0, 2.1, 10.2).looking_at(Vec3::ZERO, Vec3::Y), - EnvironmentMapLight { - intensity: 150.0, - ..EnvironmentMapLight::solid_color(&mut images, Color::WHITE) - }, )); } diff --git a/examples/asset/multi_asset_sync.rs b/examples/asset/multi_asset_sync.rs index c4b4c92684..cc233eb5fd 100644 --- a/examples/asset/multi_asset_sync.rs +++ b/examples/asset/multi_asset_sync.rs @@ -17,6 +17,11 @@ fn main() { App::new() .add_plugins(DefaultPlugins) .init_state::() + .insert_resource(AmbientLight { + color: Color::WHITE, + brightness: 2000., + ..default() + }) .add_systems(Startup, setup_assets) .add_systems(Startup, setup_scene) .add_systems(Startup, setup_ui) @@ -180,17 +185,12 @@ fn setup_ui(mut commands: Commands) { fn setup_scene( mut commands: Commands, mut meshes: ResMut>, - mut images: ResMut>, mut materials: ResMut>, ) { // Camera commands.spawn(( Camera3d::default(), Transform::from_xyz(10.0, 10.0, 15.0).looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y), - EnvironmentMapLight { - intensity: 2000.0, - ..EnvironmentMapLight::solid_color(&mut images, Color::WHITE) - }, )); // Light diff --git a/examples/math/render_primitives.rs b/examples/math/render_primitives.rs index 26246faf79..56633977e6 100644 --- a/examples/math/render_primitives.rs +++ b/examples/math/render_primitives.rs @@ -14,7 +14,7 @@ fn main() { .init_state::(); // cameras - app.add_systems(Startup, (setup_cameras, setup_lights)) + app.add_systems(Startup, (setup_cameras, setup_lights, setup_ambient_light)) .add_systems( Update, ( @@ -292,21 +292,14 @@ const CIRCULAR_SEGMENT: CircularSegment = CircularSegment { }, }; -fn setup_cameras(mut commands: Commands, mut images: ResMut>) { +fn setup_cameras(mut commands: Commands) { let start_in_2d = true; let make_camera = |is_active| Camera { is_active, ..Default::default() }; - commands.spawn(( - Camera2d, - make_camera(start_in_2d), - EnvironmentMapLight { - intensity: 50.0, - ..EnvironmentMapLight::solid_color(&mut images, Color::WHITE) - }, - )); + commands.spawn((Camera2d, make_camera(start_in_2d))); commands.spawn(( Camera3d::default(), @@ -315,6 +308,10 @@ fn setup_cameras(mut commands: Commands, mut images: ResMut>) { )); } +fn setup_ambient_light(mut ambient_light: ResMut) { + ambient_light.brightness = 50.0; +} + fn setup_lights(mut commands: Commands) { commands.spawn(( PointLight {