gloss_renderer/
light.rs

1extern crate nalgebra as na;
2extern crate nalgebra_glm as glm;
3
4use crate::{
5    components::{PosLookat, Projection, ShadowCaster, SpotLightBundle},
6    scene::Scene,
7};
8use gloss_hecs::Entity;
9
10/// Lights implements most of the functionality related to lights and inherits
11/// some of the components from camera also.
12pub struct Light {
13    pub entity: Entity,
14}
15
16impl Light {
17    #[allow(clippy::missing_panics_doc)] //really will never panic because the entity definitelly already exists in the
18                                         // world
19    pub fn new(name: &str, scene: &mut Scene) -> Self {
20        let entity = scene
21            .get_or_create_hidden_entity(name)
22            .insert_bundle(SpotLightBundle::default())
23            .insert(ShadowCaster::default())
24            .entity();
25
26        Self { entity }
27    }
28
29    pub fn from_entity(entity: Entity) -> Self {
30        Self { entity }
31    }
32
33    /// # Panics
34    /// Will panic if the ``PosLookat`` component does not exist for this entity
35    pub fn view_matrix(&self, scene: &Scene) -> na::Matrix4<f32> {
36        let pos_lookat = scene.get_comp::<&PosLookat>(&self.entity).unwrap();
37        pos_lookat.view_matrix()
38    }
39
40    /// # Panics
41    /// Will panic if the ``Projection`` component does not exist for this
42    /// entity
43    pub fn proj_matrix(&self, scene: &Scene) -> na::Matrix4<f32> {
44        let proj = scene.get_comp::<&Projection>(&self.entity).unwrap();
45        match *proj {
46            Projection::WithFov(ref proj) => proj.proj_matrix(),
47            Projection::WithIntrinsics(_) => {
48                panic!("We don't deal with light that have projection as intrinsics")
49            }
50        }
51    }
52
53    /// # Panics
54    /// Will panic if the ``Projection`` component does not exist for this
55    /// entity
56    pub fn proj_matrix_reverse_z(&self, scene: &Scene) -> na::Matrix4<f32> {
57        let proj = scene.get_comp::<&Projection>(&self.entity).unwrap();
58        match *proj {
59            Projection::WithFov(ref proj) => proj.proj_matrix_reverse_z(),
60            Projection::WithIntrinsics(_) => {
61                panic!("We don't deal with light that have projection as intrinsics")
62            }
63        }
64    }
65
66    /// returns the intensity the light should have so that a certain point in
67    /// space, after attenuating, receives a desired intensity of light
68    pub fn intensity_for_point(light_pos: &na::Point3<f32>, point: &na::Point3<f32>, desired_intensity_at_point: f32) -> f32 {
69        let dist = (light_pos - point).norm();
70        let attenuation = 1.0 / (dist * dist);
71        //power that the point receive is m_power*attenuation. If we want the power
72        // there to be power: power=m_power*attenuation. Therefore the intensity of the
73        // light is:
74        desired_intensity_at_point / attenuation
75    }
76}