gltf: load normal and occlusion as linear textures (#1762)
Load textures from gltf as linear when needed. This is for #1632, but can be done independently and won't have any visible impact before. * during iteration over materials, register textures that need to be loaded as linear * during iteration over textures * directly load bytes from external files instead of adding them as dependencies in the load context * configure the texture the same way for buffered and external textures * if the texture is linear rgb, set as linear rgb
This commit is contained in:
		
							parent
							
								
									80bd378aa0
								
							
						
					
					
						commit
						d90d19f1c7
					
				| @ -14,7 +14,7 @@ use bevy_render::{ | |||||||
|     pipeline::PrimitiveTopology, |     pipeline::PrimitiveTopology, | ||||||
|     prelude::{Color, Texture}, |     prelude::{Color, Texture}, | ||||||
|     render_graph::base, |     render_graph::base, | ||||||
|     texture::{AddressMode, FilterMode, ImageType, SamplerDescriptor, TextureError}, |     texture::{AddressMode, FilterMode, ImageType, SamplerDescriptor, TextureError, TextureFormat}, | ||||||
| }; | }; | ||||||
| use bevy_scene::Scene; | use bevy_scene::Scene; | ||||||
| use bevy_transform::{ | use bevy_transform::{ | ||||||
| @ -26,7 +26,10 @@ use gltf::{ | |||||||
|     texture::{MagFilter, MinFilter, WrappingMode}, |     texture::{MagFilter, MinFilter, WrappingMode}, | ||||||
|     Material, Primitive, |     Material, Primitive, | ||||||
| }; | }; | ||||||
| use std::{collections::HashMap, path::Path}; | use std::{ | ||||||
|  |     collections::{HashMap, HashSet}, | ||||||
|  |     path::Path, | ||||||
|  | }; | ||||||
| use thiserror::Error; | use thiserror::Error; | ||||||
| 
 | 
 | ||||||
| use crate::{Gltf, GltfNode}; | use crate::{Gltf, GltfNode}; | ||||||
| @ -79,12 +82,19 @@ async fn load_gltf<'a, 'b>( | |||||||
| 
 | 
 | ||||||
|     let mut materials = vec![]; |     let mut materials = vec![]; | ||||||
|     let mut named_materials = HashMap::new(); |     let mut named_materials = HashMap::new(); | ||||||
|  |     let mut linear_textures = HashSet::new(); | ||||||
|     for material in gltf.materials() { |     for material in gltf.materials() { | ||||||
|         let handle = load_material(&material, load_context); |         let handle = load_material(&material, load_context); | ||||||
|         if let Some(name) = material.name() { |         if let Some(name) = material.name() { | ||||||
|             named_materials.insert(name.to_string(), handle.clone()); |             named_materials.insert(name.to_string(), handle.clone()); | ||||||
|         } |         } | ||||||
|         materials.push(handle); |         materials.push(handle); | ||||||
|  |         if let Some(texture) = material.normal_texture() { | ||||||
|  |             linear_textures.insert(texture.texture().index()); | ||||||
|  |         } | ||||||
|  |         if let Some(texture) = material.occlusion_texture() { | ||||||
|  |             linear_textures.insert(texture.texture().index()); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     let mut meshes = vec![]; |     let mut meshes = vec![]; | ||||||
| @ -191,15 +201,33 @@ async fn load_gltf<'a, 'b>( | |||||||
|         .collect(); |         .collect(); | ||||||
| 
 | 
 | ||||||
|     for gltf_texture in gltf.textures() { |     for gltf_texture in gltf.textures() { | ||||||
|         if let gltf::image::Source::View { view, mime_type } = gltf_texture.source().source() { |         let mut texture = match gltf_texture.source().source() { | ||||||
|             let start = view.offset() as usize; |             gltf::image::Source::View { view, mime_type } => { | ||||||
|             let end = (view.offset() + view.length()) as usize; |                 let start = view.offset() as usize; | ||||||
|             let buffer = &buffer_data[view.buffer().index()][start..end]; |                 let end = (view.offset() + view.length()) as usize; | ||||||
|             let texture_label = texture_label(&gltf_texture); |                 let buffer = &buffer_data[view.buffer().index()][start..end]; | ||||||
|             let mut texture = Texture::from_buffer(buffer, ImageType::MimeType(mime_type))?; |                 Texture::from_buffer(buffer, ImageType::MimeType(mime_type))? | ||||||
|             texture.sampler = texture_sampler(&gltf_texture); |             } | ||||||
|             load_context.set_labeled_asset::<Texture>(&texture_label, LoadedAsset::new(texture)); |             gltf::image::Source::Uri { uri, mime_type } => { | ||||||
|  |                 let parent = load_context.path().parent().unwrap(); | ||||||
|  |                 let image_path = parent.join(uri); | ||||||
|  |                 let bytes = load_context.read_asset_bytes(image_path.clone()).await?; | ||||||
|  |                 Texture::from_buffer( | ||||||
|  |                     &bytes, | ||||||
|  |                     mime_type | ||||||
|  |                         .map(|mt| ImageType::MimeType(mt)) | ||||||
|  |                         .unwrap_or_else(|| { | ||||||
|  |                             ImageType::Extension(image_path.extension().unwrap().to_str().unwrap()) | ||||||
|  |                         }), | ||||||
|  |                 )? | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |         let texture_label = texture_label(&gltf_texture); | ||||||
|  |         texture.sampler = texture_sampler(&gltf_texture); | ||||||
|  |         if linear_textures.contains(&gltf_texture.index()) { | ||||||
|  |             texture.format = TextureFormat::Rgba8Unorm; | ||||||
|         } |         } | ||||||
|  |         load_context.set_labeled_asset::<Texture>(&texture_label, LoadedAsset::new(texture)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     let mut scenes = vec![]; |     let mut scenes = vec![]; | ||||||
| @ -252,23 +280,10 @@ async fn load_gltf<'a, 'b>( | |||||||
| fn load_material(material: &Material, load_context: &mut LoadContext) -> Handle<StandardMaterial> { | fn load_material(material: &Material, load_context: &mut LoadContext) -> Handle<StandardMaterial> { | ||||||
|     let material_label = material_label(&material); |     let material_label = material_label(&material); | ||||||
|     let pbr = material.pbr_metallic_roughness(); |     let pbr = material.pbr_metallic_roughness(); | ||||||
|     let mut dependencies = Vec::new(); |  | ||||||
|     let texture_handle = if let Some(info) = pbr.base_color_texture() { |     let texture_handle = if let Some(info) = pbr.base_color_texture() { | ||||||
|         match info.texture().source().source() { |         let label = texture_label(&info.texture()); | ||||||
|             gltf::image::Source::View { .. } => { |         let path = AssetPath::new_ref(load_context.path(), Some(&label)); | ||||||
|                 let label = texture_label(&info.texture()); |         Some(load_context.get_handle(path)) | ||||||
|                 let path = AssetPath::new_ref(load_context.path(), Some(&label)); |  | ||||||
|                 Some(load_context.get_handle(path)) |  | ||||||
|             } |  | ||||||
|             gltf::image::Source::Uri { uri, .. } => { |  | ||||||
|                 let parent = load_context.path().parent().unwrap(); |  | ||||||
|                 let image_path = parent.join(uri); |  | ||||||
|                 let asset_path = AssetPath::new(image_path, None); |  | ||||||
|                 let handle = load_context.get_handle(asset_path.clone()); |  | ||||||
|                 dependencies.push(asset_path); |  | ||||||
|                 Some(handle) |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } else { |     } else { | ||||||
|         None |         None | ||||||
|     }; |     }; | ||||||
| @ -283,8 +298,7 @@ fn load_material(material: &Material, load_context: &mut LoadContext) -> Handle< | |||||||
|             metallic: pbr.metallic_factor(), |             metallic: pbr.metallic_factor(), | ||||||
|             unlit: material.unlit(), |             unlit: material.unlit(), | ||||||
|             ..Default::default() |             ..Default::default() | ||||||
|         }) |         }), | ||||||
|         .with_dependencies(dependencies), |  | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 François
						François