Path: blob/main/crates/bevy_gltf/src/loader/gltf_ext/texture.rs
6598 views
use bevy_asset::{Handle, LoadContext};1use bevy_image::{Image, ImageAddressMode, ImageFilterMode, ImageSamplerDescriptor};2use bevy_math::Affine2;34use gltf::{5image::Source,6texture::{MagFilter, MinFilter, Texture, TextureTransform, WrappingMode},7};89#[cfg(any(10feature = "pbr_anisotropy_texture",11feature = "pbr_multi_layer_material_textures",12feature = "pbr_specular_textures"13))]14use gltf::{json::texture::Info, Document};1516use crate::{loader::DataUri, GltfAssetLabel};1718pub(crate) fn texture_handle(19texture: &Texture<'_>,20load_context: &mut LoadContext,21) -> Handle<Image> {22match texture.source().source() {23Source::View { .. } => load_context.get_label_handle(texture_label(texture).to_string()),24Source::Uri { uri, .. } => {25let uri = percent_encoding::percent_decode_str(uri)26.decode_utf8()27.unwrap();28let uri = uri.as_ref();29if let Ok(_data_uri) = DataUri::parse(uri) {30load_context.get_label_handle(texture_label(texture).to_string())31} else {32let parent = load_context.path().parent().unwrap();33let image_path = parent.join(uri);34load_context.load(image_path)35}36}37}38}3940/// Extracts the texture sampler data from the glTF [`Texture`].41pub(crate) fn texture_sampler(42texture: &Texture<'_>,43default_sampler: &ImageSamplerDescriptor,44) -> ImageSamplerDescriptor {45let gltf_sampler = texture.sampler();46let mut sampler = default_sampler.clone();4748sampler.address_mode_u = address_mode(&gltf_sampler.wrap_s());49sampler.address_mode_v = address_mode(&gltf_sampler.wrap_t());5051// Shouldn't parse filters when anisotropic filtering is on, because trilinear is then required by wgpu.52// We also trust user to have provided a valid sampler.53if sampler.anisotropy_clamp == 1 {54if let Some(mag_filter) = gltf_sampler.mag_filter().map(|mf| match mf {55MagFilter::Nearest => ImageFilterMode::Nearest,56MagFilter::Linear => ImageFilterMode::Linear,57}) {58sampler.mag_filter = mag_filter;59}60if let Some(min_filter) = gltf_sampler.min_filter().map(|mf| match mf {61MinFilter::Nearest62| MinFilter::NearestMipmapNearest63| MinFilter::NearestMipmapLinear => ImageFilterMode::Nearest,64MinFilter::Linear | MinFilter::LinearMipmapNearest | MinFilter::LinearMipmapLinear => {65ImageFilterMode::Linear66}67}) {68sampler.min_filter = min_filter;69}70if let Some(mipmap_filter) = gltf_sampler.min_filter().map(|mf| match mf {71MinFilter::Nearest72| MinFilter::Linear73| MinFilter::NearestMipmapNearest74| MinFilter::LinearMipmapNearest => ImageFilterMode::Nearest,75MinFilter::NearestMipmapLinear | MinFilter::LinearMipmapLinear => {76ImageFilterMode::Linear77}78}) {79sampler.mipmap_filter = mipmap_filter;80}81}82sampler83}8485pub(crate) fn texture_label(texture: &Texture<'_>) -> GltfAssetLabel {86GltfAssetLabel::Texture(texture.index())87}8889pub(crate) fn address_mode(wrapping_mode: &WrappingMode) -> ImageAddressMode {90match wrapping_mode {91WrappingMode::ClampToEdge => ImageAddressMode::ClampToEdge,92WrappingMode::Repeat => ImageAddressMode::Repeat,93WrappingMode::MirroredRepeat => ImageAddressMode::MirrorRepeat,94}95}9697pub(crate) fn texture_transform_to_affine2(texture_transform: TextureTransform) -> Affine2 {98Affine2::from_scale_angle_translation(99texture_transform.scale().into(),100-texture_transform.rotation(),101texture_transform.offset().into(),102)103}104105#[cfg(any(106feature = "pbr_anisotropy_texture",107feature = "pbr_multi_layer_material_textures",108feature = "pbr_specular_textures"109))]110/// Given a [`Info`], returns the handle of the texture that this111/// refers to.112///113/// This is a low-level function only used when the [`gltf`] crate has no support114/// for an extension, forcing us to parse its texture references manually.115pub(crate) fn texture_handle_from_info(116info: &Info,117document: &Document,118load_context: &mut LoadContext,119) -> Handle<Image> {120let texture = document121.textures()122.nth(info.index.value())123.expect("Texture info references a nonexistent texture");124texture_handle(&texture, load_context)125}126127128