From 97a7501cdadfa4ce85afbb775a25828ab50e72a6 Mon Sep 17 00:00:00 2001 From: Menno Date: Fri, 21 May 2021 16:25:39 +0200 Subject: [PATCH] [FEATURE] multiple light support --- src/entities/light.h | 5 ++ src/main.cpp | 11 +++-- src/shaders/entity_shader.cpp | 91 +++++++++++++++++++++++++---------- src/shaders/entity_shader.h | 14 ++++-- 4 files changed, 87 insertions(+), 34 deletions(-) diff --git a/src/entities/light.h b/src/entities/light.h index 7e6dfce..a2b6b25 100644 --- a/src/entities/light.h +++ b/src/entities/light.h @@ -13,13 +13,18 @@ namespace entities private: glm::vec3 position; glm::vec3 color; + glm::vec3 attenuation = { 1, 0, 0 }; public: Light(const glm::vec3& position, const glm::vec3& color) : position(position), color(color) { } + Light(const glm::vec3& position, const glm::vec3& color, const glm::vec3& attenuation) + : position(position), color(color), attenuation(attenuation) { } glm::vec3 GetPosition() const { return position; } void setPosition(const glm::vec3& position) { this->position = position; } glm::vec3 GetColor() const { return color; } void setColor(const glm::vec3& color) { this->color = color; } + glm::vec3 GetAttenuation() const { return attenuation; } + void SetAttenuation(const glm::vec3& attenuation) { this->attenuation = attenuation; } }; } diff --git a/src/main.cpp b/src/main.cpp index 372e299..adf61f2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -63,9 +63,12 @@ int main(void) z += (raw_model.model_size.x * 20); } - entities::Light light(glm::vec3(0, 0, -30), glm::vec3(1, 1, 1)); - - shaders::EntityShader shader; + std::vector lights; + lights.push_back(entities::Light(glm::vec3(0, 1000, -7000), glm::vec3(5, 5, 5))); + lights.push_back(entities::Light(glm::vec3(0, 0, -30), glm::vec3(2, 0, 2), glm::vec3(0.0001f, 0.0001f, 0.0001f))); + lights.push_back(entities::Light(glm::vec3(0, 0, -200), glm::vec3(0, 2, 0), glm::vec3(0.0001f, 0.0001f, 0.0001f))); + + shaders::EntityShader shader; shader.Init(); render_engine::renderer::Init(shader); @@ -82,7 +85,7 @@ int main(void) render_engine::renderer::Prepare(); shader.Start(); shader.LoadSkyColor(render_engine::renderer::SKY_COLOR); - shader.LoadLight(light); + shader.LoadLights(lights); shader.LoadViewMatrix(camera); /** diff --git a/src/shaders/entity_shader.cpp b/src/shaders/entity_shader.cpp index 93a54fc..67112d2 100644 --- a/src/shaders/entity_shader.cpp +++ b/src/shaders/entity_shader.cpp @@ -18,14 +18,14 @@ namespace shaders // Equal to the texture_coords out vec2 pass_texture_coords; out vec3 surface_normal; - out vec3 to_light_vector; + out vec3 to_light_vector[4]; out vec3 to_camera_vector; out float visibility; uniform mat4 model_matrix; uniform mat4 projection_matrix; uniform mat4 view_matrix; - uniform vec3 light_position; + uniform vec3 light_position[4]; const float density = 0.0017; const float gradient = 4; @@ -44,7 +44,10 @@ namespace shaders pass_texture_coords = texture_coords; surface_normal = (model_matrix * vec4(normal, 0.0)).xyz; - to_light_vector = light_position - world_position.xyz; + for (int i = 0; i < 4; i++) + { + to_light_vector[i] = light_position[i] - world_position.xyz; + } to_camera_vector = (inverse(view_matrix) * vec4(0.0, 0.0, 0.0, 1.0)).xyz - world_position.xyz; // Calculate the density/visibility of the vertex with the fog @@ -64,7 +67,7 @@ namespace shaders in vec2 pass_texture_coords; in vec3 surface_normal; - in vec3 to_light_vector; + in vec3 to_light_vector[4]; in vec3 to_camera_vector; in float visibility; @@ -72,33 +75,49 @@ namespace shaders out vec4 out_color; // The texture of the model - uniform sampler2D texture_sampler; + uniform sampler2D model_texture; - uniform vec3 light_color; + uniform vec3 light_color[4]; + uniform vec3 attenuation[4]; uniform float shine_damper; uniform float reflectivity; uniform vec3 sky_color; + + const float min_diffuse_lighting = 0.1; void main(void) { vec3 unit_normal = normalize(surface_normal); - vec3 unit_light_vector = normalize(to_light_vector); - vec3 unit_camera_vector = normalize(to_camera_vector); + vec3 unit_camera_vector = normalize(to_camera_vector); - // Calculate the diffuse lighting - float dot_diffuse = dot(unit_normal, unit_light_vector); - float brightness = max(dot_diffuse, 0.1); - vec3 diffuse = brightness * light_color; + vec3 total_diffuse = vec3(0.0); + vec3 total_specular = vec3(0.0); + + for (int i = 0; i < 4; i++) + { + float distance = length(to_light_vector[i]); + float att_factor = attenuation[i].x + (attenuation[i].y * distance) + (attenuation[i].z * distance * distance); + + vec3 unit_light_vector = normalize(to_light_vector[i]); - // Calculate the specular lighting - vec3 light_direction = -unit_light_vector; - vec3 reflected_light_direction = reflect(light_direction, unit_normal); - float dot_specular = dot(reflected_light_direction, unit_camera_vector); - dot_specular = max(dot_specular, 0.0); - float damped_specular = pow(dot_specular, shine_damper); - vec3 specular = damped_specular * reflectivity * light_color; + // Calculate the diffuse lighting + float dot_diffuse = dot(unit_normal, unit_light_vector); + float brightness = max(dot_diffuse, 0.0); + + // Calculate the specular lighting + vec3 light_direction = -unit_light_vector; + vec3 reflected_light_direction = reflect(light_direction, unit_normal); + float dot_specular = dot(reflected_light_direction, unit_camera_vector); + dot_specular = max(dot_specular, 0.0); + float damped_specular = pow(dot_specular, shine_damper); - out_color = vec4(diffuse, 1.0) * texture(texture_sampler, pass_texture_coords) + vec4(specular, 1.0); + total_diffuse = total_diffuse + (brightness * light_color[i]) / att_factor; + total_specular = total_specular + (damped_specular * reflectivity * light_color[i]) / att_factor; + } + + total_diffuse = max(total_diffuse, min_diffuse_lighting); + + out_color = vec4(total_diffuse, 1.0) * texture(model_texture, pass_texture_coords) + vec4(total_specular, 1.0); out_color = mix(vec4(sky_color, 1.0), out_color, visibility); } )"; @@ -124,10 +143,22 @@ namespace shaders LoadMatrix(location_view_matrix, view_matrix); } - void EntityShader::LoadLight(entities::Light& light) const + void EntityShader::LoadLights(std::vector& lights) const { - LoadVector(location_light_position, light.GetPosition()); - LoadVector(location_light_color, light.GetColor()); + for (int i = 0; i < MAX_LIGHTS; ++i) + { + if (i < lights.size()) + { + LoadVector(location_light_position[i], lights[i].GetPosition()); + LoadVector(location_light_color[i], lights[i].GetColor()); + LoadVector(location_light_attenuation[i], lights[i].GetAttenuation()); + } else + { + LoadVector(location_light_position[i], glm::vec3(0, 0, 0)); + LoadVector(location_light_color[i], glm::vec3(0, 0, 0)); + LoadVector(location_light_attenuation[i], glm::vec3(1, 0, 0)); + } + } } void EntityShader::LoadShineVariables(float shine_damper, float reflectivity) const @@ -155,10 +186,20 @@ namespace shaders location_model_matrix = GetUniformLocation("model_matrix"); location_projection_matrix = GetUniformLocation("projection_matrix"); location_view_matrix = GetUniformLocation("view_matrix"); - location_light_position = GetUniformLocation("light_position"); - location_light_color = GetUniformLocation("light_color"); location_shine_damper = GetUniformLocation("shine_damper"); location_reflectivity = GetUniformLocation("reflectivity"); location_sky_color = GetUniformLocation("sky_color"); + + for (int i = 0; i < MAX_LIGHTS; ++i) + { + std::string light_pos = std::string("light_position[") + std::to_string(i) + "]"; + location_light_position[i] = GetUniformLocation(light_pos.c_str()); + + std::string light_color = std::string("light_color[") + std::to_string(i) + "]"; + location_light_color[i] = GetUniformLocation(light_color.c_str()); + + std::string light_attenuation = std::string("attenuation[") + std::to_string(i) + "]"; + location_light_attenuation[i] = GetUniformLocation(light_attenuation.c_str()); + } } } diff --git a/src/shaders/entity_shader.h b/src/shaders/entity_shader.h index 54d9c2e..514bbb4 100644 --- a/src/shaders/entity_shader.h +++ b/src/shaders/entity_shader.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "shader_program.h" #include "../entities/camera.h" #include "../entities/light.h" @@ -14,11 +15,14 @@ namespace shaders class EntityShader : public ShaderProgram { private: + const static int MAX_LIGHTS = 4; + GLuint location_model_matrix; GLuint location_projection_matrix; GLuint location_view_matrix; - GLuint location_light_position; - GLuint location_light_color; + GLuint location_light_position[MAX_LIGHTS]; + GLuint location_light_color[MAX_LIGHTS]; + GLuint location_light_attenuation[MAX_LIGHTS]; GLuint location_shine_damper; GLuint location_reflectivity; GLuint location_sky_color; @@ -48,11 +52,11 @@ namespace shaders void LoadViewMatrix(entities::Camera& camera) const; /* - * @brief: A method to load a light into the shader + * @brief: A method to load some lights into the shader * - * @param light: The light + * @param lights: The lights */ - void LoadLight(entities::Light& light) const; + void LoadLights(std::vector& lights) const; /* * @brief: A method to load the the shine variables from a model into the shader