summaryrefslogtreecommitdiff
path: root/engine/src
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2024-05-23 22:47:30 +0200
committerHampusM <hampus@hampusmat.com>2024-05-23 22:47:30 +0200
commit36886e343781bf0ddf7458d5c6db5b5724c918e4 (patch)
treeac99b294c57f9646ad100b00da719fa870b4efd9 /engine/src
parentf47ce90430f36e74d713e22781a34f89149f7ea5 (diff)
feat(engine): add directional light
Diffstat (limited to 'engine/src')
-rw-r--r--engine/src/lighting.rs21
-rw-r--r--engine/src/renderer/opengl.rs159
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(),
)
}
}