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, |         NotShadowCaster, NotShadowReceiver, OpaqueRendererMethod, | ||||||
|     }, |     }, | ||||||
|     prelude::*, |     prelude::*, | ||||||
|     render::render_resource::TextureFormat, |     render::texture::ImageLoaderSettings, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| fn main() { | fn main() { | ||||||
| @ -21,13 +21,9 @@ fn main() { | |||||||
|         .insert_resource(DefaultOpaqueRendererMethod::deferred()) |         .insert_resource(DefaultOpaqueRendererMethod::deferred()) | ||||||
|         .insert_resource(DirectionalLightShadowMap { size: 4096 }) |         .insert_resource(DirectionalLightShadowMap { size: 4096 }) | ||||||
|         .add_plugins(DefaultPlugins) |         .add_plugins(DefaultPlugins) | ||||||
|         .insert_resource(Normal(None)) |  | ||||||
|         .insert_resource(Pause(true)) |         .insert_resource(Pause(true)) | ||||||
|         .add_systems(Startup, (setup, setup_parallax)) |         .add_systems(Startup, (setup, setup_parallax)) | ||||||
|         .add_systems( |         .add_systems(Update, (animate_light_direction, switch_mode, spin)) | ||||||
|             Update, |  | ||||||
|             (animate_light_direction, switch_mode, spin, update_normal), |  | ||||||
|         ) |  | ||||||
|         .run(); |         .run(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -211,14 +207,14 @@ fn setup( | |||||||
|         TextBundle::from_section( |         TextBundle::from_section( | ||||||
|             "", |             "", | ||||||
|             TextStyle { |             TextStyle { | ||||||
|                 font_size: 18.0, |                 font_size: 20.0, | ||||||
|                 ..default() |                 ..default() | ||||||
|             }, |             }, | ||||||
|         ) |         ) | ||||||
|         .with_style(Style { |         .with_style(Style { | ||||||
|             position_type: PositionType::Absolute, |             position_type: PositionType::Absolute, | ||||||
|             top: Val::Px(10.0), |             top: Val::Px(12.0), | ||||||
|             left: Val::Px(10.0), |             left: Val::Px(12.0), | ||||||
|             ..default() |             ..default() | ||||||
|         }), |         }), | ||||||
|     ); |     ); | ||||||
| @ -244,14 +240,17 @@ fn setup_parallax( | |||||||
|     mut commands: Commands, |     mut commands: Commands, | ||||||
|     mut materials: ResMut<Assets<StandardMaterial>>, |     mut materials: ResMut<Assets<StandardMaterial>>, | ||||||
|     mut meshes: ResMut<Assets<Mesh>>, |     mut meshes: ResMut<Assets<Mesh>>, | ||||||
|     mut normal: ResMut<Normal>, |  | ||||||
|     asset_server: Res<AssetServer>, |     asset_server: Res<AssetServer>, | ||||||
| ) { | ) { | ||||||
|     // The normal map. Note that to generate it in the GIMP image editor, you should
 |     // 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
 |     // open the depth map, and do Filters → Generic → Normal Map
 | ||||||
|     // You should enable the "flip X" checkbox.
 |     // You should enable the "flip X" checkbox.
 | ||||||
|     let normal_handle = asset_server.load("textures/parallax_example/cube_normal.png"); |     let normal_handle = asset_server.load_with_settings( | ||||||
|     normal.0 = Some(normal_handle); |         "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)); |     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 { |     let parallax_material = materials.add(StandardMaterial { | ||||||
|         perceptual_roughness: 0.4, |         perceptual_roughness: 0.4, | ||||||
|         base_color_texture: Some(asset_server.load("textures/parallax_example/cube_color.png")), |         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
 |         // The depth map is a greyscale texture where black is the highest level and
 | ||||||
|         // white the lowest.
 |         // white the lowest.
 | ||||||
|         depth_map: Some(asset_server.load("textures/parallax_example/cube_depth.png")), |         depth_map: Some(asset_server.load("textures/parallax_example/cube_depth.png")), | ||||||
| @ -281,28 +280,6 @@ fn setup_parallax( | |||||||
|         Spin { speed: 0.3 }, |         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)] | #[derive(Component)] | ||||||
| struct Spin { | struct Spin { | ||||||
|     speed: f32, |     speed: f32, | ||||||
|  | |||||||
| @ -3,18 +3,16 @@ | |||||||
| 
 | 
 | ||||||
| use std::fmt; | use std::fmt; | ||||||
| 
 | 
 | ||||||
| use bevy::{prelude::*, render::render_resource::TextureFormat}; | use bevy::{prelude::*, render::texture::ImageLoaderSettings}; | ||||||
| 
 | 
 | ||||||
| fn main() { | fn main() { | ||||||
|     App::new() |     App::new() | ||||||
|         .add_plugins(DefaultPlugins) |         .add_plugins(DefaultPlugins) | ||||||
|         .insert_resource(Normal(None)) |  | ||||||
|         .add_systems(Startup, setup) |         .add_systems(Startup, setup) | ||||||
|         .add_systems( |         .add_systems( | ||||||
|             Update, |             Update, | ||||||
|             ( |             ( | ||||||
|                 spin, |                 spin, | ||||||
|                 update_normal, |  | ||||||
|                 move_camera, |                 move_camera, | ||||||
|                 update_parallax_depth_scale, |                 update_parallax_depth_scale, | ||||||
|                 update_parallax_layers, |                 update_parallax_layers, | ||||||
| @ -200,14 +198,17 @@ fn setup( | |||||||
|     mut commands: Commands, |     mut commands: Commands, | ||||||
|     mut materials: ResMut<Assets<StandardMaterial>>, |     mut materials: ResMut<Assets<StandardMaterial>>, | ||||||
|     mut meshes: ResMut<Assets<Mesh>>, |     mut meshes: ResMut<Assets<Mesh>>, | ||||||
|     mut normal: ResMut<Normal>, |  | ||||||
|     asset_server: Res<AssetServer>, |     asset_server: Res<AssetServer>, | ||||||
| ) { | ) { | ||||||
|     // The normal map. Note that to generate it in the GIMP image editor, you should
 |     // 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
 |     // open the depth map, and do Filters → Generic → Normal Map
 | ||||||
|     // You should enable the "flip X" checkbox.
 |     // You should enable the "flip X" checkbox.
 | ||||||
|     let normal_handle = asset_server.load("textures/parallax_example/cube_normal.png"); |     let normal_handle = asset_server.load_with_settings( | ||||||
|     normal.0 = Some(normal_handle); |         "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
 |     // Camera
 | ||||||
|     commands.spawn(( |     commands.spawn(( | ||||||
| @ -254,7 +255,7 @@ fn setup( | |||||||
|     let parallax_material = materials.add(StandardMaterial { |     let parallax_material = materials.add(StandardMaterial { | ||||||
|         perceptual_roughness: 0.4, |         perceptual_roughness: 0.4, | ||||||
|         base_color_texture: Some(asset_server.load("textures/parallax_example/cube_color.png")), |         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
 |         // The depth map is a greyscale texture where black is the highest level and
 | ||||||
|         // white the lowest.
 |         // white the lowest.
 | ||||||
|         depth_map: Some(asset_server.load("textures/parallax_example/cube_depth.png")), |         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
	 Rob Parrett
						Rob Parrett