diff --git a/crates/bevy_pbr/src/pbr_material.rs b/crates/bevy_pbr/src/pbr_material.rs index 05d01e3902..91cb1d21a2 100644 --- a/crates/bevy_pbr/src/pbr_material.rs +++ b/crates/bevy_pbr/src/pbr_material.rs @@ -90,6 +90,13 @@ pub struct StandardMaterial { /// it just adds a value to the color seen on screen. pub emissive: Color, + /// The weight in which the camera exposure influences the emissive color. + /// A value of `0.0` means the emissive color is not affected by the camera exposure. + /// In opposition, a value of `1.0` means the emissive color is multiplied by the camera exposure. + /// + /// Defaults to `0.0` + pub emissive_exposure_weight: f32, + /// The UV channel to use for the [`StandardMaterial::emissive_texture`]. /// /// Defaults to [`UvChannel::Uv0`]. @@ -683,6 +690,7 @@ impl Default for StandardMaterial { base_color_channel: UvChannel::Uv0, base_color_texture: None, emissive: Color::BLACK, + emissive_exposure_weight: 0.0, emissive_channel: UvChannel::Uv0, emissive_texture: None, // Matches Blender's default roughness. @@ -964,9 +972,12 @@ impl AsBindGroupShaderType for StandardMaterial { flags |= StandardMaterialFlags::ATTENUATION_ENABLED; } + let mut emissive = LinearRgba::from(self.emissive).to_f32_array(); + emissive[3] = self.emissive_exposure_weight; + StandardMaterialUniform { base_color: LinearRgba::from(self.base_color).to_f32_array().into(), - emissive: LinearRgba::from(self.emissive).to_f32_array().into(), + emissive: emissive.into(), roughness: self.perceptual_roughness, metallic: self.metallic, reflectance: self.reflectance, diff --git a/crates/bevy_pbr/src/render/pbr_fragment.wgsl b/crates/bevy_pbr/src/render/pbr_fragment.wgsl index b2bb252f87..52b299f4c9 100644 --- a/crates/bevy_pbr/src/render/pbr_fragment.wgsl +++ b/crates/bevy_pbr/src/render/pbr_fragment.wgsl @@ -178,7 +178,6 @@ fn pbr_input_from_standard_material( pbr_input.material.alpha_cutoff = pbr_bindings::material.alpha_cutoff; // emissive - // TODO use .a for exposure compensation in HDR var emissive: vec4 = pbr_bindings::material.emissive; #ifdef VERTEX_UVS if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_EMISSIVE_TEXTURE_BIT) != 0u) { @@ -191,7 +190,7 @@ fn pbr_input_from_standard_material( uv, #endif bias, - ).rgb, 1.0); + ).rgb, emissive.a); } #endif pbr_input.material.emissive = emissive; diff --git a/crates/bevy_pbr/src/render/pbr_functions.wgsl b/crates/bevy_pbr/src/render/pbr_functions.wgsl index f816c60436..f789b3f76a 100644 --- a/crates/bevy_pbr/src/render/pbr_functions.wgsl +++ b/crates/bevy_pbr/src/render/pbr_functions.wgsl @@ -224,7 +224,6 @@ fn apply_pbr_lighting( ) -> vec4 { var output_color: vec4 = in.material.base_color; - // TODO use .a for exposure compensation in HDR let emissive = in.material.emissive; // calculate non-linear roughness from linear perceptualRoughness @@ -564,6 +563,8 @@ fn apply_pbr_lighting( emissive_light = emissive_light * (0.04 + (1.0 - 0.04) * pow(1.0 - clearcoat_NdotV, 5.0)); #endif + emissive_light = emissive_light * mix(1.0, view_bindings::view.exposure, emissive.a); + #ifdef STANDARD_MATERIAL_SPECULAR_TRANSMISSION transmitted_light += transmission::specular_transmissive_light(in.world_position, in.frag_coord.xyz, view_z, in.N, in.V, F0, ior, thickness, perceptual_roughness, specular_transmissive_color, specular_transmitted_environment_light).rgb; @@ -585,7 +586,7 @@ fn apply_pbr_lighting( // Total light output_color = vec4( - view_bindings::view.exposure * (transmitted_light + direct_light + indirect_light + emissive_light), + (view_bindings::view.exposure * (transmitted_light + direct_light + indirect_light)) + emissive_light, output_color.a ); diff --git a/examples/3d/bloom_3d.rs b/examples/3d/bloom_3d.rs index b2fd467942..36d178491b 100644 --- a/examples/3d/bloom_3d.rs +++ b/examples/3d/bloom_3d.rs @@ -41,15 +41,15 @@ fn setup_scene( )); let material_emissive1 = materials.add(StandardMaterial { - emissive: Color::linear_rgb(23000.0, 9000.0, 3000.0), // 4. Put something bright in a dark environment to see the effect + emissive: Color::linear_rgb(13.99, 5.32, 2.0), // 4. Put something bright in a dark environment to see the effect ..default() }); let material_emissive2 = materials.add(StandardMaterial { - emissive: Color::linear_rgb(3000.0, 23000.0, 9000.0), + emissive: Color::linear_rgb(2.0, 13.99, 5.32), ..default() }); let material_emissive3 = materials.add(StandardMaterial { - emissive: Color::linear_rgb(9000.0, 3000.0, 23000.0), + emissive: Color::linear_rgb(5.32, 2.0, 13.99), ..default() }); let material_non_emissive = materials.add(StandardMaterial { diff --git a/examples/3d/lightmaps.rs b/examples/3d/lightmaps.rs index fe7f2a8c59..aeeb753f4d 100644 --- a/examples/3d/lightmaps.rs +++ b/examples/3d/lightmaps.rs @@ -35,11 +35,6 @@ fn add_lightmaps_to_meshes( ) { let exposure = 250.0; for (entity, name, material) in meshes.iter() { - if &**name == "Light" { - materials.get_mut(material).unwrap().emissive = Color::Srgba(Srgba::WHITE * exposure); - continue; - } - if &**name == "large_box" { materials.get_mut(material).unwrap().lightmap_exposure = exposure; commands.entity(entity).insert(Lightmap { diff --git a/examples/3d/spotlight.rs b/examples/3d/spotlight.rs index cee0a6de69..b05fc9ff2f 100644 --- a/examples/3d/spotlight.rs +++ b/examples/3d/spotlight.rs @@ -79,12 +79,12 @@ fn setup( let sphere_mesh_direction = meshes.add(Sphere::new(0.1).mesh().uv(32, 18)); let red_emissive = materials.add(StandardMaterial { base_color: RED.into(), - emissive: Color::linear_rgba(100.0, 0.0, 0.0, 0.0), + emissive: Color::linear_rgba(1.0, 0.0, 0.0, 0.0), ..default() }); let maroon_emissive = materials.add(StandardMaterial { base_color: MAROON.into(), - emissive: Color::linear_rgba(50.0, 0.0, 0.0, 0.0), + emissive: Color::linear_rgba(0.369, 0.0, 0.0, 0.0), ..default() }); diff --git a/examples/3d/transmission.rs b/examples/3d/transmission.rs index b5fe128f9f..0fea6d0cf2 100644 --- a/examples/3d/transmission.rs +++ b/examples/3d/transmission.rs @@ -137,8 +137,8 @@ fn setup( )); // Candle Flame - let scaled_white = LinearRgba::from(ANTIQUE_WHITE) * 80.; - let scaled_orange = LinearRgba::from(ORANGE_RED) * 16.; + let scaled_white = LinearRgba::from(ANTIQUE_WHITE) * 20.; + let scaled_orange = LinearRgba::from(ORANGE_RED) * 4.; let emissive = LinearRgba { red: scaled_white.red + scaled_orange.red, green: scaled_white.green + scaled_orange.green, diff --git a/examples/ecs/iter_combinations.rs b/examples/ecs/iter_combinations.rs index 698d2961c3..cb946bfc79 100644 --- a/examples/ecs/iter_combinations.rs +++ b/examples/ecs/iter_combinations.rs @@ -99,7 +99,7 @@ fn generate_bodies( mesh: meshes.add(Sphere::new(1.0).mesh().ico(5).unwrap()), material: materials.add(StandardMaterial { base_color: ORANGE_RED.into(), - emissive: (LinearRgba::from(ORANGE_RED) * 18.).into(), + emissive: (LinearRgba::from(ORANGE_RED) * 2.).into(), ..default() }), ..default()