Send emissive color to uniform as linear instead of sRGB (#7897)

This produces more accurate results for the `EmissiveStrengthTest` glTF test case.

(Requires manually setting the emission, for now)

Before: <img width="1392" alt="Screenshot 2023-03-04 at 18 21 25" src="https://user-images.githubusercontent.com/418473/222929455-c7363d52-7133-4d4e-9d6a-562098f6bbe8.png">

After: <img width="1392" alt="Screenshot 2023-03-04 at 18 20 57" src="https://user-images.githubusercontent.com/418473/222929454-3ea20ecb-0773-4aad-978c-3832353b6871.png">

Tagging @JMS55 as a co-author, since this fix is based on their experiments with emission.

# Objective

- Have more accurate results for the `EmissiveStrengthTest` glTF test case.

## Solution

- Make sure we send the emissive color as linear instead of sRGB.

---

## Changelog

- Emission strength is now correctly interpreted by the `StandardMaterial` as linear instead of sRGB.

## Migration Guide

- If you have previously manually specified emissive values with `Color::rgb()` and would like to retain the old visual results, you must now use `Color::rgb_linear()` instead;
- If you have previously manually specified emissive values with `Color::rgb_linear()` and would like to retain the old visual results, you'll need to apply a one-time gamma calculation to your channels manually to get the _actual_ linear RGB value: 
  - For channel values greater than `0.0031308`, use `(1.055 * value.powf(1.0 / 2.4)) - 0.055`;
  - For channel values lower than or equal to `0.0031308`, use `value * 12.92`;
- Otherwise, the results should now be more consistent with other tools/engines.
This commit is contained in:
Marco Buono 2023-03-04 23:26:04 +00:00
parent 43ea6f239d
commit f87de36843
4 changed files with 8 additions and 8 deletions

View File

@ -401,7 +401,7 @@ impl AsBindGroupShaderType<StandardMaterialUniform> for StandardMaterial {
StandardMaterialUniform {
base_color: self.base_color.as_linear_rgba_f32().into(),
emissive: self.emissive.into(),
emissive: self.emissive.as_linear_rgba_f32().into(),
roughness: self.perceptual_roughness,
metallic: self.metallic,
reflectance: self.reflectance,

View File

@ -42,15 +42,15 @@ fn setup_scene(
));
let material_emissive1 = materials.add(StandardMaterial {
emissive: Color::rgb_linear(5000.0, 500.0, 50.0), // 4. Put something bright in a dark environment to see the effect
emissive: Color::rgb_linear(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::rgb_linear(50.0, 5000.0, 500.0),
emissive: Color::rgb_linear(2.0, 13.99, 5.32),
..default()
});
let material_emissive3 = materials.add(StandardMaterial {
emissive: Color::rgb_linear(500.0, 50.0, 5000.0),
emissive: Color::rgb_linear(5.32, 2.0, 13.99),
..default()
});
let material_non_emissive = materials.add(StandardMaterial {

View File

@ -138,7 +138,7 @@ fn setup(
})),
material: materials.add(StandardMaterial {
base_color: Color::RED,
emissive: Color::rgba_linear(100.0, 0.0, 0.0, 0.0),
emissive: Color::rgba_linear(7.13, 0.0, 0.0, 0.0),
..default()
}),
..default()
@ -170,7 +170,7 @@ fn setup(
})),
material: materials.add(StandardMaterial {
base_color: Color::GREEN,
emissive: Color::rgba_linear(0.0, 100.0, 0.0, 0.0),
emissive: Color::rgba_linear(0.0, 7.13, 0.0, 0.0),
..default()
}),
..default()
@ -198,7 +198,7 @@ fn setup(
})),
material: materials.add(StandardMaterial {
base_color: Color::BLUE,
emissive: Color::rgba_linear(0.0, 0.0, 100.0, 0.0),
emissive: Color::rgba_linear(0.0, 0.0, 7.13, 0.0),
..default()
}),
..default()

View File

@ -105,7 +105,7 @@ fn setup(
})),
material: materials.add(StandardMaterial {
base_color: Color::MAROON,
emissive: Color::rgba_linear(0.125, 0.0, 0.0, 0.0),
emissive: Color::rgba_linear(0.369, 0.0, 0.0, 0.0),
..default()
}),
..default()