three_d/renderer/
light.rs1macro_rules! impl_light_body {
8 ($inner:ident) => {
9 fn shader_source(&self, i: u32) -> String {
10 self.$inner().shader_source(i)
11 }
12 fn use_uniforms(&self, program: &Program, i: u32) {
13 self.$inner().use_uniforms(program, i)
14 }
15 fn id(&self) -> LightId {
16 self.$inner().id()
17 }
18 };
19}
20
21mod directional_light;
22use std::ops::Deref;
23
24#[doc(inline)]
25pub use directional_light::*;
26
27mod spot_light;
28#[doc(inline)]
29pub use spot_light::*;
30
31mod point_light;
32#[doc(inline)]
33pub use point_light::*;
34
35mod ambient_light;
36#[doc(inline)]
37pub use ambient_light::*;
38
39mod environment;
40#[doc(inline)]
41pub use environment::*;
42
43use crate::core::*;
44use crate::renderer::viewer::*;
45use crate::renderer::LightId;
46
47#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
52pub struct Attenuation {
53 pub constant: f32,
55 pub linear: f32,
57 pub quadratic: f32,
59}
60
61impl Default for Attenuation {
62 fn default() -> Self {
63 Self {
64 constant: 1.0,
65 linear: 0.0,
66 quadratic: 0.0,
67 }
68 }
69}
70
71pub trait Light {
73 fn shader_source(&self, i: u32) -> String;
79
80 fn use_uniforms(&self, program: &Program, i: u32);
82
83 fn id(&self) -> LightId;
90}
91
92impl<T: Light + ?Sized> Light for &T {
93 impl_light_body!(deref);
94}
95
96impl<T: Light + ?Sized> Light for &mut T {
97 impl_light_body!(deref);
98}
99
100impl<T: Light> Light for Box<T> {
101 impl_light_body!(as_ref);
102}
103
104impl<T: Light> Light for std::rc::Rc<T> {
105 impl_light_body!(as_ref);
106}
107
108impl<T: Light> Light for std::sync::Arc<T> {
109 impl_light_body!(as_ref);
110}
111
112impl<T: Light> Light for std::cell::RefCell<T> {
113 impl_light_body!(borrow);
114}
115
116impl<T: Light> Light for std::sync::Arc<std::sync::RwLock<T>> {
117 fn shader_source(&self, i: u32) -> String {
118 self.read().unwrap().shader_source(i)
119 }
120 fn use_uniforms(&self, program: &Program, i: u32) {
121 self.read().unwrap().use_uniforms(program, i)
122 }
123 fn id(&self) -> LightId {
124 self.read().unwrap().id()
125 }
126}
127
128pub fn lights_shader_source(lights: &[&dyn Light]) -> String {
138 let mut shader_source = include_str!("../core/shared.frag").to_string();
139 shader_source.push_str(include_str!("light/shaders/light_shared.frag"));
140 let mut dir_fun = String::new();
141 for (i, light) in lights.iter().enumerate() {
142 shader_source.push_str(&light.shader_source(i as u32));
143 dir_fun.push_str(&format!("color += calculate_lighting{}(surface_color, position, normal, view_direction, metallic, roughness, occlusion);\n", i))
144 }
145 shader_source.push_str(&format!(
146 "
147 vec3 calculate_lighting(vec3 camera_position, vec3 surface_color, vec3 position, vec3 normal, float metallic, float roughness, float occlusion)
148 {{
149 vec3 color = vec3(0.0, 0.0, 0.0);
150 vec3 view_direction = normalize(camera_position - position);
151 {}
152 return color;
153 }}
154 ",
155 &dir_fun
156 ));
157 shader_source
158}
159
160fn shadow_matrix(camera: &Camera) -> Mat4 {
161 let bias_matrix = crate::Mat4::new(
162 0.5, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.5, 0.5, 0.5, 1.0,
163 );
164 bias_matrix * camera.projection() * camera.view()
165}
166
167fn compute_up_direction(direction: Vec3) -> Vec3 {
168 if vec3(1.0, 0.0, 0.0).dot(direction).abs() > 0.9 {
169 (vec3(0.0, 1.0, 0.0).cross(direction)).normalize()
170 } else {
171 (vec3(1.0, 0.0, 0.0).cross(direction)).normalize()
172 }
173}
174
175use crate::renderer::{GeometryFunction, LightingModel, NormalDistributionFunction};
176pub(crate) fn lighting_model_to_id(model: LightingModel) -> u32 {
177 match model {
178 LightingModel::Phong => 1,
179 LightingModel::Blinn => 2,
180 LightingModel::Cook(
181 NormalDistributionFunction::Blinn,
182 GeometryFunction::SmithSchlickGGX,
183 ) => 3,
184 LightingModel::Cook(
185 NormalDistributionFunction::Beckmann,
186 GeometryFunction::SmithSchlickGGX,
187 ) => 4,
188 LightingModel::Cook(
189 NormalDistributionFunction::TrowbridgeReitzGGX,
190 GeometryFunction::SmithSchlickGGX,
191 ) => 5,
192 }
193}