Skip to main content

concinnity_asset/
directional_light.rs

1// Directional-light schema.
2
3/// An infinitely distant directional light (sun, moon, or sky fill).
4///
5/// Up to 4 directional lights may be declared; extras beyond 4 are silently ignored.
6/// When no directional light is present, a built-in warm sun is used as a fallback.
7///
8/// ```rust
9/// # use concinnity_asset::DirectionalLight;
10/// DirectionalLight {
11///     direction: [-0.3, 0.85, 0.4],
12///     color: [1.0, 0.95, 0.8],
13///     intensity: 1.0,
14///     ..Default::default()
15/// };
16/// ```
17#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
18#[serde(default)]
19pub struct DirectionalLight {
20    /// Direction pointing toward the light source. Does not need to be
21    /// normalised.
22    pub direction: [f32; 3],
23    /// Linear-space RGB colour of the light.
24    pub color: [f32; 3],
25    /// Intensity multiplier applied to the colour.
26    pub intensity: f32,
27}
28
29impl Default for DirectionalLight {
30    fn default() -> Self {
31        Self {
32            direction: [-0.3, 0.85, 0.4],
33            color: [1.0, 1.0, 1.0],
34            intensity: 1.0,
35        }
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42
43    #[test]
44    fn the_default_sun_points_down_from_above() {
45        // The direction is toward the light, so a positive Y component is what
46        // makes the default read as an overhead sun rather than an uplight.
47        let l = DirectionalLight::default();
48        assert!(l.direction[1] > 0.0);
49        assert_eq!(l.color, [1.0, 1.0, 1.0]);
50        assert_eq!(l.intensity, 1.0);
51    }
52
53    #[test]
54    fn an_authored_sun_parses_and_round_trips_through_postcard() {
55        let l: DirectionalLight =
56            serde_json::from_str(r#"{"direction":[0,1,0],"color":[1,0.9,0.7],"intensity":3}"#)
57                .unwrap();
58        assert_eq!(l.direction, [0.0, 1.0, 0.0]);
59        assert_eq!(l.color, [1.0, 0.9, 0.7]);
60        assert_eq!(l.intensity, 3.0);
61
62        let bytes = postcard::to_allocvec(&l).unwrap();
63        let back: DirectionalLight = postcard::from_bytes(&bytes).unwrap();
64        assert_eq!(back.color, [1.0, 0.9, 0.7]);
65        assert_eq!(back.intensity, 3.0);
66    }
67}