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, | ||||
|     prelude::{Color, Texture}, | ||||
|     render_graph::base, | ||||
|     texture::{AddressMode, FilterMode, ImageType, SamplerDescriptor, TextureError}, | ||||
|     texture::{AddressMode, FilterMode, ImageType, SamplerDescriptor, TextureError, TextureFormat}, | ||||
| }; | ||||
| use bevy_scene::Scene; | ||||
| use bevy_transform::{ | ||||
| @ -26,7 +26,10 @@ use gltf::{ | ||||
|     texture::{MagFilter, MinFilter, WrappingMode}, | ||||
|     Material, Primitive, | ||||
| }; | ||||
| use std::{collections::HashMap, path::Path}; | ||||
| use std::{ | ||||
|     collections::{HashMap, HashSet}, | ||||
|     path::Path, | ||||
| }; | ||||
| use thiserror::Error; | ||||
| 
 | ||||
| use crate::{Gltf, GltfNode}; | ||||
| @ -79,12 +82,19 @@ async fn load_gltf<'a, 'b>( | ||||
| 
 | ||||
|     let mut materials = vec![]; | ||||
|     let mut named_materials = HashMap::new(); | ||||
|     let mut linear_textures = HashSet::new(); | ||||
|     for material in gltf.materials() { | ||||
|         let handle = load_material(&material, load_context); | ||||
|         if let Some(name) = material.name() { | ||||
|             named_materials.insert(name.to_string(), handle.clone()); | ||||
|         } | ||||
|         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![]; | ||||
| @ -191,15 +201,33 @@ async fn load_gltf<'a, 'b>( | ||||
|         .collect(); | ||||
| 
 | ||||
|     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() { | ||||
|             gltf::image::Source::View { view, mime_type } => { | ||||
|                 let start = view.offset() as usize; | ||||
|                 let end = (view.offset() + view.length()) as usize; | ||||
|                 let buffer = &buffer_data[view.buffer().index()][start..end]; | ||||
|             let texture_label = texture_label(&gltf_texture); | ||||
|             let mut texture = 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)); | ||||
|                 Texture::from_buffer(buffer, ImageType::MimeType(mime_type))? | ||||
|             } | ||||
|             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![]; | ||||
| @ -252,23 +280,10 @@ async fn load_gltf<'a, 'b>( | ||||
| fn load_material(material: &Material, load_context: &mut LoadContext) -> Handle<StandardMaterial> { | ||||
|     let material_label = material_label(&material); | ||||
|     let pbr = material.pbr_metallic_roughness(); | ||||
|     let mut dependencies = Vec::new(); | ||||
|     let texture_handle = if let Some(info) = pbr.base_color_texture() { | ||||
|         match info.texture().source().source() { | ||||
|             gltf::image::Source::View { .. } => { | ||||
|         let label = texture_label(&info.texture()); | ||||
|         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 { | ||||
|         None | ||||
|     }; | ||||
| @ -283,8 +298,7 @@ fn load_material(material: &Material, load_context: &mut LoadContext) -> Handle< | ||||
|             metallic: pbr.metallic_factor(), | ||||
|             unlit: material.unlit(), | ||||
|             ..Default::default() | ||||
|         }) | ||||
|         .with_dependencies(dependencies), | ||||
|         }), | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 François
						François