diff options
author | HampusM <hampus@hampusmat.com> | 2024-05-23 22:47:30 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2024-05-23 22:47:30 +0200 |
commit | 36886e343781bf0ddf7458d5c6db5b5724c918e4 (patch) | |
tree | ac99b294c57f9646ad100b00da719fa870b4efd9 /engine/src | |
parent | f47ce90430f36e74d713e22781a34f89149f7ea5 (diff) |
feat(engine): add directional light
Diffstat (limited to 'engine/src')
-rw-r--r-- | engine/src/lighting.rs | 21 | ||||
-rw-r--r-- | engine/src/renderer/opengl.rs | 159 |
2 files changed, 146 insertions, 34 deletions
diff --git a/engine/src/lighting.rs b/engine/src/lighting.rs index ffa2645..398161f 100644 --- a/engine/src/lighting.rs +++ b/engine/src/lighting.rs @@ -1,6 +1,7 @@ use ecs::{Component, Sole}; use crate::color::Color; +use crate::data_types::vector::Vec3; use crate::util::builder; builder! { @@ -65,6 +66,26 @@ impl Default for AttenuationParams } builder! { +#[builder(name = DirectionalLightBuilder, derives = (Debug, Default, Clone))] +#[derive(Debug, Default, Clone, Component)] +#[non_exhaustive] +pub struct DirectionalLight +{ + pub diffuse: Color<f32>, + pub specular: Color<f32>, + pub direction: Vec3<f32>, +} +} + +impl DirectionalLight +{ + pub fn builder() -> DirectionalLightBuilder + { + DirectionalLightBuilder::default() + } +} + +builder! { /// Global light properties. #[builder(name = GlobalLightBuilder, derives = (Debug, Clone, Default))] #[derive(Debug, Clone, Default, Sole)] diff --git a/engine/src/renderer/opengl.rs b/engine/src/renderer/opengl.rs index 89f920c..3fe3388 100644 --- a/engine/src/renderer/opengl.rs +++ b/engine/src/renderer/opengl.rs @@ -11,9 +11,10 @@ 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}; +use crate::lighting::{DirectionalLight, GlobalLight, PointLight}; use crate::material::{Flags as MaterialFlags, Material}; use crate::matrix::Matrix; use crate::mesh::Mesh; @@ -100,6 +101,7 @@ fn render( Transform, )>, point_light_query: Query<(PointLight, Transform)>, + directional_lights: Query<(DirectionalLight,)>, camera_query: Query<(Camera,)>, window: Single<Window>, global_light: Single<GlobalLight>, @@ -125,6 +127,8 @@ fn render( .map(|(point_light, transform)| ((*point_light).clone(), (*transform).clone())) .collect::<Vec<_>>(); + let directional_lights = directional_lights.iter().collect::<Vec<_>>(); + let GlObjects { shader_programs: gl_shader_programs, textures: gl_textures, @@ -154,6 +158,11 @@ fn render( &global_light, shader_program, point_lights.as_slice(), + directional_lights + .iter() + .map(|(dir_light,)| &**dir_light) + .collect::<Vec<_>>() + .as_slice(), &camera, ); @@ -358,6 +367,7 @@ fn apply_light( global_light: &GlobalLight, gl_shader_program: &mut GlShaderProgram, point_lights: &[(PointLight, Transform)], + directional_lights: &[&DirectionalLight], camera: &Camera, ) { @@ -366,15 +376,55 @@ fn apply_light( "Shader cannot handle more than 64 point lights" ); + debug_assert!( + directional_lights.len() < 64, + "Shader cannot handle more than 64 directional lights" + ); + + for (dir_light_index, dir_light) in directional_lights.iter().enumerate() { + gl_shader_program.set_uniform_vec_3fv( + &create_light_uniform_name( + "directional_lights", + dir_light_index, + "direction", + ), + &dir_light.direction, + ); + + set_light_phong_uniforms( + gl_shader_program, + "directional_lights", + dir_light_index, + *dir_light, + ); + } + + gl_shader_program.set_uniform_1i( + cstr!("directional_light_cnt"), + directional_lights.len() as i32, + ); + for (point_light_index, (point_light, point_light_transform)) in point_lights.iter().enumerate() { - set_point_light_uniforms( + gl_shader_program.set_uniform_vec_3fv( + &create_light_uniform_name("point_lights", point_light_index, "position"), + &point_light_transform.position, + ); + + set_light_phong_uniforms( gl_shader_program, + "point_lights", point_light_index, point_light, - point_light_transform, - ) + ); + + set_light_attenuation_uniforms( + gl_shader_program, + "point_lights", + point_light_index, + point_light, + ); } gl_shader_program.set_uniform_1i(cstr!("point_light_cnt"), point_lights.len() as i32); @@ -421,55 +471,96 @@ fn apply_light( gl_shader_program.set_uniform_vec_3fv(cstr!("view_pos"), &camera.position); } -fn set_point_light_uniforms( +fn set_light_attenuation_uniforms( gl_shader_program: &mut GlShaderProgram, - point_light_index: usize, - point_light: &PointLight, - point_light_transform: &Transform, + light_array: &str, + light_index: usize, + light: &PointLight, ) { - 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, "phong.diffuse"), - &point_light.diffuse.clone().into(), - ); - - gl_shader_program.set_uniform_vec_3fv( - &create_point_light_uniform_name(point_light_index, "phong.specular"), - &point_light.specular.clone().into(), - ); - gl_shader_program.set_uniform_1fv( - &create_point_light_uniform_name(point_light_index, "attenuation_props.constant"), - point_light.attenuation_params.constant, + &create_light_uniform_name( + light_array, + light_index, + "attenuation_props.constant", + ), + light.attenuation_params.constant, ); gl_shader_program.set_uniform_1fv( - &create_point_light_uniform_name(point_light_index, "attenuation_props.linear"), - point_light.attenuation_params.linear, + &create_light_uniform_name(light_array, light_index, "attenuation_props.linear"), + light.attenuation_params.linear, ); gl_shader_program.set_uniform_1fv( - &create_point_light_uniform_name( - point_light_index, + &create_light_uniform_name( + light_array, + light_index, "attenuation_props.quadratic", ), - point_light.attenuation_params.quadratic, + light.attenuation_params.quadratic, + ); +} + +fn set_light_phong_uniforms( + gl_shader_program: &mut GlShaderProgram, + light_array: &str, + light_index: usize, + light: &impl Light, +) +{ + gl_shader_program.set_uniform_vec_3fv( + &create_light_uniform_name(light_array, light_index, "phong.diffuse"), + &light.diffuse().clone().into(), + ); + + gl_shader_program.set_uniform_vec_3fv( + &create_light_uniform_name(light_array, light_index, "phong.specular"), + &light.specular().clone().into(), ); } -fn create_point_light_uniform_name( - point_light_index: usize, - point_light_field: &str, +trait Light +{ + fn diffuse(&self) -> &Color<f32>; + fn specular(&self) -> &Color<f32>; +} + +impl Light for PointLight +{ + fn diffuse(&self) -> &Color<f32> + { + &self.diffuse + } + + fn specular(&self) -> &Color<f32> + { + &self.specular + } +} + +impl Light for DirectionalLight +{ + fn diffuse(&self) -> &Color<f32> + { + &self.diffuse + } + + fn specular(&self) -> &Color<f32> + { + &self.specular + } +} + +fn create_light_uniform_name( + light_array: &str, + light_index: usize, + light_field: &str, ) -> CString { unsafe { CString::from_vec_with_nul_unchecked( - format!("point_lights[{point_light_index}].{point_light_field}\0").into(), + format!("{light_array}[{light_index}].{light_field}\0").into(), ) } } |