Skip to main content

enigma_3d/
light.rs

1use glium::implement_uniform_block;
2use serde::{Deserialize, Serialize};
3
4pub enum LightEmissionType {
5    Source,
6    Ambient,
7}
8
9pub enum ShadowResolution {
10    Low,
11    Medium,
12    High,
13    Ultra,
14    Custom(u32),
15}
16
17impl ShadowResolution {
18    pub fn value(&self) -> u32 {
19        match self {
20            ShadowResolution::Low => 512,
21            ShadowResolution::Medium => 1024,
22            ShadowResolution::High => 2048,
23            ShadowResolution::Ultra => 4096,
24            ShadowResolution::Custom(v) => *v,
25        }
26    }
27}
28
29#[derive(Serialize, Deserialize)]
30pub struct LightSerializer {
31    pub position: [f32; 3],
32    pub color: [f32; 3],
33    pub intensity: f32,
34    pub direction: [f32; 3],
35    pub cast_shadow: bool,
36}
37
38#[derive(Copy, Clone)]
39pub struct Light {
40    pub position: [f32; 3],
41    pub color: [f32; 3],
42    pub intensity: f32,
43    pub direction: [f32; 3],
44    pub cast_shadow: bool
45}
46
47impl Light {
48    pub fn new(position: [f32; 3], color: [f32; 3], intensity: f32, direction: Option<[f32;3]>, cast_shadow: bool) -> Self {
49        Self {
50            position,
51            color,
52            intensity,
53            direction : direction.unwrap_or_else(|| [0.0, 0.0, 0.0]),
54            cast_shadow,
55        }
56    }
57
58    pub fn default() -> Self {
59        Light::new([0.0, 0.0, 0.0], [1.0, 1.0, 1.0], 1.0, None, true)
60    }
61
62    pub fn is_directional(&self) -> bool {
63        self.direction != [0.0, 0.0, 0.0]
64    }
65
66    pub fn from_serializer(serializer: LightSerializer) -> Self {
67        Self {
68            position: serializer.position,
69            color: serializer.color,
70            intensity: serializer.intensity,
71            direction: serializer.direction,
72            cast_shadow: serializer.cast_shadow,
73        }
74    }
75
76    pub fn to_serializer(&self) -> LightSerializer {
77        LightSerializer {
78            position: self.position,
79            color: self.color,
80            intensity: self.intensity,
81            direction: self.direction,
82            cast_shadow: self.cast_shadow,
83        }
84    }
85}
86
87pub struct LightBlock {
88    pub position: [[f32; 4]; 4],
89    pub directions: [[f32; 4]; 4],
90    pub color: [[f32; 4]; 4],
91    pub intensity: [f32; 4],
92    pub cast_shadow: [i32; 4],
93    pub amount: i32,
94    pub ambient_color: [f32; 3],
95    pub ambient_intensity: f32,
96}
97
98impl std::fmt::Debug for LightBlock {
99    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
100        f.debug_struct("LightBlock")
101            .field("position", &self.position)
102            .field("color", &self.color)
103            .field("intensity", &self.intensity)
104            .field("amount", &self.amount)
105            .field("ambient_color", &self.ambient_color)
106            .finish()
107    }
108}
109
110glium::implement_uniform_block!(Light, position, color, intensity, direction, cast_shadow);
111glium::implement_uniform_block!(LightBlock, position, directions, cast_shadow, color, intensity, amount, ambient_color, ambient_intensity);
112
113#[cfg(test)]
114mod tests {
115    use super::*;
116
117    #[test]
118    fn shadow_resolution_values() {
119        assert_eq!(ShadowResolution::Low.value(), 512);
120        assert_eq!(ShadowResolution::Medium.value(), 1024);
121        assert_eq!(ShadowResolution::High.value(), 2048);
122        assert_eq!(ShadowResolution::Ultra.value(), 4096);
123        assert_eq!(ShadowResolution::Custom(333).value(), 333);
124    }
125}