Path: blob/main/crates/bevy_gltf/src/loader/gltf_ext/material.rs
6598 views
use bevy_math::Affine2;1use bevy_pbr::UvChannel;2use bevy_render::alpha::AlphaMode;34use gltf::{json::texture::Info, Material};56use serde_json::value;78use crate::GltfAssetLabel;910use super::texture::texture_transform_to_affine2;1112#[cfg(any(13feature = "pbr_specular_textures",14feature = "pbr_multi_layer_material_textures"15))]16use {17super::texture::texture_handle_from_info,18bevy_asset::{Handle, LoadContext},19bevy_image::Image,20gltf::Document,21serde_json::{Map, Value},22};2324/// Parses a texture that's part of a material extension block and returns its25/// UV channel and image reference.26#[cfg(any(27feature = "pbr_specular_textures",28feature = "pbr_multi_layer_material_textures"29))]30pub(crate) fn parse_material_extension_texture(31material: &Material,32load_context: &mut LoadContext,33document: &Document,34extension: &Map<String, Value>,35texture_name: &str,36texture_kind: &str,37) -> (UvChannel, Option<Handle<Image>>) {38match extension39.get(texture_name)40.and_then(|value| value::from_value::<Info>(value.clone()).ok())41{42Some(json_info) => (43uv_channel(material, texture_kind, json_info.tex_coord),44Some(texture_handle_from_info(&json_info, document, load_context)),45),46None => (UvChannel::default(), None),47}48}4950pub(crate) fn uv_channel(material: &Material, texture_kind: &str, tex_coord: u32) -> UvChannel {51match tex_coord {520 => UvChannel::Uv0,531 => UvChannel::Uv1,54_ => {55let material_name = material56.name()57.map(|n| format!("the material \"{n}\""))58.unwrap_or_else(|| "an unnamed material".to_string());59let material_index = material60.index()61.map(|i| format!("index {i}"))62.unwrap_or_else(|| "default".to_string());63tracing::warn!(64"Only 2 UV Channels are supported, but {material_name} ({material_index}) \65has the TEXCOORD attribute {} on texture kind {texture_kind}, which will fallback to 0.",66tex_coord,67);68UvChannel::Uv069}70}71}7273pub(crate) fn alpha_mode(material: &Material) -> AlphaMode {74match material.alpha_mode() {75gltf::material::AlphaMode::Opaque => AlphaMode::Opaque,76gltf::material::AlphaMode::Mask => AlphaMode::Mask(material.alpha_cutoff().unwrap_or(0.5)),77gltf::material::AlphaMode::Blend => AlphaMode::Blend,78}79}8081/// Returns the index (within the `textures` array) of the texture with the82/// given field name in the data for the material extension with the given name,83/// if there is one.84pub(crate) fn extension_texture_index(85material: &Material,86extension_name: &str,87texture_field_name: &str,88) -> Option<usize> {89Some(90value::from_value::<Info>(91material92.extensions()?93.get(extension_name)?94.as_object()?95.get(texture_field_name)?96.clone(),97)98.ok()?99.index100.value(),101)102}103104/// Returns true if the material needs mesh tangents in order to be successfully105/// rendered.106///107/// We generate them if this function returns true.108pub(crate) fn needs_tangents(material: &Material) -> bool {109[110material.normal_texture().is_some(),111#[cfg(feature = "pbr_multi_layer_material_textures")]112extension_texture_index(113material,114"KHR_materials_clearcoat",115"clearcoatNormalTexture",116)117.is_some(),118]119.into_iter()120.reduce(|a, b| a || b)121.unwrap_or(false)122}123124pub(crate) fn warn_on_differing_texture_transforms(125material: &Material,126info: &gltf::texture::Info,127texture_transform: Affine2,128texture_kind: &str,129) {130let has_differing_texture_transform = info131.texture_transform()132.map(texture_transform_to_affine2)133.is_some_and(|t| t != texture_transform);134if has_differing_texture_transform {135let material_name = material136.name()137.map(|n| format!("the material \"{n}\""))138.unwrap_or_else(|| "an unnamed material".to_string());139let texture_name = info140.texture()141.name()142.map(|n| format!("its {texture_kind} texture \"{n}\""))143.unwrap_or_else(|| format!("its unnamed {texture_kind} texture"));144let material_index = material145.index()146.map(|i| format!("index {i}"))147.unwrap_or_else(|| "default".to_string());148tracing::warn!(149"Only texture transforms on base color textures are supported, but {material_name} ({material_index}) \150has a texture transform on {texture_name} (index {}), which will be ignored.", info.texture().index()151);152}153}154155pub(crate) fn material_label(material: &Material, is_scale_inverted: bool) -> GltfAssetLabel {156if let Some(index) = material.index() {157GltfAssetLabel::Material {158index,159is_scale_inverted,160}161} else {162GltfAssetLabel::DefaultMaterial163}164}165166167