summaryrefslogtreecommitdiff
path: root/engine/src
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2024-05-22 22:42:43 +0200
committerHampusM <hampus@hampusmat.com>2024-05-22 22:42:43 +0200
commite9504a3b90ef081dcd622381694f6c51e2844c2d (patch)
tree479f1e21c892c3cfc964c139015d60840862df89 /engine/src
parentdb4017c1165b9ba02655508e615d161a4c42acf0 (diff)
feat(engine): add support for multiple point lights
Diffstat (limited to 'engine/src')
-rw-r--r--engine/src/renderer/mod.rs125
1 files changed, 71 insertions, 54 deletions
diff --git a/engine/src/renderer/mod.rs b/engine/src/renderer/mod.rs
index ad587b5..485c0bb 100644
--- a/engine/src/renderer/mod.rs
+++ b/engine/src/renderer/mod.rs
@@ -1,5 +1,5 @@
use std::collections::HashMap;
-use std::ffi::c_void;
+use std::ffi::{c_void, CString};
use std::process::abort;
use cstr::cstr;
@@ -9,7 +9,6 @@ use ecs::system::{Into as _, System};
use ecs::{Component, Query};
use crate::camera::Camera;
-use crate::color::Color;
use crate::data_types::dimens::Dimens;
use crate::event::{Present as PresentEvent, Start as StartEvent};
use crate::lighting::{GlobalLight, PointLight};
@@ -39,7 +38,7 @@ use crate::projection::{new_perspective_matrix, Projection};
use crate::shader::Program as ShaderProgram;
use crate::texture::{Id as TextureId, Texture};
use crate::transform::Transform;
-use crate::vector::{Vec2, Vec3};
+use crate::vector::Vec2;
use crate::vertex::{AttributeComponentType, Vertex};
use crate::window::Window;
@@ -119,10 +118,10 @@ fn render(
// TODO: Maybe find a way to not clone here? Cloning here is needed since a transform
// can be in both the object query and the light source query
- let point_light = point_light_query
+ let point_lights = point_light_query
.iter()
- .next()
- .map(|(point_light, transform)| (point_light.clone(), transform.clone()));
+ .map(|(point_light, transform)| ((*point_light).clone(), (*transform).clone()))
+ .collect::<Vec<_>>();
let GlObjects {
shader_programs: gl_shader_programs,
@@ -152,11 +151,7 @@ fn render(
&material_flags,
&global_light,
shader_program,
- point_light
- .as_ref()
- .map(|(point_light, point_light_transform)| {
- (point_light, point_light_transform)
- }),
+ point_lights.as_slice(),
&camera,
);
@@ -360,55 +355,27 @@ fn apply_light(
material_flags: &MaterialFlags,
global_light: &GlobalLight,
gl_shader_program: &mut GlShaderProgram,
- point_light: Option<(&PointLight, &Transform)>,
+ point_lights: &[(PointLight, Transform)],
camera: &Camera,
)
{
- gl_shader_program.set_uniform_vec_3fv(
- cstr!("light.position"),
- &point_light.map_or_else(Vec3::default, |(_, point_light_transform)| {
- point_light_transform.position
- }),
- );
-
- gl_shader_program.set_uniform_vec_3fv(
- cstr!("light.diffuse"),
- &point_light
- .map_or(Color::WHITE_F32, |(point_light, _)| {
- point_light.diffuse.clone()
- })
- .into(),
+ debug_assert!(
+ point_lights.len() < 64,
+ "Shader cannot handle more than 64 point lights"
);
- gl_shader_program.set_uniform_vec_3fv(
- cstr!("light.specular"),
- &point_light
- .map_or(Color::WHITE_F32, |(point_light, _)| {
- point_light.specular.clone()
- })
- .into(),
- );
-
- gl_shader_program.set_uniform_1fv(
- cstr!("light.constant"),
- point_light.map_or(1.0, |(light_source, _)| {
- light_source.attenuation_params.constant
- }),
- );
-
- gl_shader_program.set_uniform_1fv(
- cstr!("light.linear"),
- point_light.map_or(0.0, |(light_source, _)| {
- light_source.attenuation_params.linear
- }),
- );
+ for (point_light_index, (point_light, point_light_transform)) in
+ point_lights.iter().enumerate()
+ {
+ set_point_light_uniforms(
+ gl_shader_program,
+ point_light_index,
+ point_light,
+ point_light_transform,
+ )
+ }
- gl_shader_program.set_uniform_1fv(
- cstr!("light.quadratic"),
- point_light.map_or(0.0, |(light_source, _)| {
- light_source.attenuation_params.quadratic
- }),
- );
+ gl_shader_program.set_uniform_1i(cstr!("point_light_cnt"), point_lights.len() as i32);
gl_shader_program.set_uniform_vec_3fv(
cstr!("material.ambient"),
@@ -452,6 +419,56 @@ fn apply_light(
gl_shader_program.set_uniform_vec_3fv(cstr!("view_pos"), &camera.position);
}
+fn set_point_light_uniforms(
+ gl_shader_program: &mut GlShaderProgram,
+ point_light_index: usize,
+ point_light: &PointLight,
+ point_light_transform: &Transform,
+)
+{
+ gl_shader_program.set_uniform_vec_3fv(
+ &create_point_light_uniform_name(point_light_index, "position"),
+ &point_light_transform.position,
+ );
+
+ gl_shader_program.set_uniform_vec_3fv(
+ &create_point_light_uniform_name(point_light_index, "diffuse"),
+ &point_light.diffuse.clone().into(),
+ );
+
+ gl_shader_program.set_uniform_vec_3fv(
+ &create_point_light_uniform_name(point_light_index, "specular"),
+ &point_light.specular.clone().into(),
+ );
+
+ gl_shader_program.set_uniform_1fv(
+ &create_point_light_uniform_name(point_light_index, "constant"),
+ point_light.attenuation_params.constant,
+ );
+
+ gl_shader_program.set_uniform_1fv(
+ &create_point_light_uniform_name(point_light_index, "linear"),
+ point_light.attenuation_params.linear,
+ );
+
+ gl_shader_program.set_uniform_1fv(
+ &create_point_light_uniform_name(point_light_index, "quadratic"),
+ point_light.attenuation_params.quadratic,
+ );
+}
+
+fn create_point_light_uniform_name(
+ point_light_index: usize,
+ point_light_field: &str,
+) -> CString
+{
+ unsafe {
+ CString::from_vec_with_nul_unchecked(
+ format!("point_lights[{point_light_index}].{point_light_field}\0").into(),
+ )
+ }
+}
+
fn create_view(camera: &Camera) -> Matrix<f32, 4, 4>
{
let mut view = Matrix::new();