Add emissive_exposure_weight to the StandardMaterial (#13350)
# Objective
- The emissive color gets multiplied by the camera exposure value. But
this cancels out almost any emissive effect.
- Fixes #13133
- Closes PR #13337
## Solution
- Add emissive_exposure_weight to the StandardMaterial
- In the shader this value is stored in the alpha channel of the
emissive color.
- This value defines how much the exposure influences the emissive
color.
- It's equal to Google's Filament:
https://google.github.io/filament/Materials.html#emissive
4f021583f1/shaders/src/shading_lit.fs (L287)
## Testing
- The result of
[EmissiveStrengthTest](https://github.com/KhronosGroup/glTF-Sample-Models/tree/main/2.0/EmissiveStrengthTest)
with the default value of 0.0:
without bloom:

with bloom:

This commit is contained in:
parent
47d6e967b2
commit
1fcf6a444f
@ -90,6 +90,13 @@ pub struct StandardMaterial {
|
|||||||
/// it just adds a value to the color seen on screen.
|
/// it just adds a value to the color seen on screen.
|
||||||
pub emissive: Color,
|
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`].
|
/// The UV channel to use for the [`StandardMaterial::emissive_texture`].
|
||||||
///
|
///
|
||||||
/// Defaults to [`UvChannel::Uv0`].
|
/// Defaults to [`UvChannel::Uv0`].
|
||||||
@ -683,6 +690,7 @@ impl Default for StandardMaterial {
|
|||||||
base_color_channel: UvChannel::Uv0,
|
base_color_channel: UvChannel::Uv0,
|
||||||
base_color_texture: None,
|
base_color_texture: None,
|
||||||
emissive: Color::BLACK,
|
emissive: Color::BLACK,
|
||||||
|
emissive_exposure_weight: 0.0,
|
||||||
emissive_channel: UvChannel::Uv0,
|
emissive_channel: UvChannel::Uv0,
|
||||||
emissive_texture: None,
|
emissive_texture: None,
|
||||||
// Matches Blender's default roughness.
|
// Matches Blender's default roughness.
|
||||||
@ -964,9 +972,12 @@ impl AsBindGroupShaderType<StandardMaterialUniform> for StandardMaterial {
|
|||||||
flags |= StandardMaterialFlags::ATTENUATION_ENABLED;
|
flags |= StandardMaterialFlags::ATTENUATION_ENABLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut emissive = LinearRgba::from(self.emissive).to_f32_array();
|
||||||
|
emissive[3] = self.emissive_exposure_weight;
|
||||||
|
|
||||||
StandardMaterialUniform {
|
StandardMaterialUniform {
|
||||||
base_color: LinearRgba::from(self.base_color).to_f32_array().into(),
|
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,
|
roughness: self.perceptual_roughness,
|
||||||
metallic: self.metallic,
|
metallic: self.metallic,
|
||||||
reflectance: self.reflectance,
|
reflectance: self.reflectance,
|
||||||
|
|||||||
@ -178,7 +178,6 @@ fn pbr_input_from_standard_material(
|
|||||||
pbr_input.material.alpha_cutoff = pbr_bindings::material.alpha_cutoff;
|
pbr_input.material.alpha_cutoff = pbr_bindings::material.alpha_cutoff;
|
||||||
|
|
||||||
// emissive
|
// emissive
|
||||||
// TODO use .a for exposure compensation in HDR
|
|
||||||
var emissive: vec4<f32> = pbr_bindings::material.emissive;
|
var emissive: vec4<f32> = pbr_bindings::material.emissive;
|
||||||
#ifdef VERTEX_UVS
|
#ifdef VERTEX_UVS
|
||||||
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_EMISSIVE_TEXTURE_BIT) != 0u) {
|
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,
|
uv,
|
||||||
#endif
|
#endif
|
||||||
bias,
|
bias,
|
||||||
).rgb, 1.0);
|
).rgb, emissive.a);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
pbr_input.material.emissive = emissive;
|
pbr_input.material.emissive = emissive;
|
||||||
|
|||||||
@ -224,7 +224,6 @@ fn apply_pbr_lighting(
|
|||||||
) -> vec4<f32> {
|
) -> vec4<f32> {
|
||||||
var output_color: vec4<f32> = in.material.base_color;
|
var output_color: vec4<f32> = in.material.base_color;
|
||||||
|
|
||||||
// TODO use .a for exposure compensation in HDR
|
|
||||||
let emissive = in.material.emissive;
|
let emissive = in.material.emissive;
|
||||||
|
|
||||||
// calculate non-linear roughness from linear perceptualRoughness
|
// 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));
|
emissive_light = emissive_light * (0.04 + (1.0 - 0.04) * pow(1.0 - clearcoat_NdotV, 5.0));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
emissive_light = emissive_light * mix(1.0, view_bindings::view.exposure, emissive.a);
|
||||||
|
|
||||||
#ifdef STANDARD_MATERIAL_SPECULAR_TRANSMISSION
|
#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;
|
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
|
// Total light
|
||||||
output_color = vec4<f32>(
|
output_color = vec4<f32>(
|
||||||
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
|
output_color.a
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -41,15 +41,15 @@ fn setup_scene(
|
|||||||
));
|
));
|
||||||
|
|
||||||
let material_emissive1 = materials.add(StandardMaterial {
|
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()
|
..default()
|
||||||
});
|
});
|
||||||
let material_emissive2 = materials.add(StandardMaterial {
|
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()
|
..default()
|
||||||
});
|
});
|
||||||
let material_emissive3 = materials.add(StandardMaterial {
|
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()
|
..default()
|
||||||
});
|
});
|
||||||
let material_non_emissive = materials.add(StandardMaterial {
|
let material_non_emissive = materials.add(StandardMaterial {
|
||||||
|
|||||||
@ -35,11 +35,6 @@ fn add_lightmaps_to_meshes(
|
|||||||
) {
|
) {
|
||||||
let exposure = 250.0;
|
let exposure = 250.0;
|
||||||
for (entity, name, material) in meshes.iter() {
|
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" {
|
if &**name == "large_box" {
|
||||||
materials.get_mut(material).unwrap().lightmap_exposure = exposure;
|
materials.get_mut(material).unwrap().lightmap_exposure = exposure;
|
||||||
commands.entity(entity).insert(Lightmap {
|
commands.entity(entity).insert(Lightmap {
|
||||||
|
|||||||
@ -79,12 +79,12 @@ fn setup(
|
|||||||
let sphere_mesh_direction = meshes.add(Sphere::new(0.1).mesh().uv(32, 18));
|
let sphere_mesh_direction = meshes.add(Sphere::new(0.1).mesh().uv(32, 18));
|
||||||
let red_emissive = materials.add(StandardMaterial {
|
let red_emissive = materials.add(StandardMaterial {
|
||||||
base_color: RED.into(),
|
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()
|
..default()
|
||||||
});
|
});
|
||||||
let maroon_emissive = materials.add(StandardMaterial {
|
let maroon_emissive = materials.add(StandardMaterial {
|
||||||
base_color: MAROON.into(),
|
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()
|
..default()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -137,8 +137,8 @@ fn setup(
|
|||||||
));
|
));
|
||||||
|
|
||||||
// Candle Flame
|
// Candle Flame
|
||||||
let scaled_white = LinearRgba::from(ANTIQUE_WHITE) * 80.;
|
let scaled_white = LinearRgba::from(ANTIQUE_WHITE) * 20.;
|
||||||
let scaled_orange = LinearRgba::from(ORANGE_RED) * 16.;
|
let scaled_orange = LinearRgba::from(ORANGE_RED) * 4.;
|
||||||
let emissive = LinearRgba {
|
let emissive = LinearRgba {
|
||||||
red: scaled_white.red + scaled_orange.red,
|
red: scaled_white.red + scaled_orange.red,
|
||||||
green: scaled_white.green + scaled_orange.green,
|
green: scaled_white.green + scaled_orange.green,
|
||||||
|
|||||||
@ -99,7 +99,7 @@ fn generate_bodies(
|
|||||||
mesh: meshes.add(Sphere::new(1.0).mesh().ico(5).unwrap()),
|
mesh: meshes.add(Sphere::new(1.0).mesh().ico(5).unwrap()),
|
||||||
material: materials.add(StandardMaterial {
|
material: materials.add(StandardMaterial {
|
||||||
base_color: ORANGE_RED.into(),
|
base_color: ORANGE_RED.into(),
|
||||||
emissive: (LinearRgba::from(ORANGE_RED) * 18.).into(),
|
emissive: (LinearRgba::from(ORANGE_RED) * 2.).into(),
|
||||||
..default()
|
..default()
|
||||||
}),
|
}),
|
||||||
..default()
|
..default()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user