three_d/renderer/light/
point_light.rs

1use crate::core::*;
2use crate::renderer::*;
3
4///
5/// A light which shines from the given position in all directions.
6///
7pub struct PointLight {
8    /// The intensity of the light. This allows for higher intensity than 1 which can be used to simulate high intensity light sources like the sun.
9    pub intensity: f32,
10    /// The base color of the light.
11    pub color: Srgba,
12    /// The position of the light.
13    pub position: Vec3,
14    /// The [Attenuation] of the light.
15    pub attenuation: Attenuation,
16}
17
18impl PointLight {
19    /// Constructs a new point light.
20    pub fn new(
21        _context: &Context,
22        intensity: f32,
23        color: Srgba,
24        position: Vec3,
25        attenuation: Attenuation,
26    ) -> PointLight {
27        PointLight {
28            intensity,
29            color,
30            position,
31            attenuation,
32        }
33    }
34}
35
36impl Light for PointLight {
37    fn shader_source(&self, i: u32) -> String {
38        format!(
39        "
40            uniform vec3 color{};
41            uniform vec3 attenuation{};
42            uniform vec3 position{};
43
44            vec3 calculate_lighting{}(vec3 surface_color, vec3 position, vec3 normal, vec3 view_direction, float metallic, float roughness, float occlusion)
45            {{
46                vec3 light_direction = position{} - position;
47                float distance = length(light_direction);
48                light_direction = light_direction / distance;
49
50                vec3 light_color = attenuate(color{}, attenuation{}, distance);
51                return calculate_light(light_color, light_direction, surface_color, view_direction, normal, metallic, roughness);
52            }}
53        
54        ", i, i, i, i, i, i, i)
55    }
56    fn use_uniforms(&self, program: &Program, i: u32) {
57        program.use_uniform(
58            &format!("color{}", i),
59            self.color.to_linear_srgb().truncate() * self.intensity,
60        );
61        program.use_uniform(
62            &format!("attenuation{}", i),
63            vec3(
64                self.attenuation.constant,
65                self.attenuation.linear,
66                self.attenuation.quadratic,
67            ),
68        );
69        program.use_uniform(&format!("position{}", i), self.position);
70    }
71
72    fn id(&self) -> LightId {
73        LightId::PointLight
74    }
75}