-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
[Merged by Bors] - Send emissive color to uniform as linear instead of sRGB #7897
Conversation
This produces more accurate results for the `EmissiveStrengthTest` glTF test case. (Requires manually setting the emission, for now) Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
To replicate the results, download the test file from Khronos then apply this patch: diff --git a/examples/tools/scene_viewer/main.rs b/examples/tools/scene_viewer/main.rs
index ee084e0af..ebfbb0937 100644
--- a/examples/tools/scene_viewer/main.rs
+++ b/examples/tools/scene_viewer/main.rs
@@ -6,6 +6,8 @@
//! With no arguments it will load the `FlightHelmet` glTF model from the repository assets subdirectory.
use bevy::{
+ core_pipeline::{bloom::BloomSettings, tonemapping::Tonemapping},
+ gltf::Gltf,
math::Vec3A,
prelude::*,
render::primitives::{Aabb, Sphere},
@@ -78,8 +80,28 @@ fn setup_scene_after_load(
mut scene_handle: ResMut<SceneHandle>,
asset_server: Res<AssetServer>,
meshes: Query<(&GlobalTransform, Option<&Aabb>), With<Handle<Mesh>>>,
+
+ gltf_assets: Res<Assets<Gltf>>,
+ mut materials: ResMut<Assets<StandardMaterial>>,
) {
if scene_handle.is_loaded && !*setup {
+ let gltf = gltf_assets.get(&scene_handle.gltf_handle).unwrap();
+
+ let mh = gltf.named_materials.get("Emit1".into()).unwrap();
+ materials.get_mut(mh).unwrap().emissive = Color::rgb_linear(0.1, 0.5, 0.9);
+
+ let mh = gltf.named_materials.get("Emit2".into()).unwrap();
+ materials.get_mut(mh).unwrap().emissive = Color::rgb_linear(0.1, 0.5, 0.9) * 2.0;
+
+ let mh = gltf.named_materials.get("Emit4".into()).unwrap();
+ materials.get_mut(mh).unwrap().emissive = Color::rgb_linear(0.1, 0.5, 0.9) * 4.0;
+
+ let mh = gltf.named_materials.get("Emit8".into()).unwrap();
+ materials.get_mut(mh).unwrap().emissive = Color::rgb_linear(0.1, 0.5, 0.9) * 8.0;
+
+ let mh = gltf.named_materials.get("Emit16".into()).unwrap();
+ materials.get_mut(mh).unwrap().emissive = Color::rgb_linear(0.1, 0.5, 0.9) * 16.0;
+
*setup = true;
// Find an approximate bounding box of the scene from its meshes
if meshes.iter().any(|(_, maybe_aabb)| maybe_aabb.is_none()) {
@@ -123,32 +145,35 @@ fn setup_scene_after_load(
)
.looking_at(Vec3::from(aabb.center), Vec3::Y),
camera: Camera {
- is_active: false,
+ is_active: true,
+ hdr: true,
..default()
},
+ tonemapping: Tonemapping::BlenderFilmic,
..default()
},
- EnvironmentMapLight {
- diffuse_map: asset_server
- .load("assets/environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
- specular_map: asset_server
- .load("assets/environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
- },
+ BloomSettings::default(),
+ // EnvironmentMapLight {
+ // diffuse_map: asset_server
+ // .load("assets/environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
+ // specular_map: asset_server
+ // .load("assets/environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
+ // },
camera_controller,
));
- // Spawn a default light if the scene does not have one
- if !scene_handle.has_light {
- info!("Spawning a directional light");
- commands.spawn(DirectionalLightBundle {
- directional_light: DirectionalLight {
- shadows_enabled: false,
- ..default()
- },
- ..default()
- });
-
- scene_handle.has_light = true;
- }
+ // // Spawn a default light if the scene does not have one
+ // if !scene_handle.has_light {
+ // info!("Spawning a directional light");
+ // commands.spawn(DirectionalLightBundle {
+ // directional_light: DirectionalLight {
+ // shadows_enabled: true,
+ // ..default()
+ // },
+ // ..default()
+ // });
+
+ // scene_handle.has_light = true;
+ // }
}
}
diff --git a/examples/tools/scene_viewer/scene_viewer_plugin.rs b/examples/tools/scene_viewer/scene_viewer_plugin.rs
index 33277e6e5..897ed246d 100644
--- a/examples/tools/scene_viewer/scene_viewer_plugin.rs
+++ b/examples/tools/scene_viewer/scene_viewer_plugin.rs
@@ -12,7 +12,7 @@ use super::camera_controller_plugin::*;
#[derive(Resource)]
pub struct SceneHandle {
- gltf_handle: Handle<Gltf>,
+ pub gltf_handle: Handle<Gltf>,
scene_index: usize,
#[cfg(feature = "animation")]
animations: Vec<Handle<AnimationClip>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs a migration guide/changelog, but code (the one line that there is) is good :)
Added the migration guide. |
Actually @coreh new change is needed: fix bloom example values, they're too bloom-y after this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The gltf loader does the right thing by interpreting the emissive factor values from the gltf as linear. However, the plain .into() in this PR was doing a linear to non-linear conversion, which was then being used as linear. The PR is correct.
Calculated via: (1.055 * value.powf(1.0 / 2.4)) - 0.055 Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
Updated the guide with math extracted from this function and updated the bloom example using the same math to get the old results back: |
Fixed two more examples. There's no real way to fix I guess I can use |
What about the bloom_2d example? |
The Edit: Confirmed that it does look the same. |
bors r+ |
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.
Pull request successfully merged into main. Build succeeded:
|
…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 produces more accurate results for the
EmissiveStrengthTest
glTF test case.(Requires manually setting the emission, for now)
Before:
After:
Tagging @JMS55 as a co-author, since this fix is based on their experiments with emission.
Objective
EmissiveStrengthTest
glTF test case.Solution
Changelog
StandardMaterial
as linear instead of sRGB.Migration Guide
Color::rgb()
and would like to retain the old visual results, you must now useColor::rgb_linear()
instead;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:0.0031308
, use(1.055 * value.powf(1.0 / 2.4)) - 0.055
;0.0031308
, usevalue * 12.92
;