From c02d34227ace82263a1836385834f62b43f4394d Mon Sep 17 00:00:00 2001 From: MrLetsplay2003 Date: Tue, 11 Oct 2022 17:27:22 +0200 Subject: [PATCH] Basic lighting --- src/kekengine/cpp/engine.cpp | 38 ++++++++++++- src/kekengine/cpp/light.cpp | 44 +++++++++++++++ src/kekengine/cpp/mesh.cpp | 34 ++++++------ src/kekengine/cpp/scene.cpp | 4 +- src/kekengine/include/constants.h | 5 ++ src/kekengine/include/light.h | 55 +++++++++++++++++++ src/kekengine/include/scene.h | 7 ++- .../res/shader/include/lightcalc.glsl | 10 ++-- src/kekengine/res/shader/include/types.glsl | 38 ++----------- src/kekengine/res/shader/mesh/fragment.glsl | 15 ++++- src/kekgame/cpp/kekgame.cpp | 5 +- 11 files changed, 189 insertions(+), 66 deletions(-) create mode 100644 src/kekengine/cpp/light.cpp create mode 100644 src/kekengine/include/light.h diff --git a/src/kekengine/cpp/engine.cpp b/src/kekengine/cpp/engine.cpp index 7c979eb..a8bbae2 100644 --- a/src/kekengine/cpp/engine.cpp +++ b/src/kekengine/cpp/engine.cpp @@ -152,7 +152,7 @@ int init() { glfwSetInputMode(kekData.window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glClearColor(0.1f, 0.3f, 0.1f, 0.0f); - //glfwSwapInterval(0); + // glfwSwapInterval(0); stbi_set_flip_vertically_on_load(true); @@ -217,6 +217,38 @@ int start() { glUniformMatrix4fv(glGetUniformLocation(kekData.shader->id, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); glUniform3fv(glGetUniformLocation(kekData.shader->id, "cameraPos"), 1, glm::value_ptr(position)); + LightList *lights = kekData.activeScene->lights; + + std::vector shaderLights; + + for(PointLight *light : lights->point) { + if(glm::abs(light->getPosition() - kekData.activeCamera->getPosition()).length() < 10) { + shaderLights.push_back(light); + } + } + + glUniform1i(glGetUniformLocation(kekData.shader->id, "numPointLights"), 1); + + unsigned int i = 0; + for(Light *light : shaderLights) { + std::string prefix = "lights[" + std::to_string(i) + "]."; + + switch(light->getType()) { + case LightType::POINT: + { + PointLight *l = (PointLight *) light; + glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "position").c_str()), 1, glm::value_ptr(l->getPosition())); + glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "color").c_str()), 1, glm::value_ptr(l->color)); + glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "attenuation").c_str()), 1, glm::value_ptr(glm::vec3(l->constant, l->linear, l->quadratic))); + } + case LightType::DIRECTIONAL: + case LightType::SPOT: + break; + } + + i++; + } + if(kekData.activeScene) kekData.activeScene->draw(kekData.shader); // Swap buffers and poll window events @@ -225,8 +257,8 @@ int start() { auto end = std::chrono::high_resolution_clock::now(); std::chrono::duration secsTaken = end - start; - //std::cout << "FT: " << secsTaken.count() * 1000 << std::endl; - //std::cout << "FR: " << (1.0f / secsTaken.count()) << std::endl; + // std::cout << "FT: " << secsTaken.count() * 1000 << std::endl; + // std::cout << "FR: " << (1.0f / secsTaken.count()) << std::endl; } return KEK_SUCCESS; diff --git a/src/kekengine/cpp/light.cpp b/src/kekengine/cpp/light.cpp new file mode 100644 index 0000000..3f730ea --- /dev/null +++ b/src/kekengine/cpp/light.cpp @@ -0,0 +1,44 @@ +#include + +#include "light.h" +#include "constants.h" + +namespace kek { + +Light::Light(glm::vec3 color) { + this->color = color; +} + +Light::~Light() { + +} + +PointLight::PointLight(glm::vec3 color, float constantFalloff, float linearFalloff, float quadraticFalloff): Light(color) { + this->constant = constantFalloff; + this->linear = linearFalloff; + this->quadratic = quadraticFalloff; +} + +PointLight::~PointLight() { + +} + +LightType PointLight::getType() { + return LightType::POINT; +} + +LightList::LightList() { + point = std::vector(); + //directional = std::vector(); + //spot = std::vector(); +} + +void LightList::add(Light *light) { + switch(light->getType()) { + case LightType::POINT: point.push_back((PointLight *) light); break; + //case LightType::DIRECTIONAL: directional.push_back((DirectionalLight *) light); break; + //case LightType::SPOT: spot.push_back((SpotLight *) light); break; + } +} + +} diff --git a/src/kekengine/cpp/mesh.cpp b/src/kekengine/cpp/mesh.cpp index 4f3b6a9..b71e32c 100644 --- a/src/kekengine/cpp/mesh.cpp +++ b/src/kekengine/cpp/mesh.cpp @@ -24,30 +24,30 @@ Mesh::Mesh(std::vector vertices, std::vector indices, Material this->indices = indices; this->material = material; - glGenVertexArrays(1, &vao); - glGenBuffers(1, &vbo); - glGenBuffers(1, &ebo); + glCreateVertexArrays(1, &vao); + glCreateBuffers(1, &vbo); + glCreateBuffers(1, &ebo); - glBindVertexArray(vao); + //glBindVertexArray(vao); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW); - //glBindBuffer(GL_ARRAY_BUFFER, 0); + glNamedBufferData(vbo, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW); + glNamedBufferData(ebo, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW); - //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glVertexArrayVertexBuffer(vao, 0, vbo, 0, sizeof(Vertex)); - glVertexAttribPointer(KEK_VERTEX_SHADER_IN_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); - glEnableVertexAttribArray(KEK_VERTEX_SHADER_IN_POSITION); + glEnableVertexArrayAttrib(vao, KEK_VERTEX_SHADER_IN_POSITION); + glVertexArrayAttribFormat(vao, KEK_VERTEX_SHADER_IN_POSITION, sizeof(float), GL_FLOAT, GL_FALSE, 0); + glVertexArrayAttribBinding(vao, KEK_VERTEX_SHADER_IN_POSITION, 0); - glVertexAttribPointer(KEK_VERTEX_SHADER_IN_NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *) offsetof(Vertex, normal)); - glEnableVertexAttribArray(KEK_VERTEX_SHADER_IN_NORMAL); + glEnableVertexArrayAttrib(vao, KEK_VERTEX_SHADER_IN_NORMAL); + glVertexArrayAttribFormat(vao, KEK_VERTEX_SHADER_IN_NORMAL, sizeof(float), GL_FLOAT, GL_FALSE, offsetof(Vertex, normal)); + glVertexArrayAttribBinding(vao, KEK_VERTEX_SHADER_IN_NORMAL, 0); - glVertexAttribPointer(KEK_VERTEX_SHADER_IN_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *) offsetof(Vertex, texCoords)); - glEnableVertexAttribArray(KEK_VERTEX_SHADER_IN_TEXCOORD); + glEnableVertexArrayAttrib(vao, KEK_VERTEX_SHADER_IN_TEXCOORD); + glVertexArrayAttribFormat(vao, KEK_VERTEX_SHADER_IN_TEXCOORD, sizeof(float), GL_FLOAT, GL_FALSE, offsetof(Vertex, texCoords)); + glVertexArrayAttribBinding(vao, KEK_VERTEX_SHADER_IN_TEXCOORD, 0); - glBindVertexArray(0); + glVertexArrayElementBuffer(vao, ebo); GLenum err = glGetError(); if(err != GL_NO_ERROR) { diff --git a/src/kekengine/cpp/scene.cpp b/src/kekengine/cpp/scene.cpp index a662fa1..6651b1e 100644 --- a/src/kekengine/cpp/scene.cpp +++ b/src/kekengine/cpp/scene.cpp @@ -3,11 +3,13 @@ namespace kek { Scene::Scene() { - + this->lights = new LightList(); } Scene::~Scene() { for(GameObject *obj : objects) delete obj; + for(Light *l : lights->point) delete l; + delete lights; } void Scene::addObject(GameObject *object) { diff --git a/src/kekengine/include/constants.h b/src/kekengine/include/constants.h index b267e08..9d0802c 100644 --- a/src/kekengine/include/constants.h +++ b/src/kekengine/include/constants.h @@ -9,3 +9,8 @@ #define KEK_CAMERA_NEAR 0.1f #define KEK_CAMERA_FAR 100.0f + +#define KEK_LIGHT_LIMIT 8 // Also in shader/mesh/fragment.glsl + +#define KEK_LIGHT_DEFAULT_AMBIENT_STRENGTH 0.05f +#define KEK_LIGHT_DEFAULT_SPECULAR_STRENGTH 0.1f diff --git a/src/kekengine/include/light.h b/src/kekengine/include/light.h new file mode 100644 index 0000000..2ef4bd9 --- /dev/null +++ b/src/kekengine/include/light.h @@ -0,0 +1,55 @@ +#pragma once + +#include +#include + +#include "object.h" + +namespace kek { + +enum class LightType { + POINT, + DIRECTIONAL, + SPOT +}; + +class Light { + +public: + glm::vec3 color; + + Light(glm::vec3 color); + + virtual ~Light(); + + virtual LightType getType() = 0; + +}; + +class PointLight: public Light, public DefaultObject { + +public: + float constant, linear, quadratic; + + PointLight(glm::vec3 color, float constant, float linear, float quadratic); + + ~PointLight(); + + LightType getType(); + +}; + +class LightList { + +public: + std::vector point; + //std::vector directional; + //std::vector spot; + + LightList(); + + void add(Light *light); + +}; + +} diff --git a/src/kekengine/include/scene.h b/src/kekengine/include/scene.h index 9a62787..9c641b7 100644 --- a/src/kekengine/include/scene.h +++ b/src/kekengine/include/scene.h @@ -3,15 +3,16 @@ #include #include "gameobject.h" +#include "light.h" namespace kek { class Scene { -protected: - std::vector objects; - public: + std::vector objects; + LightList *lights; + Scene(); ~Scene(); diff --git a/src/kekengine/res/shader/include/lightcalc.glsl b/src/kekengine/res/shader/include/lightcalc.glsl index 66e5777..8fa530f 100644 --- a/src/kekengine/res/shader/include/lightcalc.glsl +++ b/src/kekengine/res/shader/include/lightcalc.glsl @@ -1,21 +1,21 @@ -vec3 calcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir, vec2 texCoord, float shadow) { +vec3 calcPointLight(Light light, vec3 normal, vec3 fragPos, vec3 viewDir, vec2 texCoord, float shadow) { vec3 lightDir = normalize(light.position - fragPos); vec3 halfwayDir = normalize(lightDir + viewDir); // Ambient - vec3 ambient = light.ambient * vec3(texture(material.diffuse, texCoord)); + vec3 ambient = light.color * vec3(texture(material.ambient, texCoord)); // Diffuse float diff = max(dot(normal, lightDir), 0.0); - vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, texCoord)); + vec3 diffuse = light.color * diff * vec3(texture(material.diffuse, texCoord)); // Specular float spec = pow(max(dot(normal, halfwayDir), 0.0), material.shininess); - vec3 specular = light.specular * spec * vec3(texture(material.specular, texCoord)); + vec3 specular = light.color * spec * vec3(texture(material.specular, texCoord)); // Attenuation float dist = length(light.position - fragPos); - float attenuation = 1.0 / (light.constant + light.linear * dist + light.quadratic * (dist * dist)); + float attenuation = 1.0 / (light.attenuation.x + light.attenuation.y * dist + light.attenuation.z * (dist * dist)); ambient *= attenuation; diffuse *= attenuation; diff --git a/src/kekengine/res/shader/include/types.glsl b/src/kekengine/res/shader/include/types.glsl index 4293fab..eb67f94 100644 --- a/src/kekengine/res/shader/include/types.glsl +++ b/src/kekengine/res/shader/include/types.glsl @@ -5,41 +5,11 @@ struct Material { float shininess; }; -struct PointLight { - vec3 position; - - vec3 ambient; - vec3 diffuse; - vec3 specular; - - float constant; - float linear; - float quadratic; -}; - -struct DirectionalLight { - vec3 direction; - - vec3 ambient; - vec3 diffuse; - vec3 specular; - - mat4 lightSpaceMatrix; -}; - -struct SpotLight { +struct Light { vec3 position; vec3 direction; - float innerCutOff; - float outerCutOff; - - vec3 ambient; - vec3 diffuse; - vec3 specular; - - float constant; - float linear; - float quadratic; - + vec3 color; + vec3 attenuation; + vec2 cutoff; mat4 lightSpaceMatrix; }; diff --git a/src/kekengine/res/shader/mesh/fragment.glsl b/src/kekengine/res/shader/mesh/fragment.glsl index f31ac2e..74e1300 100644 --- a/src/kekengine/res/shader/mesh/fragment.glsl +++ b/src/kekengine/res/shader/mesh/fragment.glsl @@ -8,21 +8,32 @@ in VS_OUT { !include types.glsl +uniform Light lights[8]; +uniform int numPointLights; + uniform Material material; uniform vec3 cameraPos; out vec4 color; +const float gamma = 2.2; + !include lightcalc.glsl void main() { - vec3 norm = normalize(fs_in.normal); + vec3 normal = normalize(fs_in.normal); vec3 viewDir = normalize(cameraPos - fs_in.fragmentPosition); //color = length(fs_in.fragmentPosition) / 2 * vec4(1.0); //color = vec4(norm, 1.0); color = texture(material.diffuse, fs_in.textureCoordinate); - //PointLight light = {}; + vec3 result = vec3(0.0); + + for(int i = 0; i < numPointLights; i++) { + result += calcPointLight(lights[i], normal, fs_in.fragmentPosition, viewDir, fs_in.textureCoordinate, 0.0); + } + + color = vec4(pow(result, vec3(1.0 / gamma)), 1.0); } diff --git a/src/kekgame/cpp/kekgame.cpp b/src/kekgame/cpp/kekgame.cpp index a49d3bb..bd9ada0 100644 --- a/src/kekgame/cpp/kekgame.cpp +++ b/src/kekgame/cpp/kekgame.cpp @@ -19,13 +19,16 @@ int main(int argc, char **argv) { Scene *scene = new Scene(); scene->addObject(test); - for(int i = 0; i < 1; i++) { + for(int i = 0; i < 10; i++) { GameObject *test2 = new GameObject(); test2->addMesh(ObjParser::loadMesh("object/cube_colored/Cube.obj")); test2->moveTo(glm::vec3(0.0f, 5.0f, 3 * i)); scene->addObject(test2); } + PointLight *light = new PointLight(glm::vec3(1), 1, 1, 1); + scene->lights->add(light); + Engine::setActiveScene(scene); Engine::start();