gltf_viewer_lib/render/
material.rs1use std::rc::Rc;
2use std::path::Path;
3
4use gltf;
5
6use crate::render::math::*;
7use crate::render::{ Root };
8use crate::render::texture::Texture;
9use crate::shader::*;
10use crate::importdata::ImportData;
11
12pub struct Material {
13 pub index: Option<usize>, pub name: Option<String>,
15
16 pub base_color_factor: Vector4,
18 pub base_color_texture: Option<Rc<Texture>>,
19 pub metallic_factor: f32,
20 pub roughness_factor: f32,
21 pub metallic_roughness_texture: Option<Rc<Texture>>,
22
23 pub normal_texture: Option<Rc<Texture>>,
24 pub normal_scale: Option<f32>,
25
26 pub occlusion_texture: Option<Rc<Texture>>,
27 pub occlusion_strength: f32,
28 pub emissive_factor: Vector3,
29 pub emissive_texture: Option<Rc<Texture>>,
30
31 pub alpha_cutoff: f32,
32 pub alpha_mode: gltf::material::AlphaMode,
33
34 pub double_sided: bool,
35
36}
37
38impl Material {
39 pub fn from_gltf(
40 g_material: &gltf::material::Material<'_>,
41 root: &mut Root,
42 imp: &ImportData,
43 base_path: &Path
44 ) -> Material {
45 let pbr = g_material.pbr_metallic_roughness();
46
47 let mut material = Material {
48 index: g_material.index(),
49 name: g_material.name().map(|s| s.into()),
50 base_color_factor: pbr.base_color_factor().into(),
51 base_color_texture: None,
53 metallic_factor: pbr.metallic_factor(),
54 roughness_factor: pbr.roughness_factor(),
55 metallic_roughness_texture: None,
56
57 normal_texture: None,
58 normal_scale: None,
59
60 occlusion_texture: None,
61 occlusion_strength: 0.0,
62
63 emissive_factor: g_material.emissive_factor().into(),
64 emissive_texture: None,
65
66 alpha_cutoff: g_material.alpha_cutoff(),
67 alpha_mode: g_material.alpha_mode(),
68
69 double_sided: g_material.double_sided(),
70 };
71
72 if let Some(color_info) = pbr.base_color_texture() {
73 material.base_color_texture = Some(
74 load_texture(&color_info.texture(), color_info.tex_coord(), root, imp, base_path));
75 }
76 if let Some(mr_info) = pbr.metallic_roughness_texture() {
77 material.metallic_roughness_texture = Some(
78 load_texture(&mr_info.texture(), mr_info.tex_coord(), root, imp, base_path));
79 }
80 if let Some(normal_texture) = g_material.normal_texture() {
81 material.normal_texture = Some(
82 load_texture(&normal_texture.texture(), normal_texture.tex_coord(), root, imp, base_path));
83 material.normal_scale = Some(normal_texture.scale());
84 }
85 if let Some(occ_texture) = g_material.occlusion_texture() {
86 material.occlusion_texture = Some(
87 load_texture(&occ_texture.texture(), occ_texture.tex_coord(), root, imp, base_path));
88 material.occlusion_strength = occ_texture.strength();
89 }
90 if let Some(em_info) = g_material.emissive_texture() {
91 material.emissive_texture = Some(
92 load_texture(&em_info.texture(), em_info.tex_coord(), root, imp, base_path));
93 }
94
95 material
96 }
97
98 pub fn shader_flags(&self) -> ShaderFlags {
99 let mut flags = ShaderFlags::empty();
100 if self.base_color_texture.is_some() {
101 flags |= ShaderFlags::HAS_BASECOLORMAP;
102 }
103 if self.normal_texture.is_some() {
104 flags |= ShaderFlags::HAS_NORMALMAP;
105 }
106 if self.emissive_texture.is_some() {
107 flags |= ShaderFlags::HAS_EMISSIVEMAP;
108 }
109 if self.metallic_roughness_texture.is_some() {
110 flags |= ShaderFlags::HAS_METALROUGHNESSMAP;
111 }
112 if self.occlusion_texture.is_some() {
113 flags |= ShaderFlags::HAS_OCCLUSIONMAP;
114 }
115 flags
116 }
117
118}
119
120fn load_texture(
121 g_texture: &gltf::texture::Texture<'_>,
122 tex_coord: u32,
123 root: &mut Root,
124 imp: &ImportData,
125 base_path: &Path) -> Rc<Texture>
126{
127 if let Some(tex) = root.textures.iter().find(|tex| (***tex).index == g_texture.index()) {
128 return Rc::clone(tex)
129 }
130
131 let texture = Rc::new(Texture::from_gltf(g_texture, tex_coord, imp, base_path));
132 root.textures.push(Rc::clone(&texture));
133 texture
134}