diff --git a/include/core/render/api.hpp b/include/core/render/api.hpp index 1e3ad20..d014a64 100644 --- a/include/core/render/api.hpp +++ b/include/core/render/api.hpp @@ -3,6 +3,7 @@ #include +#include #include #include "tools/logger.hpp" @@ -39,7 +40,7 @@ namespace Engine { void Startup(); void Shutdown(); void RenderScene(Engine::Scene::Scene *, glm::mat4, glm::mat4, glm::vec3); - void RenderObject(Engine::Object *, glm::mat4, glm::mat4, glm::vec3, Graphics::Lighting::Light *); + void RenderObject(Engine::Object *, glm::mat4, glm::mat4, glm::vec3, std::vector>); }; } } diff --git a/include/core/render/shader/base.hpp b/include/core/render/shader/base.hpp index c2925ed..d10deff 100644 --- a/include/core/render/shader/base.hpp +++ b/include/core/render/shader/base.hpp @@ -36,10 +36,10 @@ namespace Engine { virtual void Linking() = 0; virtual std::optional Compile(Shader, std::string) = 0; virtual void Build(std::filesystem::path, std::filesystem::path) = 0; - virtual void UniformFloat(const char *, float) = 0; - virtual void UniformInt(const char *, int) = 0; - virtual void UniformVector(const char *, glm::vec3) = 0; - virtual void UniformMatrix(const char *, glm::mat4) = 0; + virtual void UniformFloat(const std::string &, float) = 0; + virtual void UniformInt(const std::string &, int) = 0; + virtual void UniformVector(const std::string &, glm::vec3) = 0; + virtual void UniformMatrix(const std::string &, glm::mat4) = 0; }; } } diff --git a/include/core/render/shader/opengl.hpp b/include/core/render/shader/opengl.hpp index b0d20f6..40f7309 100644 --- a/include/core/render/shader/opengl.hpp +++ b/include/core/render/shader/opengl.hpp @@ -21,10 +21,10 @@ namespace Engine { void Use(); void Linking(); void Build(std::filesystem::path, std::filesystem::path); - void UniformInt(const char *, int); - void UniformFloat(const char *, float); - void UniformVector(const char *, glm::vec3); - void UniformMatrix(const char *, glm::mat4); + void UniformInt(const std::string &, int); + void UniformFloat(const std::string &, float); + void UniformVector(const std::string &, glm::vec3); + void UniformMatrix(const std::string &, glm::mat4); }; } } diff --git a/include/meta.hpp b/include/meta.hpp index 787fc23..f73f4b5 100644 --- a/include/meta.hpp +++ b/include/meta.hpp @@ -1,7 +1,7 @@ #ifndef __META_HPP__ #define __META_HPP__ -#define ENGINE_VERSION "0.1.2" +#define ENGINE_VERSION "0.1.3" #define GLSL_VERSION "#version 420" #endif diff --git a/resources/shaders/default.frag b/resources/shaders/default.frag index 7f7de8f..bde9490 100644 --- a/resources/shaders/default.frag +++ b/resources/shaders/default.frag @@ -1,5 +1,7 @@ #version 420 core +#define MAX_LIGHT_SOURCES 32 + #define DIRECTIONAL 0 #define POINT 1 #define SPOT 2 @@ -31,8 +33,9 @@ in vec3 FragPos; out vec4 color; -uniform Light light; uniform vec3 viewPosition; +uniform int lightSourcesCount; +uniform Light lights[MAX_LIGHT_SOURCES]; vec3 calculateDirectionLight(Light, vec3, vec3); @@ -41,22 +44,26 @@ vec3 calculateSpotLight(Light, vec3, vec3, vec3); void main() { - vec3 result; + vec3 result = vec3(0.0f); vec3 defaultColor = vec3(0.66f); vec3 norm = normalize(Normal); vec3 viewDir = normalize(viewPosition - FragPos); - if (light.type == DIRECTIONAL) { - result = calculateDirectionLight(light, norm, viewDir); - } - else if (light.type == POINT) { - result = calculatePointLight(light, norm, FragPos, viewDir); - } - else if (light.type == SPOT) { - result = calculateSpotLight(light, norm, FragPos, viewDir); + for(int index = 0; index < lightSourcesCount; index++) { + Light light = lights[index]; + + if (light.type == DIRECTIONAL) { + result += calculateDirectionLight(light, norm, viewDir) * light.intensity; + } + else if (light.type == POINT) { + result += calculatePointLight(light, norm, FragPos, viewDir) * light.intensity; + } + else if (light.type == SPOT) { + result += calculateSpotLight(light, norm, FragPos, viewDir) * light.intensity; + } } - color = vec4(result * defaultColor * light.intensity, 1.0f); + color = vec4(result * defaultColor, 1.0f); } diff --git a/resources/shaders/material.frag b/resources/shaders/material.frag index f7b9b7d..4bf98a1 100644 --- a/resources/shaders/material.frag +++ b/resources/shaders/material.frag @@ -1,5 +1,7 @@ #version 420 core +#define MAX_LIGHT_SOURCES 32 + #define DIRECTIONAL 0 #define POINT 1 #define SPOT 2 @@ -37,11 +39,12 @@ struct Material { in vec3 Normal; in vec3 FragPos; -uniform Light light; +out vec4 color; + uniform Material material; uniform vec3 viewPosition; - -out vec4 color; +uniform int lightSourcesCount; +uniform Light lights[MAX_LIGHT_SOURCES]; vec3 calculateDirectionLight(Light, Material, vec3, vec3); @@ -50,21 +53,25 @@ vec3 calculateSpotLight(Light, Material, vec3, vec3, vec3); void main() { - vec3 result; + vec3 result = vec3(0.0f); vec3 norm = normalize(Normal); vec3 viewDir = normalize(viewPosition - FragPos); - if (light.type == DIRECTIONAL) { - result = calculateDirectionLight(light, material, norm, viewDir); - } - else if (light.type == POINT) { - result = calculatePointLight(light, material, norm, FragPos, viewDir); - } - else if (light.type == SPOT) { - result = calculateSpotLight(light, material, norm, FragPos, viewDir); + for(int index = 0; index < lightSourcesCount; index++) { + Light light = lights[index]; + + if (light.type == DIRECTIONAL) { + result += calculateDirectionLight(light, material, norm, viewDir) * light.intensity; + } + else if (light.type == POINT) { + result += calculatePointLight(light, material, norm, FragPos, viewDir) * light.intensity; + } + else if (light.type == SPOT) { + result += calculateSpotLight(light, material, norm, FragPos, viewDir) * light.intensity; + } } - color = vec4((result * material.color) * light.intensity, 1.0f); + color = vec4(result * material.color, 1.0f); } diff --git a/src/core/render/api.cpp b/src/core/render/api.cpp index 5b90034..e802a34 100644 --- a/src/core/render/api.cpp +++ b/src/core/render/api.cpp @@ -58,17 +58,16 @@ void Render::Shutdown() { void Render::RenderScene(Engine::Scene::Scene *scene, glm::mat4 projection, glm::mat4 view, glm::vec3 cameraPosition) { // TODO: Only for opengl backend - std::shared_ptr lighting = scene->lighting[0]; - + // TODO: Add logger warning if more lights are added than the shader supports for (std::shared_ptr object : scene->root->entities) { - RenderObject(object.get(), projection, view, cameraPosition, lighting.get()); + RenderObject(object.get(), projection, view, cameraPosition, scene->lighting); } - if (lighting->HasComponent(Ecs::Component::Type::LIGHT)) { + for (std::shared_ptr light : scene->lighting) { glm::mat4 model = glm::mat4(1.0f); - model = glm::translate(model, lighting->transform->position); - model = glm::rotate(model, glm::radians(180.0f), lighting->transform->rotation); - model = glm::scale(model, lighting->transform->scale); + model = glm::translate(model, light->transform->position); + model = glm::rotate(model, glm::radians(180.0f), light->transform->rotation); + model = glm::scale(model, light->transform->scale); lightingShader->Use(); lightingShader->UniformMatrix("model", model); @@ -76,16 +75,19 @@ void Render::RenderScene(Engine::Scene::Scene *scene, glm::mat4 projection, glm: lightingShader->UniformMatrix("projection", projection); // If the editor is enabled, then draw where the light source is - lighting->mesh->VAO->bind(); - glDrawArrays(GL_TRIANGLES, 0, lighting->mesh->vertices.size() / 6); - lighting->mesh->VAO->unbind(); + light->mesh->VAO->bind(); + glDrawArrays(GL_TRIANGLES, 0, light->mesh->vertices.size() / 6); + light->mesh->VAO->unbind(); } scene->environment->skybox->update(projection * view); } -void Render::RenderObject(Object *object, glm::mat4 projection, glm::mat4 view, glm::vec3 cameraPosition, Graphics::Lighting::Light *lighting) { +void Render::RenderObject( + Object *object, glm::mat4 projection, glm::mat4 view, glm::vec3 cameraPosition, + std::vector> lights +) { if (object->HasComponent(Ecs::Component::Type::MESH)) { glm::mat4 model = glm::mat4(1.0f); model = glm::translate(model, object->transform->position); @@ -104,34 +106,39 @@ void Render::RenderObject(Object *object, glm::mat4 projection, glm::mat4 view, shader->UniformMatrix("model", model); shader->UniformMatrix("view", view); shader->UniformMatrix("projection", projection); - shader->UniformVector("viewPosition", cameraPosition); - shader->UniformVector("light.position", lighting->transform->position); - shader->UniformVector("light.color", lighting->light->color); - shader->UniformVector("light.ambient", lighting->light->ambient); - shader->UniformVector("light.diffuse", lighting->light->diffuse); - shader->UniformVector("light.specular", lighting->light->specular); - shader->UniformFloat("light.intensity", lighting->light->intensity); - - if (lighting->light->lightType == Graphics::Lighting::Type::DIRECTIONAL) { - shader->UniformInt("light.type", Graphics::Lighting::Type::DIRECTIONAL); - shader->UniformVector("light.direction", lighting->light->direction); - } - else if (lighting->light->lightType == Graphics::Lighting::Type::POINT) { - shader->UniformInt("light.type", Graphics::Lighting::Type::POINT); - shader->UniformFloat("light.constant", lighting->light->constant); - shader->UniformFloat("light.linear", lighting->light->linear); - shader->UniformFloat("light.quadratic", lighting->light->quadratic); - } - else if (lighting->light->lightType == Graphics::Lighting::Type::SPOT) { - shader->UniformInt("light.type", Graphics::Lighting::Type::SPOT); - shader->UniformVector("light.direction", lighting->light->direction); - shader->UniformFloat("light.constant", lighting->light->constant); - shader->UniformFloat("light.linear", lighting->light->linear); - shader->UniformFloat("light.quadratic", lighting->light->quadratic); - shader->UniformFloat("light.cutOff", glm::cos(glm::radians(lighting->light->cutOff))); - shader->UniformFloat("light.outerCutOff", glm::cos(glm::radians(lighting->light->outerCutOff))); + shader->UniformInt("lightSourcesCount", lights.size()); + + for (size_t index = 0; index < lights.size(); index++) { + std::shared_ptr light = lights[index]; + + shader->UniformVector(fmt::format("lights[{}].position", index), light->transform->position); + shader->UniformVector(fmt::format("lights[{}].color", index), light->light->color); + shader->UniformVector(fmt::format("lights[{}].ambient", index), light->light->ambient); + shader->UniformVector(fmt::format("lights[{}].diffuse", index), light->light->diffuse); + shader->UniformVector(fmt::format("lights[{}].specular", index), light->light->specular); + shader->UniformFloat(fmt::format("lights[{}].intensity", index), light->light->intensity); + + if (light->light->lightType == Graphics::Lighting::Type::DIRECTIONAL) { + shader->UniformInt(fmt::format("lights[{}].type", index), Graphics::Lighting::Type::DIRECTIONAL); + shader->UniformVector(fmt::format("lights[{}].direction", index), light->light->direction); + } + else if (light->light->lightType == Graphics::Lighting::Type::POINT) { + shader->UniformInt(fmt::format("lights[{}].type", index), Graphics::Lighting::Type::POINT); + shader->UniformFloat(fmt::format("lights[{}].constant", index), light->light->constant); + shader->UniformFloat(fmt::format("lights[{}].linear", index), light->light->linear); + shader->UniformFloat(fmt::format("lights[{}].quadratic", index), light->light->quadratic); + } + else if (light->light->lightType == Graphics::Lighting::Type::SPOT) { + shader->UniformInt(fmt::format("lights[{}].type", index), Graphics::Lighting::Type::SPOT); + shader->UniformVector(fmt::format("lights[{}].direction", index), light->light->direction); + shader->UniformFloat(fmt::format("lights[{}].constant", index), light->light->constant); + shader->UniformFloat(fmt::format("lights[{}].linear", index), light->light->linear); + shader->UniformFloat(fmt::format("lights[{}].quadratic", index), light->light->quadratic); + shader->UniformFloat(fmt::format("lights[{}].cutOff", index), glm::cos(glm::radians(light->light->cutOff))); + shader->UniformFloat(fmt::format("lights[{}].outerCutOff", index), glm::cos(glm::radians(light->light->outerCutOff))); + } } if (object->HasComponent(Ecs::Component::Type::MATERIAL)) { diff --git a/src/core/render/shader/opengl.cpp b/src/core/render/shader/opengl.cpp index 01df090..1fdfa89 100644 --- a/src/core/render/shader/opengl.cpp +++ b/src/core/render/shader/opengl.cpp @@ -126,25 +126,25 @@ void OpenglShaderProgram::Use() { } -void OpenglShaderProgram::UniformFloat(const char *attribute, float value) { - GLint variable = glGetUniformLocation(this->object, attribute); +void OpenglShaderProgram::UniformFloat(const std::string &attribute, float value) { + GLint variable = glGetUniformLocation(this->object, attribute.c_str()); glUniform1f(variable, value); } -void OpenglShaderProgram::UniformInt(const char *attribute, int value) { - GLint variable = glGetUniformLocation(this->object, attribute); +void OpenglShaderProgram::UniformInt(const std::string &attribute, int value) { + GLint variable = glGetUniformLocation(this->object, attribute.c_str()); glUniform1i(variable, value); } -void OpenglShaderProgram::UniformVector(const char *attribute, glm::vec3 vector){ - GLint variable = glGetUniformLocation(this->object, attribute); +void OpenglShaderProgram::UniformVector(const std::string &attribute, glm::vec3 vector){ + GLint variable = glGetUniformLocation(this->object, attribute.c_str()); glUniform3fv(variable, 1, glm::value_ptr(vector)); } -void OpenglShaderProgram::UniformMatrix(const char *attribure, glm::mat4 matrix) { - GLuint targetAttribute = glGetUniformLocation(this->object, attribure); - glUniformMatrix4fv(targetAttribute, 1, GL_FALSE, glm::value_ptr(matrix)); +void OpenglShaderProgram::UniformMatrix(const std::string &attribute, glm::mat4 matrix) { + GLuint variable = glGetUniformLocation(this->object, attribute.c_str()); + glUniformMatrix4fv(variable, 1, GL_FALSE, glm::value_ptr(matrix)); } diff --git a/src/main.cpp b/src/main.cpp index b81f67a..2a9c3c9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -185,6 +185,7 @@ class UserApplication : public Engine::EngineApplication { std::shared_ptr cube = std::make_shared(); std::shared_ptr cube2 = std::make_shared(); + plane->transform->position = {0.0f, 0.1f, 0.0f}; plane->transform->rotation = {0.0f, 1.0f, 1.0f}; plane->transform->scale = {20.0f, 20.0f, 1.0f}; @@ -207,6 +208,11 @@ class UserApplication : public Engine::EngineApplication { // Add sun to the scene std::shared_ptr sun = std::make_shared(); + std::shared_ptr point = + std::make_shared(); + std::shared_ptr point2 = + std::make_shared(); + sun->name = "Sun"; sun->light->intensity = 2.0f; @@ -217,7 +223,14 @@ class UserApplication : public Engine::EngineApplication { sun->transform->position = {-3.0f, 3.0f, -3.0f}; sun->transform->scale = {0.1f, 0.1f, 0.1f}; + point->transform->position = {3.0f, 3.0f, 3.0f}; + point->transform->scale = {0.1f, 0.1f, 0.1f}; + point2->transform->position = {4.0f, 2.0f, 2.0f}; + point2->transform->scale = {0.1f, 0.1f, 0.1f}; + scene->lighting.push_back(sun); + scene->lighting.push_back(point); + scene->lighting.push_back(point2); // End sun light this->debugAxes = Tool::Debug::DebugAxes::GetInstance(); @@ -264,9 +277,9 @@ int main() { UserApplication *application = new UserApplication(); Engine::Engine engine(application); - engine.Startup(); - try { + engine.Startup(); + engine.Run(); } catch (const std::exception& error) { std::cerr << error.what() << std::endl;