1use crate::*;
2
3static LIGHTS: Lazy<AtomicRefCell<LightingState>> =
4 Lazy::new(|| AtomicRefCell::new(LightingState::default()));
5
6#[derive(Default)]
7pub struct LightingState {
8 pub lights: Vec<Light>,
9}
10
11impl LightingState {
12 pub fn begin_frame() {
13 LIGHTS.borrow_mut().lights.clear();
14 }
15
16 pub fn take_lights() -> Vec<Light> {
17 LIGHTS.borrow_mut().lights.clone()
18 }
19}
20
21pub fn draw_light(light: Light) {
22 LIGHTS.borrow_mut().lights.push(light);
23}
24
25pub fn light_count() -> usize {
26 LIGHTS.borrow().lights.len()
27}
28
29pub struct PointLight {
30 pub radius: f32,
31 pub radius_mod: f32,
32 pub strength: f32,
33 pub strength_mod: f32,
34 pub color: Color,
35}
36
37#[derive(Copy, Clone, Debug, Default, bytemuck::Pod, bytemuck::Zeroable)]
38#[repr(C)]
39pub struct Light {
40 pub color: Color,
41 pub world_position: [f32; 2],
42 pub screen_position: [f32; 2],
43 pub radius: f32,
44 pub strength: f32,
45 pub _padding: [f32; 2],
46}
47
48impl Light {
49 pub fn simple(world_position: Vec2, radius: f32, strength: f32) -> Self {
50 Self {
51 color: WHITE,
52 world_position: world_position.as_array(),
53 screen_position: Vec2::ZERO.as_array(),
54 radius,
55 strength,
56 _padding: [0.0; 2],
57 }
58 }
59}
60
61pub const MAX_LIGHTS: usize = 128;
62
63#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
64#[repr(C)]
65pub struct LightUniform {
66 pub lights: [Light; 128],
67 pub num_lights: i32,
68 _padding: [f32; 3],
69}
70
71impl Default for LightUniform {
72 fn default() -> Self {
73 Self {
74 lights: [Light::default(); 128],
75 num_lights: 0,
76 _padding: [0.0; 3],
77 }
78 }
79}
80
81#[repr(C)]
82#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
83pub struct GlobalLightingParams {
84 pub ambient_light_color: [f32; 4],
85 pub ambient_light_intensity: f32,
86 pub quadratic_falloff: u32,
87 pub lighting_enabled: u32,
88 pub shadow_strength: f32,
89 pub fog_color: [f32; 4],
90 pub film_grain_strength: f32,
91 pub noise_strength: f32,
92 pub light_blending_mode: u32,
93 pub global_light_intensity: f32,
94 pub global_light_color: [f32; 4],
95 pub vignette_color: [f32; 4],
96 pub vignette_intensity: f32,
97 pub vignette_radius: f32,
98 pub shake_amount: f32,
99 pub time: f32,
100 pub color_balance: [f32; 4],
101 pub global_brightness: f32,
102 pub debug_visualization: u32,
103 pub gamma_correction: f32,
104 pub use_lut: u32,
105
106 pub exposure: f32,
108
109 pub gamma: f32,
111
112 pub pre_saturation: f32,
117
118 pub post_saturation: f32,
123
124 pub resolution: [f32; 2],
125 pub chromatic_aberration: f32,
126 pub bloom_threshold: f32,
127 pub bloom_lerp: f32,
128 pub bloom_gamma: f32,
129 pub _padding: [f32; 2],
130}
131
132impl Default for GlobalLightingParams {
133 fn default() -> Self {
134 GlobalLightingParams {
135 ambient_light_color: [1.0, 1.0, 1.0, 1.0],
136 ambient_light_intensity: 1.0,
137 quadratic_falloff: 0,
138 lighting_enabled: 1,
139 shadow_strength: 1.0,
140 fog_color: [0.5, 0.5, 0.5, 1.0],
141 film_grain_strength: 0.5,
142 noise_strength: 0.2,
143 light_blending_mode: 0,
144 global_light_intensity: 1.0,
145 global_light_color: [1.0, 1.0, 1.0, 1.0],
146 vignette_color: [0.0, 0.0, 0.0, 1.0],
147 vignette_intensity: 0.5,
148 vignette_radius: 1.0,
149 color_balance: [1.0, 1.0, 1.0, 1.0],
150 global_brightness: 1.0,
151 debug_visualization: 0,
152 gamma_correction: 1.0,
153 use_lut: 0,
154 shake_amount: 0.0,
155 time: 0.0,
156
157 exposure: 0.0,
158 gamma: 1.0,
159 pre_saturation: 1.0,
160 post_saturation: 1.0,
161
162 resolution: [1920.0, 1080.0],
163 chromatic_aberration: 0.0,
164 bloom_threshold: 0.8,
165 bloom_lerp: 0.3,
166 bloom_gamma: 1.0,
167 _padding: [0.0; 2],
168 }
169 }
170}
171
172pub fn lighting_ui(
173 params: &mut GlobalLightingParams,
174 ui: &mut egui::Ui,
175) -> bool {
176 let mut changed = false;
177
178 changed |= field_editor(
179 ui,
180 "Chromatic Aberration",
181 &mut params.chromatic_aberration,
182 );
183
184 changed |= field_editor(ui, "Bloom Threshold", &mut params.bloom_threshold);
185 changed |= field_editor(ui, "Bloom Lerp", &mut params.bloom_lerp);
186 changed |= field_editor(ui, "Bloom Gamma", &mut params.bloom_gamma);
187
188 changed |= field_editor(ui, "Exposure", &mut params.exposure);
189 changed |= field_editor(ui, "Gamma", &mut params.gamma);
190 changed |= field_editor(ui, "Pre-Saturation", &mut params.pre_saturation);
191 changed |= field_editor(ui, "Post-Saturation", &mut params.post_saturation);
192
193 changed |= field_editor(ui, "Shake Amount", &mut params.shake_amount);
194
195 changed |= field_editor_vec4(
196 ui,
197 "Ambient Light Color",
198 &mut params.ambient_light_color,
199 );
200 changed |= field_editor(
201 ui,
202 "Ambient Light Intensity",
203 &mut params.ambient_light_intensity,
204 );
205 changed |=
206 field_editor(ui, "Quadratic Falloff", &mut params.quadratic_falloff);
207
208 changed |=
209 field_editor(ui, "Light Blend Mode", &mut params.light_blending_mode);
210 changed |= field_editor(
211 ui,
212 "Global Light Intensity",
213 &mut params.global_light_intensity,
214 );
215 changed |= field_editor_vec4(
216 ui,
217 "Global Light Color",
218 &mut params.global_light_color,
219 );
220
221 changed |=
222 field_editor(ui, "Lighting Enabled", &mut params.lighting_enabled);
223 changed |= field_editor(ui, "Shadow Strength", &mut params.shadow_strength);
224 changed |= field_editor_vec4(ui, "Fog Color", &mut params.fog_color);
225 changed |= field_editor(
226 ui,
227 "Film Grain Strength",
228 &mut params.film_grain_strength,
229 );
230 changed |= field_editor(ui, "Noise Strength", &mut params.noise_strength);
231 changed |= field_editor(
232 ui,
233 "Debug Visualization",
234 &mut params.debug_visualization,
235 );
236
237 changed |=
238 field_editor_vec4(ui, "Vignette Color", &mut params.vignette_color);
239 changed |=
240 field_editor(ui, "Vignette Intensity", &mut params.vignette_intensity);
241 changed |= field_editor(ui, "Vignette Radius", &mut params.vignette_radius);
242 changed |=
243 field_editor_vec4(ui, "Color Balance", &mut params.color_balance);
244 changed |=
245 field_editor(ui, "Global Brightness", &mut params.global_brightness);
246 changed |=
247 field_editor(ui, "Gamma Correction", &mut params.gamma_correction);
248 changed |= field_editor(ui, "Use LUT", &mut params.use_lut);
249
250 changed
251}
252
253fn field_editor_vec4(
254 ui: &mut egui::Ui,
255 label: &str,
256 field: &mut [f32; 4],
257) -> bool {
258 let mut changed = false;
259 ui.horizontal(|ui| {
260 ui.label(label);
261 ui.vertical(|ui| {
262 let labels = ["X", "Y", "Z", "W"];
263 ui.horizontal(|ui| {
264 for (i, value) in field.iter_mut().enumerate() {
265 let value_changed = ui
266 .add(
267 egui::DragValue::new(value)
268 .speed(0.01)
269 .clamp_range(0.0..=1.0)
270 .prefix(labels[i]),
271 )
272 .changed();
273 changed |= value_changed;
274 }
275 });
276 });
277 });
278 changed
279}
280
281fn field_editor<T>(ui: &mut egui::Ui, label: &str, field: &mut T) -> bool
282where T: Clone + PartialEq + 'static + egui::emath::Numeric {
283 let mut changed = false;
284
285 ui.horizontal(|ui| {
286 ui.label(label);
287 changed = ui.add(egui::DragValue::new(field).speed(0.01)).changed();
288 });
289
290 changed
291}