From e9504a3b90ef081dcd622381694f6c51e2844c2d Mon Sep 17 00:00:00 2001 From: HampusM Date: Wed, 22 May 2024 22:42:43 +0200 Subject: feat(engine): add support for multiple point lights --- engine/src/renderer/mod.rs | 125 +++++++++++++++++++++++++-------------------- 1 file changed, 71 insertions(+), 54 deletions(-) (limited to 'engine/src/renderer/mod.rs') 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::>(); 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 { let mut view = Matrix::new(); -- cgit v1.2.3-18-g5258