summaryrefslogtreecommitdiff
path: root/engine
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
parentf47ce90430f36e74d713e22781a34f89149f7ea5 (diff)
feat(engine): add directional light
Diffstat (limited to 'engine')
-rw-r--r--engine/fragment.glsl51
-rw-r--r--engine/light.glsl36
-rw-r--r--engine/src/lighting.rs21
-rw-r--r--engine/src/renderer/opengl.rs159
4 files changed, 212 insertions, 55 deletions
diff --git a/engine/fragment.glsl b/engine/fragment.glsl
index cc46f36..5bf5ff2 100644
--- a/engine/fragment.glsl
+++ b/engine/fragment.glsl
@@ -3,7 +3,7 @@
#preinclude "light.glsl"
#preinclude "vertex_data.glsl"
-#define MAX_POINT_LIGHT_CNT 64
+#define MAX_LIGHT_CNT 64
out vec4 FragColor;
@@ -12,23 +12,62 @@ in VertexData vertex_data;
uniform vec3 view_pos;
uniform sampler2D input_texture;
uniform Material material;
-uniform PointLight point_lights[MAX_POINT_LIGHT_CNT];
+
+uniform PointLight point_lights[MAX_LIGHT_CNT];
uniform int point_light_cnt;
+uniform DirectionalLight directional_lights[MAX_LIGHT_CNT];
+uniform int directional_light_cnt;
+
void main()
{
vec3 ambient_light = calc_ambient_light(material, vertex_data.texture_coords);
+ vec3 directional_light_sum = vec3(0.0, 0.0, 0.0);
+
+ for (int dl_index = 0; dl_index < directional_light_cnt; dl_index++) {
+ CalculatedLight calculated_dir_light;
+
+ calc_light(
+ // Negated since we want the light to point from the light direction
+ normalize(-directional_lights[dl_index].direction),
+ directional_lights[dl_index].phong,
+ vertex_data,
+ view_pos,
+ material,
+ calculated_dir_light
+ );
+
+ directional_light_sum +=
+ calculated_dir_light.diffuse + calculated_dir_light.specular;
+ }
+
vec3 point_light_sum = vec3(0.0, 0.0, 0.0);
for (int pl_index = 0; pl_index < point_light_cnt; pl_index++) {
- point_light_sum += calc_point_light(
- point_lights[pl_index],
+ vec3 light_direction =
+ normalize(point_lights[pl_index].position - vertex_data.world_space_pos);
+
+ CalculatedLight calculated_point_light;
+
+ calc_light(
+ light_direction,
+ point_lights[pl_index].phong,
vertex_data,
view_pos,
- material
+ material,
+ calculated_point_light
);
+
+ float attenuation =
+ calc_attenuation(point_lights[pl_index], vertex_data.world_space_pos);
+
+ calculated_point_light.diffuse *= attenuation;
+ calculated_point_light.specular *= attenuation;
+
+ point_light_sum +=
+ calculated_point_light.diffuse + calculated_point_light.specular;
}
- FragColor = vec4((ambient_light + point_light_sum), 1.0);
+ FragColor = vec4((ambient_light + directional_light_sum + point_light_sum), 1.0);
}
diff --git a/engine/light.glsl b/engine/light.glsl
index 92d3ec3..1bc23a4 100644
--- a/engine/light.glsl
+++ b/engine/light.glsl
@@ -36,6 +36,18 @@ struct PointLight
AttenuationProperties attenuation_props;
};
+struct DirectionalLight
+{
+ LightPhong phong;
+ vec3 direction;
+};
+
+struct CalculatedLight
+{
+ vec3 diffuse;
+ vec3 specular;
+};
+
vec3 calc_ambient_light(in Material material, in vec2 texture_coords)
{
return vec3(texture(material.ambient_map, texture_coords)) * material.ambient;
@@ -88,40 +100,34 @@ float calc_attenuation(in PointLight point_light, in vec3 position)
* pow(light_distance, 2));
}
-vec3 calc_point_light(
- in PointLight light,
+void calc_light(
+ in vec3 light_direction,
+ in LightPhong light_phong,
in VertexData vertex_data,
in vec3 view_pos,
- in Material material
+ in Material material,
+ out CalculatedLight calculated_light
)
{
- vec3 light_direction = normalize(light.position - vertex_data.world_space_pos);
vec3 norm = normalize(vertex_data.world_space_normal);
- vec3 diffuse_light = calc_diffuse_light(
+ calculated_light.diffuse = calc_diffuse_light(
material,
- light.phong,
+ light_phong,
light_direction,
norm,
vertex_data.texture_coords
);
- vec3 specular_light = calc_specular_light(
+ calculated_light.specular = calc_specular_light(
material,
- light.phong,
+ light_phong,
light_direction,
norm,
view_pos,
vertex_data.world_space_pos,
vertex_data.texture_coords
);
-
- float attenuation = calc_attenuation(light, vertex_data.world_space_pos);
-
- diffuse_light *= attenuation;
- specular_light *= attenuation;
-
- return diffuse_light + specular_light;
}
#endif
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(),
)
}
}