Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add emissive_exposure_weight to the StandardMaterial #13350

Merged
merged 3 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion crates/bevy_pbr/src/pbr_material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`].
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -964,9 +972,12 @@ impl AsBindGroupShaderType<StandardMaterialUniform> 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,
Expand Down
3 changes: 1 addition & 2 deletions crates/bevy_pbr/src/render/pbr_fragment.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -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<f32> = pbr_bindings::material.emissive;
#ifdef VERTEX_UVS
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_EMISSIVE_TEXTURE_BIT) != 0u) {
Expand All @@ -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;
Expand Down
5 changes: 3 additions & 2 deletions crates/bevy_pbr/src/render/pbr_functions.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,6 @@ fn apply_pbr_lighting(
) -> vec4<f32> {
var output_color: vec4<f32> = in.material.base_color;

// TODO use .a for exposure compensation in HDR
let emissive = in.material.emissive;

// calculate non-linear roughness from linear perceptualRoughness
Expand Down Expand Up @@ -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;

Expand All @@ -585,7 +586,7 @@ fn apply_pbr_lighting(

// Total light
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
);

Expand Down
6 changes: 3 additions & 3 deletions examples/3d/bloom_3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
5 changes: 0 additions & 5 deletions examples/3d/lightmaps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions examples/3d/spotlight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
});

Expand Down
4 changes: 2 additions & 2 deletions examples/3d/transmission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion examples/ecs/iter_combinations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down