From e71ffe3f2a2bb1d0116081be6d8bb8ebe8609df3 Mon Sep 17 00:00:00 2001 From: MrLetsplay2003 Date: Sat, 15 Oct 2022 19:56:44 +0200 Subject: [PATCH] Improve lighting, Keep track of frame time --- CMakeLists.txt | 7 +- src/kekengine/cpp/engine.cpp | 165 +++++++++++------- src/kekengine/cpp/mesh.cpp | 8 +- src/kekengine/cpp/shader.cpp | 22 +++ src/kekengine/include/constants.h | 10 +- src/kekengine/include/internal.h | 2 + src/kekengine/include/shader.h | 30 ++++ .../res/shader/include/constants.glsl | 1 + src/kekengine/res/shader/include/types.glsl | 7 +- src/kekengine/res/shader/mesh/fragment.glsl | 10 +- src/kekgame/cpp/kekgame.cpp | 4 +- 11 files changed, 188 insertions(+), 78 deletions(-) create mode 100644 src/kekengine/res/shader/include/constants.glsl diff --git a/CMakeLists.txt b/CMakeLists.txt index 3735264..acffba6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,9 +14,9 @@ if(WIN32) #set(BUILD_SHARED_LIBS OFF) endif() -message("Build shared libs: ${BUILD_SHARED_LIBS}") message("Debug: ${KEKENGINE_DEBUG}") message("Build kekgame: ${KEKENGINE_BUILD_KEKGAME}") +message("Build with VR support: ${KEKENGINE_VR}") message("Target platform: ${KEKENGINE_TARGET_PLATFORM}") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) @@ -118,6 +118,11 @@ if(${KEKENGINE_BUILD_KEKGAME}) add_executable(kekgame ${KEKGAME_SOURCE_FILES}) add_dependencies(kekgame kekgame_res) + + if(WIN32) + target_link_options(kekgame PUBLIC -static-libgcc -static-libstdc++ -static) + endif() + target_link_libraries(kekgame PUBLIC kekengine_static) target_include_directories(kekgame PRIVATE "src/kekengine/include") endif() diff --git a/src/kekengine/cpp/engine.cpp b/src/kekengine/cpp/engine.cpp index 7a4e0a3..cec0d9e 100644 --- a/src/kekengine/cpp/engine.cpp +++ b/src/kekengine/cpp/engine.cpp @@ -152,12 +152,13 @@ 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); kekData.activeCamera = new Camera(); kekData.shader = new Shader("shader/mesh/vertex.glsl", "shader/mesh/fragment.glsl"); + kekData.shader->initLighting(); return KEK_SUCCESS; } @@ -175,29 +176,29 @@ int start() { } if(glfwGetKey(kekData.window, GLFW_KEY_W) == GLFW_PRESS) { - kekData.activeCamera->translate(kekData.activeCamera->direction * 0.1f); + kekData.activeCamera->translate(kekData.activeCamera->direction * KEK_NOCLIP_SPEED * kekData.lastFrameTime); } if(glfwGetKey(kekData.window, GLFW_KEY_S) == GLFW_PRESS) { - kekData.activeCamera->translate(kekData.activeCamera->direction * -0.1f); + kekData.activeCamera->translate(kekData.activeCamera->direction * -KEK_NOCLIP_SPEED * kekData.lastFrameTime); } if(glfwGetKey(kekData.window, GLFW_KEY_A) == GLFW_PRESS) { glm::vec3 camRight = glm::normalize(glm::cross(kekData.activeCamera->direction, glm::vec3(0.0f, 1.0f, 0.0f))); - kekData.activeCamera->translate(-camRight * 0.1f); + kekData.activeCamera->translate(-camRight * KEK_NOCLIP_SPEED * kekData.lastFrameTime); } if(glfwGetKey(kekData.window, GLFW_KEY_D) == GLFW_PRESS) { glm::vec3 camRight = glm::normalize(glm::cross(kekData.activeCamera->direction, glm::vec3(0.0f, 1.0f, 0.0f))); - kekData.activeCamera->translate(camRight * 0.1f); + kekData.activeCamera->translate(camRight * KEK_NOCLIP_SPEED * kekData.lastFrameTime); } if(glfwGetKey(kekData.window, GLFW_KEY_SPACE) == GLFW_PRESS) { - kekData.activeCamera->translateY(0.1f); + kekData.activeCamera->translateY(KEK_NOCLIP_SPEED * kekData.lastFrameTime); } if(glfwGetKey(kekData.window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS) { - kekData.activeCamera->translateY(-0.1f); + kekData.activeCamera->translateY(-KEK_NOCLIP_SPEED * kekData.lastFrameTime); } if(glfwGetKey(kekData.window, GLFW_KEY_ESCAPE) == GLFW_PRESS) { @@ -217,69 +218,106 @@ 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; + if(kekData.shader->lighting) { + LightList *lights = kekData.activeScene->lights; - std::vector shaderLights; // TODO: Maybe don't compute on every frame + std::vector shaderLights; // TODO: Maybe don't compute on every frame - for(PointLight *light : lights->point) { - if(glm::length2(glm::abs(light->getPosition() - kekData.activeCamera->getPosition())) < KEK_LIGHT_MAX_DISTANCE_SQUARED) { + for(PointLight *light : lights->point) { + if(glm::length2(glm::abs(light->getPosition() - kekData.activeCamera->getPosition())) < KEK_LIGHT_MAX_DISTANCE_SQUARED) { + shaderLights.push_back(light); + } + } + + for(DirectionalLight *light : lights->directional) { shaderLights.push_back(light); } - } - for(DirectionalLight *light : lights->directional) { - shaderLights.push_back(light); - } - - for(SpotLight *light : lights->spot) { - if(glm::length2(glm::abs(light->getPosition() - kekData.activeCamera->getPosition())) < KEK_LIGHT_MAX_DISTANCE_SQUARED) { - shaderLights.push_back(light); - } - } - - unsigned int i = 0; - int numPointLights = 0, numDirectionalLights = 0, numSpotLights = 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 + "color").c_str()), 1, glm::value_ptr(l->color)); - glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "position").c_str()), 1, glm::value_ptr(l->getPosition())); - glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "attenuation").c_str()), 1, glm::value_ptr(glm::vec3(l->constant, l->linear, l->quadratic))); - numPointLights++; - break; - } - case LightType::DIRECTIONAL: - { - DirectionalLight *l = (DirectionalLight *) light; - glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "color").c_str()), 1, glm::value_ptr(l->color)); - glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "direction").c_str()), 1, glm::value_ptr(l->direction)); - numDirectionalLights++; - break; - } - case LightType::SPOT: - { - SpotLight *l = (SpotLight *) light; - glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "color").c_str()), 1, glm::value_ptr(l->color)); - glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "position").c_str()), 1, glm::value_ptr(l->getPosition())); - glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "direction").c_str()), 1, glm::value_ptr(l->direction)); - glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "attenuation").c_str()), 1, glm::value_ptr(glm::vec3(l->constant, l->linear, l->quadratic))); - glUniform2fv(glGetUniformLocation(kekData.shader->id, (prefix + "cutoff").c_str()), 1, glm::value_ptr(glm::vec2(glm::cos(l->innerCutoff), glm::cos(l->outerCutoff)))); - numSpotLights++; - break; + for(SpotLight *light : lights->spot) { + if(glm::length2(glm::abs(light->getPosition() - kekData.activeCamera->getPosition())) < KEK_LIGHT_MAX_DISTANCE_SQUARED) { + shaderLights.push_back(light); } } - i++; - } + unsigned int i = 0; + int numPointLights = 0, numDirectionalLights = 0, numSpotLights = 0; - glUniform1i(glGetUniformLocation(kekData.shader->id, "numPointLights"), numPointLights); - glUniform1i(glGetUniformLocation(kekData.shader->id, "numDirectionalLights"), numDirectionalLights); - glUniform1i(glGetUniformLocation(kekData.shader->id, "numSpotLights"), numSpotLights); + 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 + "color").c_str()), 1, glm::value_ptr(l->color)); + glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "position").c_str()), 1, glm::value_ptr(l->getPosition())); + glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "attenuation").c_str()), 1, glm::value_ptr(glm::vec3(l->constant, l->linear, l->quadratic))); + numPointLights++; + break; + } + case LightType::DIRECTIONAL: + { + DirectionalLight *l = (DirectionalLight *) light; + glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "color").c_str()), 1, glm::value_ptr(l->color)); + glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "direction").c_str()), 1, glm::value_ptr(l->direction)); + numDirectionalLights++; + break; + } + case LightType::SPOT: + { + SpotLight *l = (SpotLight *) light; + glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "color").c_str()), 1, glm::value_ptr(l->color)); + glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "position").c_str()), 1, glm::value_ptr(l->getPosition())); + glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "direction").c_str()), 1, glm::value_ptr(l->direction)); + glUniform3fv(glGetUniformLocation(kekData.shader->id, (prefix + "attenuation").c_str()), 1, glm::value_ptr(glm::vec3(l->constant, l->linear, l->quadratic))); + glUniform2fv(glGetUniformLocation(kekData.shader->id, (prefix + "cutoff").c_str()), 1, glm::value_ptr(glm::vec2(glm::cos(l->innerCutoff), glm::cos(l->outerCutoff)))); + numSpotLights++; + break; + } + }*/ + + ShaderLight shLight; + //shLight.color = light->color; + memcpy(shLight.color, glm::value_ptr(light->color), sizeof(shLight.color)); + switch(light->getType()) { + case LightType::POINT: + { + PointLight *l = (PointLight *) light; + memcpy(&shLight.position, glm::value_ptr(l->getPosition()), sizeof(shLight.position)); + memcpy(&shLight.attenuation, glm::value_ptr(glm::vec3(l->constant, l->linear, l->quadratic)), sizeof(shLight.attenuation)); + numPointLights++; + break; + } + case LightType::DIRECTIONAL: + { + DirectionalLight *l = (DirectionalLight *) light; + memcpy(&shLight.direction, glm::value_ptr(l->direction), sizeof(shLight.direction)); + numDirectionalLights++; + break; + } + case LightType::SPOT: + { + SpotLight *l = (SpotLight *) light; + memcpy(&shLight.position, glm::value_ptr(l->getPosition()), sizeof(shLight.position)); + memcpy(&shLight.direction, glm::value_ptr(l->direction), sizeof(shLight.direction)); + memcpy(&shLight.attenuation, glm::value_ptr(glm::vec3(l->constant, l->linear, l->quadratic)), sizeof(shLight.attenuation)); + memcpy(&shLight.cutoff, glm::value_ptr(glm::vec2(glm::cos(l->innerCutoff), glm::cos(l->outerCutoff))), sizeof(shLight.cutoff)); + numSpotLights++; + break; + } + } + kekData.shader->lighting->buffer[i] = shLight; + i++; + } + + // TODO: Fix broken lights + glNamedBufferData(kekData.shader->lighting->ubo, kekData.shader->lighting->blockSize, &kekData.shader->lighting->buffer, GL_DYNAMIC_DRAW); + glBindBufferBase(GL_UNIFORM_BUFFER, KEK_UNIFORM_LIGHTS_BINDING, kekData.shader->lighting->ubo); + + glUniform1i(glGetUniformLocation(kekData.shader->id, "numPointLights"), numPointLights); + glUniform1i(glGetUniformLocation(kekData.shader->id, "numDirectionalLights"), numDirectionalLights); + glUniform1i(glGetUniformLocation(kekData.shader->id, "numSpotLights"), numSpotLights); + } if(kekData.activeScene) kekData.activeScene->draw(kekData.shader); @@ -289,8 +327,9 @@ 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; + kekData.lastFrameTime = secsTaken.count(); + std::cout << "FT: " << kekData.lastFrameTime << std::endl; + std::cout << "FR: " << (1.0f / kekData.lastFrameTime) << std::endl; } return KEK_SUCCESS; diff --git a/src/kekengine/cpp/mesh.cpp b/src/kekengine/cpp/mesh.cpp index b71e32c..9bfc526 100644 --- a/src/kekengine/cpp/mesh.cpp +++ b/src/kekengine/cpp/mesh.cpp @@ -33,19 +33,19 @@ Mesh::Mesh(std::vector vertices, std::vector indices, Material glNamedBufferData(vbo, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW); glNamedBufferData(ebo, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW); - glVertexArrayVertexBuffer(vao, 0, vbo, 0, sizeof(Vertex)); + glVertexArrayVertexBuffer(vao, KEK_MESH_VERTEX_BUFFER_BINDING, vbo, 0, sizeof(Vertex)); 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); + glVertexArrayAttribBinding(vao, KEK_VERTEX_SHADER_IN_POSITION, KEK_MESH_VERTEX_BUFFER_BINDING); 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); + glVertexArrayAttribBinding(vao, KEK_VERTEX_SHADER_IN_NORMAL, KEK_MESH_VERTEX_BUFFER_BINDING); 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); + glVertexArrayAttribBinding(vao, KEK_VERTEX_SHADER_IN_TEXCOORD, KEK_MESH_VERTEX_BUFFER_BINDING); glVertexArrayElementBuffer(vao, ebo); diff --git a/src/kekengine/cpp/shader.cpp b/src/kekengine/cpp/shader.cpp index a97b300..6c81193 100644 --- a/src/kekengine/cpp/shader.cpp +++ b/src/kekengine/cpp/shader.cpp @@ -1,6 +1,7 @@ #include "shader.h" #include "types.h" #include "resource.h" +#include "constants.h" #include @@ -117,6 +118,27 @@ Shader::~Shader() { glDeleteProgram(id); } +void Shader::initLighting() { + lighting = (LightingData *) calloc(1, sizeof(LightingData)); + lighting->blockID = glGetUniformBlockIndex(id, "LightInfo"); + glUniformBlockBinding(id, lighting->blockID, KEK_UNIFORM_LIGHTS_BINDING); + glCreateBuffers(1, &lighting->ubo); + + GLenum err = glGetError(); + if(err != GL_NO_ERROR) { + std::cout << "OpenGL error while init lighting: " << err << std::endl; + exit(1); + } + + glGetActiveUniformBlockiv(id, lighting->blockID, GL_UNIFORM_BLOCK_DATA_SIZE, &lighting->blockSize); + std::cout << "Lighting block size: " << lighting->blockSize << std::endl; + std::cout << "Light size: " << sizeof(ShaderLight) << std::endl; + if(lighting->blockSize != KEK_LIGHT_LIMIT * sizeof(ShaderLight)) { + std::cerr << "Lighting block size doesn't match (is " << lighting->blockSize << ", should be " << KEK_LIGHT_LIMIT * sizeof(ShaderLight) << "). Improper padding?" << std::endl; + exit(1); + } +} + void Shader::use() { glUseProgram(id); } diff --git a/src/kekengine/include/constants.h b/src/kekengine/include/constants.h index 79d7ab3..cbb2ced 100644 --- a/src/kekengine/include/constants.h +++ b/src/kekengine/include/constants.h @@ -7,11 +7,17 @@ #define KEK_VERTEX_SHADER_IN_NORMAL 1 #define KEK_VERTEX_SHADER_IN_TEXCOORD 2 +#define KEK_MESH_VERTEX_BUFFER_BINDING 0 + +#define KEK_UNIFORM_LIGHTS_BINDING 0 + +#define KEK_LIGHT_LIMIT 64 // Also in shader/mesh/fragment.glsl + +#define KEK_NOCLIP_SPEED 10.0f + #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/internal.h b/src/kekengine/include/internal.h index 0cdd3a0..278c733 100644 --- a/src/kekengine/include/internal.h +++ b/src/kekengine/include/internal.h @@ -25,6 +25,8 @@ struct KekData { int screenWidth; int screenHeight; + float lastFrameTime; + std::map> loadedTextures; }; diff --git a/src/kekengine/include/shader.h b/src/kekengine/include/shader.h index 59a14fa..aee3dd5 100644 --- a/src/kekengine/include/shader.h +++ b/src/kekengine/include/shader.h @@ -1,13 +1,41 @@ #pragma once #include +#include + +#include "constants.h" namespace kek { +#pragma pack(1) +struct ShaderLight { + float color[3]; + float pad; + float position[3]; + float pad2; + float direction[3]; + float pad3; + float attenuation[3]; // constant, linear, quadratic + float pad4; + float cutoff[2]; // inner, outer + //float lightSpaceMatrix[16]; // mat4 + float padding[2]; +}; +#pragma pack(0) + +// Lighting data for shader +struct LightingData { + unsigned int blockID; + int blockSize; + unsigned int ubo; + ShaderLight buffer[KEK_LIGHT_LIMIT]; +}; + class Shader { public: unsigned int id; + LightingData *lighting; Shader(std::string vertexPath, std::string fragmentPath); @@ -15,6 +43,8 @@ public: ~Shader(); + void initLighting(); + void use(); }; diff --git a/src/kekengine/res/shader/include/constants.glsl b/src/kekengine/res/shader/include/constants.glsl new file mode 100644 index 0000000..24b9406 --- /dev/null +++ b/src/kekengine/res/shader/include/constants.glsl @@ -0,0 +1 @@ +#define MAX_LIGHTS 64 diff --git a/src/kekengine/res/shader/include/types.glsl b/src/kekengine/res/shader/include/types.glsl index 422c778..d767fbc 100644 --- a/src/kekengine/res/shader/include/types.glsl +++ b/src/kekengine/res/shader/include/types.glsl @@ -7,9 +7,14 @@ struct Material { struct Light { vec3 color; + float pad; vec3 position; + float pad2; vec3 direction; + float pad3; vec3 attenuation; // constant, linear, quadratic + float pad4; vec2 cutoff; // inner, outer - mat4 lightSpaceMatrix; + //mat4 lightSpaceMatrix; + vec2 padding; }; diff --git a/src/kekengine/res/shader/mesh/fragment.glsl b/src/kekengine/res/shader/mesh/fragment.glsl index e95a7c5..deaaec6 100644 --- a/src/kekengine/res/shader/mesh/fragment.glsl +++ b/src/kekengine/res/shader/mesh/fragment.glsl @@ -7,8 +7,12 @@ in VS_OUT { } fs_in; !include types.glsl +!include constants.glsl + +layout(std140) uniform LightInfo { + Light lights[MAX_LIGHTS]; +}; -uniform Light lights[8]; uniform int numPointLights; uniform int numDirectionalLights; uniform int numSpotLights; @@ -26,10 +30,6 @@ const float gamma = 2.2; void main() { 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); vec3 result = vec3(0.0); diff --git a/src/kekgame/cpp/kekgame.cpp b/src/kekgame/cpp/kekgame.cpp index c6bcf26..bd6c6d3 100644 --- a/src/kekgame/cpp/kekgame.cpp +++ b/src/kekgame/cpp/kekgame.cpp @@ -29,8 +29,8 @@ int main(int argc, char **argv) { PointLight *light = new PointLight(glm::vec3(1), 1, 0, 1); scene->lights->add(light); - DirectionalLight *l = new DirectionalLight(glm::vec3(1), glm::vec3(1, -1, 1)); - scene->lights->add(l); + //DirectionalLight *l = new DirectionalLight(glm::vec3(1), glm::vec3(1, -1, 1)); + //scene->lights->add(l); //SpotLight *spot = new SpotLight(glm::vec3(1), glm::vec3(0, 0, -1), 1, 0, 1, glm::radians(8.0f), glm::radians(15.0f)); //spot->moveTo(glm::vec3(0, 0, 5));