Skip to content

Commit

Permalink
gltf: load normal and occlusion as linear textures (#1762)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
mockersf committed Mar 26, 2021
1 parent 80bd378 commit d90d19f
Showing 1 changed file with 42 additions and 28 deletions.
70 changes: 42 additions & 28 deletions crates/bevy_gltf/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -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};
Expand Down Expand Up @@ -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![];
Expand Down Expand Up @@ -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 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));
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];
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![];
Expand Down Expand Up @@ -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)
}
}
let label = texture_label(&info.texture());
let path = AssetPath::new_ref(load_context.path(), Some(&label));
Some(load_context.get_handle(path))
} else {
None
};
Expand All @@ -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),
}),
)
}

Expand Down

0 comments on commit d90d19f

Please sign in to comment.