1
2use crate::prelude::*;
3use std::{
4 any::Any,
5 collections::{HashMap, BTreeSet},
6 fmt::Debug,
7 sync::Arc,
8};
9
10#[derive(Debug, Clone)]
12pub enum MaterialComponent {
13 Texture(Arc<VulkanTexture>),
14 Color(Vec4),
15 Luminance(f32),
16}
17
18impl MaterialComponent {
19 pub fn from_obj(device: Arc<VulkanDevice>, cmdbuf: VkCommandBuffer, obj_comp: &ObjMaterialComponent) -> Result<Self, VulkanError> {
21 match obj_comp {
22 ObjMaterialComponent::Texture(path) => Ok(MaterialComponent::Texture(Arc::new(VulkanTexture::new_from_path(device, cmdbuf, path, true, Some(VkFilter::VK_FILTER_LINEAR), VkImageUsageFlagBits::VK_IMAGE_USAGE_SAMPLED_BIT as VkImageUsageFlags)?))),
23 ObjMaterialComponent::Color(color) => Ok(MaterialComponent::Color(*color)),
24 ObjMaterialComponent::Luminance(lum) => Ok(MaterialComponent::Luminance(*lum)),
25 }
26 }
27}
28
29#[derive(Default, Debug, Clone)]
31pub struct MaterialLegacy {
32 pub ambient: MaterialComponent,
34
35 pub diffuse: MaterialComponent,
37
38 pub specular: MaterialComponent,
40
41 pub specular_power: MaterialComponent,
43
44 pub normal: MaterialComponent,
46
47 pub emissive: MaterialComponent,
49
50 pub others: HashMap<String, MaterialComponent>,
52}
53
54#[derive(Default, Debug, Clone)]
56pub struct MaterialPbr {
57 pub albedo: MaterialComponent,
59
60 pub normal: MaterialComponent,
62
63 pub ao: MaterialComponent,
65
66 pub displacement: MaterialComponent,
68
69 pub roughness: MaterialComponent,
71
72 pub metalness: MaterialComponent,
74
75 pub emissive: MaterialComponent,
77
78 pub others: HashMap<String, MaterialComponent>,
80}
81
82impl Default for MaterialComponent {
83 fn default() -> Self {
84 Self::Color(Vec4::new(0.5, 0.5, 0.5, 1.0))
85 }
86}
87
88pub trait Material: Debug + Any {
90 fn get_ambient(&self) -> Option<&MaterialComponent>;
92
93 fn get_diffuse(&self) -> Option<&MaterialComponent>;
95
96 fn get_specular(&self) -> Option<&MaterialComponent>;
98
99 fn get_specular_power(&self) -> Option<&MaterialComponent>;
101
102 fn get_albedo(&self) -> Option<&MaterialComponent>;
104
105 fn get_ao(&self) -> Option<&MaterialComponent>;
107
108 fn get_displacement(&self) -> Option<&MaterialComponent>;
110
111 fn get_roughness(&self) -> Option<&MaterialComponent>;
113
114 fn get_metalness(&self) -> Option<&MaterialComponent>;
116
117 fn get_normal(&self) -> Option<&MaterialComponent>;
119
120 fn get_emissive(&self) -> Option<&MaterialComponent>;
122
123 fn get_names(&self) -> BTreeSet<String>;
125
126 fn get_by_name(&self, name: &str) -> Option<&MaterialComponent>;
128
129 fn set_by_name(&mut self, name: &str, texture: MaterialComponent);
131}
132
133pub fn create_material_from_obj_material(device: Arc<VulkanDevice>, cmdbuf: VkCommandBuffer, objmat: &dyn ObjMaterial) -> Result<Arc<dyn Material>, VulkanError> {
135 let mut ret: Box<dyn Material> = if (objmat as &dyn Any).downcast_ref::<ObjMaterialLegacy>().is_some() {
136 Box::new(MaterialLegacy::default())
137 } else {
138 Box::new(MaterialPbr::default())
139 };
140 for entry in objmat.get_names().iter() {
141 ret.set_by_name(entry, MaterialComponent::from_obj(device.clone(), cmdbuf, objmat.get_by_name(entry).unwrap())?);
142 }
143 Ok(Arc::from(ret))
144}
145
146impl Material for MaterialLegacy {
147 fn get_ambient(&self) -> Option<&MaterialComponent> {Some(&self.ambient)}
148 fn get_diffuse(&self) -> Option<&MaterialComponent> {Some(&self.diffuse)}
149 fn get_specular(&self) -> Option<&MaterialComponent> {Some(&self.specular)}
150 fn get_specular_power(&self) -> Option<&MaterialComponent> {Some(&self.specular_power)}
151 fn get_normal(&self) -> Option<&MaterialComponent> {Some(&self.normal)}
152 fn get_emissive(&self) -> Option<&MaterialComponent> {Some(&self.emissive)}
153
154 fn get_albedo(&self) -> Option<&MaterialComponent> {Some(&self.diffuse)}
155 fn get_ao(&self) -> Option<&MaterialComponent> {Some(&self.ambient)}
156 fn get_displacement(&self) -> Option<&MaterialComponent> {None}
157 fn get_roughness(&self) -> Option<&MaterialComponent> {None}
158 fn get_metalness(&self) -> Option<&MaterialComponent> {None}
159
160 fn get_names(&self) -> BTreeSet<String> {
161 let mut ret = BTreeSet::new();
162 ret.insert("ambient".to_owned());
163 ret.insert("diffuse".to_owned());
164 ret.insert("specular".to_owned());
165 ret.insert("specular_power".to_owned());
166 ret.insert("normal".to_owned());
167 ret.insert("emissive".to_owned());
168 for (name, _) in self.others.iter() {
169 ret.insert(name.clone());
170 }
171 ret
172 }
173
174 fn get_by_name(&self, name: &str) -> Option<&MaterialComponent> {
175 match self.others.get(name) {
176 Some(data) => Some(data),
177 None => {
178 match name {
179 "ambient" => self.get_ambient(),
180 "diffuse" => self.get_diffuse(),
181 "specular" => self.get_specular(),
182 "specular_power" => self.get_specular_power(),
183 "normal" => self.get_normal(),
184 "emissive" => self.get_emissive(),
185 _ => None,
186 }
187 }
188 }
189 }
190
191 fn set_by_name(&mut self, name: &str, texture: MaterialComponent) {
192 match name {
193 "ambient" => self.ambient = texture,
194 "diffuse" => self.diffuse = texture,
195 "specular" => self.specular = texture,
196 "specular_power" => self.specular_power = texture,
197 "normal" => self.normal = texture,
198 "emissive" => self.emissive = texture,
199 others =>{
200 self.others.insert(others.to_owned(), texture);
201 }
202 }
203 }
204}
205
206impl Material for MaterialPbr {
207 fn get_albedo(&self) -> Option<&MaterialComponent> {Some(&self.albedo)}
208 fn get_ao(&self) -> Option<&MaterialComponent> {Some(&self.ao)}
209 fn get_displacement(&self) -> Option<&MaterialComponent> {Some(&self.displacement)}
210 fn get_roughness(&self) -> Option<&MaterialComponent> {Some(&self.roughness)}
211 fn get_metalness(&self) -> Option<&MaterialComponent> {Some(&self.metalness)}
212 fn get_normal(&self) -> Option<&MaterialComponent> {Some(&self.normal)}
213 fn get_emissive(&self) -> Option<&MaterialComponent> {Some(&self.emissive)}
214
215 fn get_ambient(&self) -> Option<&MaterialComponent> {Some(&self.ao)}
216 fn get_diffuse(&self) -> Option<&MaterialComponent> {Some(&self.albedo)}
217 fn get_specular(&self) -> Option<&MaterialComponent> {None}
218 fn get_specular_power(&self) -> Option<&MaterialComponent> {None}
219
220 fn get_names(&self) -> BTreeSet<String> {
221 let mut ret = BTreeSet::new();
222 ret.insert("albedo".to_owned());
223 ret.insert("ao".to_owned());
224 ret.insert("displacement".to_owned());
225 ret.insert("roughness".to_owned());
226 ret.insert("metalness".to_owned());
227 ret.insert("normal".to_owned());
228 ret.insert("emissive".to_owned());
229 for (name, _) in self.others.iter() {
230 ret.insert(name.clone());
231 }
232 ret
233 }
234
235 fn get_by_name(&self, name: &str) -> Option<&MaterialComponent> {
236 match self.others.get(name) {
237 Some(data) => Some(data),
238 None => {
239 match name {
240 "albedo" => self.get_albedo(),
241 "ao" => self.get_ao(),
242 "displacement" => self.get_displacement(),
243 "roughness" => self.get_roughness(),
244 "metalness" => self.get_metalness(),
245 "normal" => self.get_normal(),
246 "emissive" => self.get_emissive(),
247 _ => None,
248 }
249 }
250 }
251 }
252
253 fn set_by_name(&mut self, name: &str, texture: MaterialComponent) {
254 match name {
255 "albedo" => self.albedo = texture,
256 "ao" => self.ao = texture,
257 "displacement" => self.displacement = texture,
258 "roughness" => self.roughness = texture,
259 "metalness" => self.metalness = texture,
260 "normal" => self.normal = texture,
261 "emissive" => self.emissive = texture,
262 others =>{
263 self.others.insert(others.to_owned(), texture);
264 }
265 }
266 }
267}