globject_rs/
material.rs

1
2use crate::prelude::*;
3use std::{
4	collections::{HashMap, BTreeSet},
5	fmt::Debug,
6	rc::Rc,
7};
8
9/// The material component
10#[derive(Debug, Clone)]
11pub enum MaterialComponent {
12	Texture(Rc<dyn GenericTexture>),
13	Color(Vec4),
14	Luminance(f32),
15}
16
17/// The legacy illumination model material
18#[derive(Default, Debug, Clone)]
19pub struct MaterialLegacy {
20	/// Base brightness
21	pub ambient: MaterialComponent,
22
23	/// Base color
24	pub diffuse: MaterialComponent,
25
26	/// Specular color
27	pub specular: MaterialComponent,
28
29	/// Specular power
30	pub specular_power: MaterialComponent,
31
32	/// Normal map
33	pub normal: MaterialComponent,
34
35	/// Emissive, self-lighting
36	pub emissive: MaterialComponent,
37
38	/// The other type of components
39	pub others: HashMap<String, MaterialComponent>,
40}
41
42/// The physically based rendering illumination model material
43#[derive(Default, Debug, Clone)]
44pub struct MaterialPbr {
45	/// Base color
46	pub albedo: MaterialComponent,
47
48	/// Normal map
49	pub normal: MaterialComponent,
50
51	/// Ambient occlusion
52	pub ao: MaterialComponent,
53
54	/// A.k.a. Height map. The renderer must render this map by extruding the mesh, or use ray-marching to cast the protrusions of the map
55	pub displacement: MaterialComponent,
56
57	/// Roughness, something sort of the legacy specular-key map
58	pub roughness: MaterialComponent,
59
60	/// Metalness, something sort of the legacy specular map
61	pub metalness: MaterialComponent,
62
63	/// Emissive, self-lighting
64	pub emissive: MaterialComponent,
65
66	/// The other type of components
67	pub others: HashMap<String, MaterialComponent>,
68}
69
70impl Default for MaterialComponent {
71	fn default() -> Self {
72		Self::Color(Vec4::new(0.5, 0.5, 0.5, 1.0))
73	}
74}
75
76/// The `Material` trait helps the `MaterialLegacy` struct or the `MaterialPbr` struct to be able to turn into an object
77pub trait Material: Debug {
78	/// Get the ambient color
79	fn get_ambient(&self) -> Option<&MaterialComponent>;
80
81	/// Get the diffuse color
82	fn get_diffuse(&self) -> Option<&MaterialComponent>;
83
84	/// Get the specular color
85	fn get_specular(&self) -> Option<&MaterialComponent>;
86
87	/// Get the specular power
88	fn get_specular_power(&self) -> Option<&MaterialComponent>;
89
90	/// Get the base color (PBR)
91	fn get_albedo(&self) -> Option<&MaterialComponent>;
92
93	/// Get the ambient occlusion (PBR)
94	fn get_ao(&self) -> Option<&MaterialComponent>;
95
96	/// Get the displacement map (A.k.a. height map) (PBR)
97	fn get_displacement(&self) -> Option<&MaterialComponent>;
98
99	/// Get the roughness map (PBR)
100	fn get_roughness(&self) -> Option<&MaterialComponent>;
101
102	/// Get the metalness map (PBR)
103	fn get_metalness(&self) -> Option<&MaterialComponent>;
104
105	/// Get the normal map
106	fn get_normal(&self) -> Option<&MaterialComponent>;
107
108	/// Get the emissive color
109	fn get_emissive(&self) -> Option<&MaterialComponent>;
110
111	/// Get all of the component names exists in this material
112	fn get_names(&self) -> BTreeSet<String>;
113
114	/// Get a component by the name of the component
115	fn get_by_name(&self, name: &str) -> Option<&MaterialComponent>;
116
117	/// Set a componnet by the name of the component
118	fn set_by_name(&mut self, name: &str, texture: MaterialComponent);
119}
120
121impl Material for MaterialLegacy {
122	fn get_ambient(&self) ->		Option<&MaterialComponent> {Some(&self.ambient)}
123	fn get_diffuse(&self) ->		Option<&MaterialComponent> {Some(&self.diffuse)}
124	fn get_specular(&self) ->		Option<&MaterialComponent> {Some(&self.specular)}
125	fn get_specular_power(&self) ->	Option<&MaterialComponent> {Some(&self.specular_power)}
126	fn get_normal(&self) ->			Option<&MaterialComponent> {Some(&self.normal)}
127	fn get_emissive(&self) ->		Option<&MaterialComponent> {Some(&self.emissive)}
128
129	fn get_albedo(&self) ->			Option<&MaterialComponent> {None}
130	fn get_ao(&self) ->				Option<&MaterialComponent> {None}
131	fn get_displacement(&self) ->	Option<&MaterialComponent> {None}
132	fn get_roughness(&self) ->		Option<&MaterialComponent> {None}
133	fn get_metalness(&self) ->		Option<&MaterialComponent> {None}
134
135	fn get_names(&self) -> BTreeSet<String> {
136		let mut ret = BTreeSet::new();
137		ret.insert("ambient".to_owned());
138		ret.insert("diffuse".to_owned());
139		ret.insert("specular".to_owned());
140		ret.insert("specular_power".to_owned());
141		ret.insert("normal".to_owned());
142		ret.insert("emissive".to_owned());
143		for (name, _) in self.others.iter() {
144			ret.insert(name.clone());
145		}
146		ret
147	}
148
149	fn get_by_name(&self, name: &str) -> Option<&MaterialComponent> {
150		match self.others.get(name) {
151			Some(data) => Some(data),
152			None => {
153				match name {
154					"ambient" =>		self.get_ambient(),
155					"diffuse" =>		self.get_diffuse(),
156					"specular" =>		self.get_specular(),
157					"specular_power" =>	self.get_specular_power(),
158					"normal" =>			self.get_normal(),
159					"emissive" =>		self.get_emissive(),
160					_ => None,
161				}
162			}
163		}
164	}
165
166	fn set_by_name(&mut self, name: &str, texture: MaterialComponent) {
167		match name {
168			"ambient" =>		self.ambient = texture,
169			"diffuse" =>		self.diffuse = texture,
170			"specular" =>		self.specular = texture,
171			"specular_power" =>	self.specular_power = texture,
172			"normal" =>			self.normal = texture,
173			"emissive" =>		self.emissive = texture,
174			others =>{
175				self.others.insert(others.to_owned(), texture);
176			}
177		}
178	}
179}
180
181impl Material for MaterialPbr {
182	fn get_albedo(&self) ->			Option<&MaterialComponent> {Some(&self.albedo)}
183	fn get_ao(&self) ->				Option<&MaterialComponent> {Some(&self.ao)}
184	fn get_displacement(&self) ->	Option<&MaterialComponent> {Some(&self.displacement)}
185	fn get_roughness(&self) ->		Option<&MaterialComponent> {Some(&self.roughness)}
186	fn get_metalness(&self) ->		Option<&MaterialComponent> {Some(&self.metalness)}
187	fn get_normal(&self) ->			Option<&MaterialComponent> {Some(&self.normal)}
188	fn get_emissive(&self) ->		Option<&MaterialComponent> {Some(&self.emissive)}
189
190	fn get_ambient(&self) ->		Option<&MaterialComponent> {None}
191	fn get_diffuse(&self) ->		Option<&MaterialComponent> {None}
192	fn get_specular(&self) ->		Option<&MaterialComponent> {None}
193	fn get_specular_power(&self) ->	Option<&MaterialComponent> {None}
194
195	fn get_names(&self) -> BTreeSet<String> {
196		let mut ret = BTreeSet::new();
197		ret.insert("albedo".to_owned());
198		ret.insert("ao".to_owned());
199		ret.insert("displacement".to_owned());
200		ret.insert("roughness".to_owned());
201		ret.insert("metalness".to_owned());
202		ret.insert("normal".to_owned());
203		ret.insert("emissive".to_owned());
204		for (name, _) in self.others.iter() {
205			ret.insert(name.clone());
206		}
207		ret
208	}
209
210	fn get_by_name(&self, name: &str) -> Option<&MaterialComponent> {
211		match self.others.get(name) {
212			Some(data) => Some(data),
213			None => {
214				match name {
215					"albedo" =>			self.get_albedo(),
216					"ao" =>				self.get_ao(),
217					"displacement" =>	self.get_displacement(),
218					"roughness" =>		self.get_roughness(),
219					"metalness" =>		self.get_metalness(),
220					"normal" =>			self.get_normal(),
221					"emissive" =>		self.get_emissive(),
222					_ => None,
223				}
224			}
225		}
226	}
227
228	fn set_by_name(&mut self, name: &str, texture: MaterialComponent) {
229		match name {
230			"albedo" =>			self.albedo = texture,
231			"ao" =>				self.ao = texture,
232			"displacement" =>	self.displacement = texture,
233			"roughness" =>		self.roughness = texture,
234			"metalness" =>		self.metalness = texture,
235			"normal" =>			self.normal = texture,
236			"emissive" =>		self.emissive = texture,
237			others =>{
238				self.others.insert(others.to_owned(), texture);
239			}
240		}
241	}
242}