Use load_with_settings instead of manually overriding srgbness in examples (#13399)
# Objective
`parallax_mapping` and `deferred_rendering` both use a roundabout way of
manually overriding the srgbness of their normal map textures.
This can now be done with `load_with_settings` in one line of code.
## Solution
- Delete the override systems and use `load_with_settings` instead
- Make `deferred_rendering`'s instruction text style consistent with
other examples while I'm in there.
(see #8478)
## Testing
Tested by running with `load` instead of `load_settings` and confirming
that lighting looks bad when `is_srgb` is not configured, and good when
it is.
## Discussion
It would arguably make more sense to configure this in a `.meta` file,
but I used `load_with_settings` because that's how it was done in the
`clearcoat` example and it does seem nice for documentation purposes to
call this out explicitly in code.
This commit is contained in:
parent
aa907d5437
commit
7cbc0357be
@ -12,7 +12,7 @@ use bevy::{
|
||||
NotShadowCaster, NotShadowReceiver, OpaqueRendererMethod,
|
||||
},
|
||||
prelude::*,
|
||||
render::render_resource::TextureFormat,
|
||||
render::texture::ImageLoaderSettings,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
@ -21,13 +21,9 @@ fn main() {
|
||||
.insert_resource(DefaultOpaqueRendererMethod::deferred())
|
||||
.insert_resource(DirectionalLightShadowMap { size: 4096 })
|
||||
.add_plugins(DefaultPlugins)
|
||||
.insert_resource(Normal(None))
|
||||
.insert_resource(Pause(true))
|
||||
.add_systems(Startup, (setup, setup_parallax))
|
||||
.add_systems(
|
||||
Update,
|
||||
(animate_light_direction, switch_mode, spin, update_normal),
|
||||
)
|
||||
.add_systems(Update, (animate_light_direction, switch_mode, spin))
|
||||
.run();
|
||||
}
|
||||
|
||||
@ -211,14 +207,14 @@ fn setup(
|
||||
TextBundle::from_section(
|
||||
"",
|
||||
TextStyle {
|
||||
font_size: 18.0,
|
||||
font_size: 20.0,
|
||||
..default()
|
||||
},
|
||||
)
|
||||
.with_style(Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(10.0),
|
||||
left: Val::Px(10.0),
|
||||
top: Val::Px(12.0),
|
||||
left: Val::Px(12.0),
|
||||
..default()
|
||||
}),
|
||||
);
|
||||
@ -244,14 +240,17 @@ fn setup_parallax(
|
||||
mut commands: Commands,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut normal: ResMut<Normal>,
|
||||
asset_server: Res<AssetServer>,
|
||||
) {
|
||||
// The normal map. Note that to generate it in the GIMP image editor, you should
|
||||
// open the depth map, and do Filters → Generic → Normal Map
|
||||
// You should enable the "flip X" checkbox.
|
||||
let normal_handle = asset_server.load("textures/parallax_example/cube_normal.png");
|
||||
normal.0 = Some(normal_handle);
|
||||
let normal_handle = asset_server.load_with_settings(
|
||||
"textures/parallax_example/cube_normal.png",
|
||||
// The normal map texture is in linear color space. Lighting won't look correct
|
||||
// if `is_srgb` is `true`, which is the default.
|
||||
|settings: &mut ImageLoaderSettings| settings.is_srgb = false,
|
||||
);
|
||||
|
||||
let mut cube = Mesh::from(Cuboid::new(0.15, 0.15, 0.15));
|
||||
|
||||
@ -262,7 +261,7 @@ fn setup_parallax(
|
||||
let parallax_material = materials.add(StandardMaterial {
|
||||
perceptual_roughness: 0.4,
|
||||
base_color_texture: Some(asset_server.load("textures/parallax_example/cube_color.png")),
|
||||
normal_map_texture: normal.0.clone(),
|
||||
normal_map_texture: Some(normal_handle),
|
||||
// The depth map is a greyscale texture where black is the highest level and
|
||||
// white the lowest.
|
||||
depth_map: Some(asset_server.load("textures/parallax_example/cube_depth.png")),
|
||||
@ -281,28 +280,6 @@ fn setup_parallax(
|
||||
Spin { speed: 0.3 },
|
||||
));
|
||||
}
|
||||
|
||||
/// Store handle of the normal to later modify its format in [`update_normal`].
|
||||
#[derive(Resource)]
|
||||
struct Normal(Option<Handle<Image>>);
|
||||
|
||||
// See `examples/3d/parallax_mapping.rs` example for reasoning
|
||||
fn update_normal(
|
||||
mut already_ran: Local<bool>,
|
||||
mut images: ResMut<Assets<Image>>,
|
||||
normal: Res<Normal>,
|
||||
) {
|
||||
if *already_ran {
|
||||
return;
|
||||
}
|
||||
if let Some(normal) = normal.0.as_ref() {
|
||||
if let Some(image) = images.get_mut(normal) {
|
||||
image.texture_descriptor.format = TextureFormat::Rgba8Unorm;
|
||||
*already_ran = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
struct Spin {
|
||||
speed: f32,
|
||||
|
||||
@ -3,18 +3,16 @@
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use bevy::{prelude::*, render::render_resource::TextureFormat};
|
||||
use bevy::{prelude::*, render::texture::ImageLoaderSettings};
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins(DefaultPlugins)
|
||||
.insert_resource(Normal(None))
|
||||
.add_systems(Startup, setup)
|
||||
.add_systems(
|
||||
Update,
|
||||
(
|
||||
spin,
|
||||
update_normal,
|
||||
move_camera,
|
||||
update_parallax_depth_scale,
|
||||
update_parallax_layers,
|
||||
@ -200,14 +198,17 @@ fn setup(
|
||||
mut commands: Commands,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut normal: ResMut<Normal>,
|
||||
asset_server: Res<AssetServer>,
|
||||
) {
|
||||
// The normal map. Note that to generate it in the GIMP image editor, you should
|
||||
// open the depth map, and do Filters → Generic → Normal Map
|
||||
// You should enable the "flip X" checkbox.
|
||||
let normal_handle = asset_server.load("textures/parallax_example/cube_normal.png");
|
||||
normal.0 = Some(normal_handle);
|
||||
let normal_handle = asset_server.load_with_settings(
|
||||
"textures/parallax_example/cube_normal.png",
|
||||
// The normal map texture is in linear color space. Lighting won't look correct
|
||||
// if `is_srgb` is `true`, which is the default.
|
||||
|settings: &mut ImageLoaderSettings| settings.is_srgb = false,
|
||||
);
|
||||
|
||||
// Camera
|
||||
commands.spawn((
|
||||
@ -254,7 +255,7 @@ fn setup(
|
||||
let parallax_material = materials.add(StandardMaterial {
|
||||
perceptual_roughness: 0.4,
|
||||
base_color_texture: Some(asset_server.load("textures/parallax_example/cube_color.png")),
|
||||
normal_map_texture: normal.0.clone(),
|
||||
normal_map_texture: Some(normal_handle),
|
||||
// The depth map is a greyscale texture where black is the highest level and
|
||||
// white the lowest.
|
||||
depth_map: Some(asset_server.load("textures/parallax_example/cube_depth.png")),
|
||||
@ -335,38 +336,3 @@ fn setup(
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
/// Store handle of the normal to later modify its format in [`update_normal`].
|
||||
#[derive(Resource)]
|
||||
struct Normal(Option<Handle<Image>>);
|
||||
|
||||
/// Work around the default bevy image loader.
|
||||
///
|
||||
/// The bevy image loader used by `AssetServer` always loads images in
|
||||
/// `Srgb` mode, which is usually what it should do,
|
||||
/// but is incompatible with normal maps.
|
||||
///
|
||||
/// Normal maps require a texture in linear color space,
|
||||
/// so we overwrite the format of the normal map we loaded through `AssetServer`
|
||||
/// in this system.
|
||||
///
|
||||
/// Note that this method of conversion is a last resort workaround. You should
|
||||
/// get your normal maps from a 3d model file, like gltf.
|
||||
///
|
||||
/// In this system, we wait until the image is loaded, immediately
|
||||
/// change its format and never run the logic afterward.
|
||||
fn update_normal(
|
||||
mut already_ran: Local<bool>,
|
||||
mut images: ResMut<Assets<Image>>,
|
||||
normal: Res<Normal>,
|
||||
) {
|
||||
if *already_ran {
|
||||
return;
|
||||
}
|
||||
if let Some(normal) = normal.0.as_ref() {
|
||||
if let Some(image) = images.get_mut(normal) {
|
||||
image.texture_descriptor.format = TextureFormat::Rgba8Unorm;
|
||||
*already_ran = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user