1use crate::asset_id::TextureId;
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
13pub struct TextureTransform {
14 pub offset: [f32; 2],
16 pub rotation: f32,
18 pub scale: [f32; 2],
20 pub uv_set: u32,
22}
23
24impl Default for TextureTransform {
25 fn default() -> Self {
26 Self {
27 offset: [0.0, 0.0],
28 rotation: 0.0,
29 scale: [1.0, 1.0],
30 uv_set: 0,
31 }
32 }
33}
34
35impl TextureTransform {
36 pub const IDENTITY: Self = Self {
37 offset: [0.0, 0.0],
38 rotation: 0.0,
39 scale: [1.0, 1.0],
40 uv_set: 0,
41 };
42
43 pub fn to_packed(&self) -> ([f32; 3], [f32; 3]) {
56 let cos_r = self.rotation.cos();
57 let sin_r = self.rotation.sin();
58 let m00 = cos_r * self.scale[0];
59 let m01 = sin_r * self.scale[1];
60 let m02 = self.offset[0];
61 let m10 = -sin_r * self.scale[0];
62 let m11 = cos_r * self.scale[1];
63 let m12 = self.offset[1];
64 ([m00, m01, m02], [m10, m11, m12])
65 }
66}
67
68#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default, Hash)]
70pub enum AlphaMode {
71 #[default]
73 Opaque,
74 Mask,
76 Blend,
78 Dither,
82}
83
84#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
90pub struct Material {
91 pub base_color: [f32; 4],
93 pub emissive_factor: [f32; 3],
95 pub alpha_mode: AlphaMode,
97 pub alpha_cutoff: f32,
99 #[serde(default = "default_blend_opaque_alpha_threshold")]
108 pub blend_opaque_alpha_threshold: f32,
109 pub base_texture: Option<String>,
111 #[serde(default)]
112 pub base_texture_transform: TextureTransform,
113 pub emissive_texture: Option<String>,
115 #[serde(default)]
116 pub emissive_texture_transform: TextureTransform,
117 pub normal_texture: Option<String>,
119 #[serde(default)]
120 pub normal_texture_transform: TextureTransform,
121 #[serde(default = "default_normal_scale")]
123 pub normal_scale: f32,
124 #[serde(default)]
126 pub normal_map_flip_y: bool,
127 #[serde(default)]
129 pub normal_map_two_component: bool,
130 #[serde(default)]
134 pub detail_base_texture: Option<String>,
135 #[serde(default)]
138 pub detail_normal_texture: Option<String>,
139 #[serde(default = "default_detail_uv_scale")]
141 pub detail_uv_scale: f32,
142 #[serde(default)]
145 pub height_texture: Option<String>,
146 #[serde(default)]
148 pub parallax_scale: f32,
149 #[serde(default)]
154 pub reflection_box_min: [f32; 3],
155 #[serde(default)]
157 pub reflection_box_max: [f32; 3],
158 pub metallic_roughness_texture: Option<String>,
160 #[serde(default)]
161 pub metallic_roughness_texture_transform: TextureTransform,
162 pub occlusion_texture: Option<String>,
164 #[serde(default)]
165 pub occlusion_texture_transform: TextureTransform,
166 #[serde(default = "default_occlusion_strength")]
168 pub occlusion_strength: f32,
169 pub roughness: f32,
171 pub metallic: f32,
173 pub unlit: bool,
175 #[serde(default)]
177 pub double_sided: bool,
178 #[serde(default)]
180 pub transmission_factor: f32,
181 #[serde(default)]
182 pub transmission_texture: Option<String>,
183 #[serde(default)]
184 pub transmission_texture_transform: TextureTransform,
185 #[serde(default)]
187 pub thickness: f32,
188 #[serde(default)]
189 pub thickness_texture: Option<String>,
190 #[serde(default)]
191 pub thickness_texture_transform: TextureTransform,
192 #[serde(default = "default_attenuation_color")]
194 pub attenuation_color: [f32; 3],
195 #[serde(default)]
197 pub attenuation_distance: f32,
198 #[serde(default = "default_ior")]
200 pub ior: f32,
201 #[serde(default = "default_specular_factor")]
203 pub specular_factor: f32,
204 #[serde(default = "default_specular_color_factor")]
206 pub specular_color_factor: [f32; 3],
207 #[serde(default)]
208 pub specular_texture: Option<String>,
209 #[serde(default)]
210 pub specular_texture_transform: TextureTransform,
211 #[serde(default)]
212 pub specular_color_texture: Option<String>,
213 #[serde(default)]
214 pub specular_color_texture_transform: TextureTransform,
215 #[serde(default = "default_emissive_strength")]
217 pub emissive_strength: f32,
218 #[serde(default)]
221 pub diffuse_transmission_factor: f32,
222 #[serde(default)]
223 pub diffuse_transmission_texture: Option<String>,
224 #[serde(default)]
225 pub diffuse_transmission_texture_transform: TextureTransform,
226 #[serde(default = "default_diffuse_transmission_color")]
228 pub diffuse_transmission_color_factor: [f32; 3],
229 #[serde(default)]
230 pub diffuse_transmission_color_texture: Option<String>,
231 #[serde(default)]
232 pub diffuse_transmission_color_texture_transform: TextureTransform,
233 #[serde(default)]
236 pub dispersion: f32,
237 #[serde(default)]
239 pub anisotropy_strength: f32,
240 #[serde(default)]
242 pub anisotropy_rotation: f32,
243 #[serde(default)]
244 pub anisotropy_texture: Option<String>,
245 #[serde(default)]
246 pub anisotropy_texture_transform: TextureTransform,
247 #[serde(default)]
249 pub iridescence_factor: f32,
250 #[serde(default)]
251 pub iridescence_texture: Option<String>,
252 #[serde(default)]
253 pub iridescence_texture_transform: TextureTransform,
254 #[serde(default = "default_iridescence_ior")]
256 pub iridescence_ior: f32,
257 #[serde(default = "default_iridescence_thickness_min")]
259 pub iridescence_thickness_minimum: f32,
260 #[serde(default = "default_iridescence_thickness_max")]
262 pub iridescence_thickness_maximum: f32,
263 #[serde(default)]
264 pub iridescence_thickness_texture: Option<String>,
265 #[serde(default)]
266 pub iridescence_thickness_texture_transform: TextureTransform,
267 #[serde(default)]
269 pub sheen_color_factor: [f32; 3],
270 #[serde(default)]
271 pub sheen_color_texture: Option<String>,
272 #[serde(default)]
273 pub sheen_color_texture_transform: TextureTransform,
274 #[serde(default)]
276 pub sheen_roughness_factor: f32,
277 #[serde(default)]
278 pub sheen_roughness_texture: Option<String>,
279 #[serde(default)]
280 pub sheen_roughness_texture_transform: TextureTransform,
281 #[serde(default)]
283 pub clearcoat_factor: f32,
284 #[serde(default)]
285 pub clearcoat_texture: Option<String>,
286 #[serde(default)]
287 pub clearcoat_texture_transform: TextureTransform,
288 #[serde(default)]
290 pub clearcoat_roughness_factor: f32,
291 #[serde(default)]
292 pub clearcoat_roughness_texture: Option<String>,
293 #[serde(default)]
294 pub clearcoat_roughness_texture_transform: TextureTransform,
295 #[serde(default)]
297 pub clearcoat_normal_texture: Option<String>,
298 #[serde(default)]
299 pub clearcoat_normal_texture_transform: TextureTransform,
300 #[serde(default = "default_normal_scale")]
301 pub clearcoat_normal_scale: f32,
302}
303
304#[derive(Clone, Copy, Debug, Default)]
312pub struct MaterialTextureIds {
313 pub base: Option<TextureId>,
314 pub emissive: Option<TextureId>,
315 pub normal: Option<TextureId>,
316 pub detail_base: Option<TextureId>,
317 pub detail_normal: Option<TextureId>,
318 pub height: Option<TextureId>,
319 pub metallic_roughness: Option<TextureId>,
320 pub occlusion: Option<TextureId>,
321 pub transmission: Option<TextureId>,
322 pub thickness: Option<TextureId>,
323 pub specular: Option<TextureId>,
324 pub specular_color: Option<TextureId>,
325 pub diffuse_transmission: Option<TextureId>,
326 pub diffuse_transmission_color: Option<TextureId>,
327 pub anisotropy: Option<TextureId>,
328 pub iridescence: Option<TextureId>,
329 pub iridescence_thickness: Option<TextureId>,
330 pub sheen_color: Option<TextureId>,
331 pub sheen_roughness: Option<TextureId>,
332 pub clearcoat: Option<TextureId>,
333 pub clearcoat_roughness: Option<TextureId>,
334 pub clearcoat_normal: Option<TextureId>,
335}
336
337fn default_blend_opaque_alpha_threshold() -> f32 {
338 0.99
339}
340
341fn default_normal_scale() -> f32 {
342 1.0
343}
344
345fn default_detail_uv_scale() -> f32 {
346 4.0
347}
348
349fn default_occlusion_strength() -> f32 {
350 1.0
351}
352
353fn default_attenuation_color() -> [f32; 3] {
354 [1.0, 1.0, 1.0]
355}
356
357fn default_ior() -> f32 {
358 1.5
359}
360
361fn default_specular_factor() -> f32 {
362 1.0
363}
364
365fn default_specular_color_factor() -> [f32; 3] {
366 [1.0, 1.0, 1.0]
367}
368
369fn default_emissive_strength() -> f32 {
370 1.0
371}
372
373fn default_diffuse_transmission_color() -> [f32; 3] {
374 [1.0, 1.0, 1.0]
375}
376
377fn default_iridescence_ior() -> f32 {
378 1.3
379}
380
381fn default_iridescence_thickness_min() -> f32 {
382 100.0
383}
384
385fn default_iridescence_thickness_max() -> f32 {
386 400.0
387}
388
389impl Material {
390 pub fn is_transparent(&self) -> bool {
392 matches!(self.alpha_mode, AlphaMode::Mask | AlphaMode::Blend)
393 }
394
395 pub fn texture_names(&self) -> impl Iterator<Item = &str> {
400 [
401 self.base_texture.as_deref(),
402 self.emissive_texture.as_deref(),
403 self.normal_texture.as_deref(),
404 self.detail_base_texture.as_deref(),
405 self.detail_normal_texture.as_deref(),
406 self.height_texture.as_deref(),
407 self.metallic_roughness_texture.as_deref(),
408 self.occlusion_texture.as_deref(),
409 self.transmission_texture.as_deref(),
410 self.thickness_texture.as_deref(),
411 self.specular_texture.as_deref(),
412 self.specular_color_texture.as_deref(),
413 self.diffuse_transmission_texture.as_deref(),
414 self.diffuse_transmission_color_texture.as_deref(),
415 self.anisotropy_texture.as_deref(),
416 self.iridescence_texture.as_deref(),
417 self.iridescence_thickness_texture.as_deref(),
418 self.sheen_color_texture.as_deref(),
419 self.sheen_roughness_texture.as_deref(),
420 self.clearcoat_texture.as_deref(),
421 self.clearcoat_roughness_texture.as_deref(),
422 self.clearcoat_normal_texture.as_deref(),
423 ]
424 .into_iter()
425 .flatten()
426 }
427}
428
429impl Default for Material {
430 fn default() -> Self {
431 Self {
432 base_color: [0.7, 0.7, 0.7, 1.0],
433 emissive_factor: [0.0, 0.0, 0.0],
434 alpha_mode: AlphaMode::Opaque,
435 alpha_cutoff: 0.5,
436 blend_opaque_alpha_threshold: 0.99,
437 base_texture: None,
438 base_texture_transform: TextureTransform::IDENTITY,
439 emissive_texture: None,
440 emissive_texture_transform: TextureTransform::IDENTITY,
441 normal_texture: None,
442 normal_texture_transform: TextureTransform::IDENTITY,
443 normal_scale: 1.0,
444 normal_map_flip_y: false,
445 normal_map_two_component: false,
446 detail_base_texture: None,
447 detail_normal_texture: None,
448 detail_uv_scale: default_detail_uv_scale(),
449 height_texture: None,
450 parallax_scale: 0.0,
451 reflection_box_min: [0.0, 0.0, 0.0],
452 reflection_box_max: [0.0, 0.0, 0.0],
453 metallic_roughness_texture: None,
454 metallic_roughness_texture_transform: TextureTransform::IDENTITY,
455 occlusion_texture: None,
456 occlusion_texture_transform: TextureTransform::IDENTITY,
457 occlusion_strength: 1.0,
458 roughness: 0.5,
459 metallic: 0.0,
460 unlit: false,
461 double_sided: false,
462 transmission_factor: 0.0,
463 transmission_texture: None,
464 transmission_texture_transform: TextureTransform::IDENTITY,
465 thickness: 0.0,
466 thickness_texture: None,
467 thickness_texture_transform: TextureTransform::IDENTITY,
468 attenuation_color: [1.0, 1.0, 1.0],
469 attenuation_distance: 0.0,
470 ior: 1.5,
471 specular_factor: 1.0,
472 specular_color_factor: [1.0, 1.0, 1.0],
473 specular_texture: None,
474 specular_texture_transform: TextureTransform::IDENTITY,
475 specular_color_texture: None,
476 specular_color_texture_transform: TextureTransform::IDENTITY,
477 emissive_strength: 1.0,
478 diffuse_transmission_factor: 0.0,
479 diffuse_transmission_texture: None,
480 diffuse_transmission_texture_transform: TextureTransform::IDENTITY,
481 diffuse_transmission_color_factor: [1.0, 1.0, 1.0],
482 diffuse_transmission_color_texture: None,
483 diffuse_transmission_color_texture_transform: TextureTransform::IDENTITY,
484 dispersion: 0.0,
485 anisotropy_strength: 0.0,
486 anisotropy_rotation: 0.0,
487 anisotropy_texture: None,
488 anisotropy_texture_transform: TextureTransform::IDENTITY,
489 iridescence_factor: 0.0,
490 iridescence_texture: None,
491 iridescence_texture_transform: TextureTransform::IDENTITY,
492 iridescence_ior: 1.3,
493 iridescence_thickness_minimum: 100.0,
494 iridescence_thickness_maximum: 400.0,
495 iridescence_thickness_texture: None,
496 iridescence_thickness_texture_transform: TextureTransform::IDENTITY,
497 sheen_color_factor: [0.0, 0.0, 0.0],
498 sheen_color_texture: None,
499 sheen_color_texture_transform: TextureTransform::IDENTITY,
500 sheen_roughness_factor: 0.0,
501 sheen_roughness_texture: None,
502 sheen_roughness_texture_transform: TextureTransform::IDENTITY,
503 clearcoat_factor: 0.0,
504 clearcoat_texture: None,
505 clearcoat_texture_transform: TextureTransform::IDENTITY,
506 clearcoat_roughness_factor: 0.0,
507 clearcoat_roughness_texture: None,
508 clearcoat_roughness_texture_transform: TextureTransform::IDENTITY,
509 clearcoat_normal_texture: None,
510 clearcoat_normal_texture_transform: TextureTransform::IDENTITY,
511 clearcoat_normal_scale: 1.0,
512 }
513 }
514}