Skip to main content

gltf_reader/
material.rs

1use alloc::borrow::Cow;
2use ownable::IntoOwned;
3use serde::Deserialize;
4
5use crate::texture::Texture;
6use crate::{Extensions, Extras, Idx};
7
8fn default_base_color_factor() -> [f32; 4] {
9    [1.0; 4]
10}
11
12fn one_f32() -> f32 {
13    1.0
14}
15
16fn half_f32() -> f32 {
17    0.5
18}
19
20/// Reference to a texture.
21#[derive(Debug, Clone, Deserialize, IntoOwned)]
22pub struct TextureInfo<'a> {
23    /// The index of the texture.
24    pub index: Idx<Texture<'static>>,
25    /// The set index of texture's TEXCOORD attribute used for texture coordinate mapping.
26    #[serde(rename = "texCoord")]
27    #[serde(default)]
28    pub texcoord: u64,
29
30    #[serde(borrow)]
31    pub extensions: Option<Extensions<'a>>,
32    #[serde(borrow)]
33    pub extras: Option<Extras<'a>>,
34}
35
36/// Reference to a normal texture.
37#[derive(Debug, Clone, Deserialize, IntoOwned)]
38pub struct NormalTextureInfo<'a> {
39    #[serde(flatten, borrow)]
40    pub inner: TextureInfo<'a>,
41    /// The scalar parameter applied to each normal vector of the normal texture.
42    #[serde(default = "one_f32")]
43    pub scale: f32,
44}
45
46/// Reference to an occlusion texture.
47#[derive(Debug, Clone, Deserialize, IntoOwned)]
48pub struct OcclusionTextureInfo<'a> {
49    #[serde(flatten, borrow)]
50    pub inner: TextureInfo<'a>,
51    /// A scalar multiplier controlling the amount of occlusion applied.
52    #[serde(default = "one_f32")]
53    pub strength: f32,
54}
55
56/// A set of parameter values that are used to define the metallic-roughness material model from
57/// Physically-Based Rendering (PBR) methodology.
58#[derive(Debug, Clone, Deserialize, IntoOwned)]
59pub struct PbrMetallicRoughness<'a> {
60    /// The base color texture.
61    #[serde(rename = "baseColorTexture")]
62    #[serde(borrow)]
63    pub base_color_texture: Option<TextureInfo<'a>>,
64    #[serde(rename = "metallicRoughnessTexture")]
65    #[serde(borrow)]
66    pub metallic_roughness_texture: Option<TextureInfo<'a>>,
67
68    /// The factors for the base color of the material.
69    #[serde(rename = "baseColorFactor")]
70    #[serde(default = "default_base_color_factor")]
71    pub base_color_factor: [f32; 4],
72    /// The factor for the metalness of the material.
73    #[serde(rename = "metallicFactor")]
74    #[serde(default = "one_f32")]
75    pub metallic_factor: f32,
76    /// The factor for the roughness of the material,
77    #[serde(rename = "roughnessFactor")]
78    #[serde(default = "one_f32")]
79    pub roughness_factor: f32,
80
81    #[serde(borrow)]
82    pub extensions: Option<Extensions<'a>>,
83    #[serde(borrow)]
84    pub extras: Option<Extras<'a>>,
85}
86
87/// glTF known alpha modes.
88#[derive(Debug, Clone, Copy, PartialEq, Eq)]
89pub enum AlphaModeEnum {
90    Opaque,
91    Mask,
92    Blend,
93}
94
95/// The alpha rendering mode of a material.
96#[derive(Clone, PartialEq, Eq, Deserialize, IntoOwned)]
97#[serde(transparent)]
98pub struct AlphaMode<'a>(#[serde(borrow)] pub Cow<'a, str>);
99
100impl Default for AlphaMode<'_> {
101    fn default() -> Self {
102        Self::OPAQUE
103    }
104}
105
106impl core::fmt::Debug for AlphaMode<'_> {
107    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
108        if let Some(e) = self.to_enum() {
109            e.fmt(f)
110        } else {
111            self.0.fmt(f)
112        }
113    }
114}
115
116impl AlphaMode<'_> {
117    pub const OPAQUE: Self = Self(Cow::Borrowed("OPAQUE"));
118    pub const MASK: Self = Self(Cow::Borrowed("MASK"));
119    pub const BLEND: Self = Self(Cow::Borrowed("BLEND"));
120
121    pub fn to_enum(&self) -> Option<AlphaModeEnum> {
122        if *self == Self::OPAQUE {
123            return Some(AlphaModeEnum::Opaque);
124        } else if *self == Self::MASK {
125            return Some(AlphaModeEnum::Mask);
126        } else if *self == Self::BLEND {
127            return Some(AlphaModeEnum::Blend);
128        }
129
130        None
131    }
132}
133
134/// The material appearence of a primitive.
135#[derive(Debug, Clone, Deserialize, IntoOwned)]
136pub struct Material<'a> {
137    /// The user-defined name of this object.
138    #[serde(borrow)]
139    pub name: Option<Cow<'a, str>>,
140
141    /// A set of parameter values that are used to define the metallic-roughness material model from
142    /// Physically Based Rendering (PBR) methodology.
143    #[serde(rename = "pbrMetallicRoughness")]
144    #[serde(borrow)]
145    pub pbr_metallic_roughness: Option<PbrMetallicRoughness<'a>>,
146    /// The tangent space normal texture.
147    #[serde(rename = "normalTexture")]
148    #[serde(borrow)]
149    pub normal_texture: Option<NormalTextureInfo<'a>>,
150    /// The occlusion texture.
151    #[serde(rename = "occlusionTexture")]
152    #[serde(borrow)]
153    pub occlusion_texture: Option<OcclusionTextureInfo<'a>>,
154    /// The emissive texture.
155    #[serde(rename = "emissiveTexture")]
156    #[serde(borrow)]
157    pub emissive_texture: Option<TextureInfo<'a>>,
158    /// The factors for the emissive color of the material.
159    #[serde(rename = "emissiveFactor")]
160    #[serde(default)]
161    pub emissive_factor: [f32; 3],
162    /// The alpha rendering mode of the material.
163    #[serde(rename = "alphaMode")]
164    #[serde(default)]
165    pub alpha_mode: AlphaMode<'a>,
166    /// The alpha cutoff value of the material.
167    #[serde(rename = "alphaCutoff")]
168    #[serde(default = "half_f32")]
169    pub alpha_cutoff: f32,
170    /// Specifies whether the material is double sided.
171    #[serde(rename = "doubleSided")]
172    #[serde(default)]
173    pub double_sided: bool,
174
175    #[serde(borrow)]
176    pub extensions: Option<Extensions<'a>>,
177    #[serde(borrow)]
178    pub extras: Option<Extras<'a>>,
179}