From bbd186bca9561817377f574013eae39faba7d4e7 Mon Sep 17 00:00:00 2001 From: 4VRDriver <44267643+4VRDriver@users.noreply.github.com> Date: Tue, 22 Sep 2020 10:40:25 +0200 Subject: [PATCH] Add exposure HDR lighting --- imgui.ini | 2 +- res/shaders/basic.frag | 14 +++----- res/shaders/postprocessing.frag | 5 +++ src/CMakeLists.txt | 1 + src/Camera.h | 7 ++++ src/Controller.cpp | 45 +++++++++++++++-------- src/Controller.h | 5 ++- src/Framebuffer.cpp | 63 ++++++++++++++++++++++++++------- src/Framebuffer.h | 16 +++++++++ src/Light.cpp | 2 -- src/Light.h | 5 ++- src/Shadows.cpp | 24 +++++++++++++ src/Shadows.h | 19 ++++++++++ 13 files changed, 165 insertions(+), 43 deletions(-) create mode 100644 src/Shadows.cpp create mode 100644 src/Shadows.h diff --git a/imgui.ini b/imgui.ini index e90789c..39c660b 100644 --- a/imgui.ini +++ b/imgui.ini @@ -9,7 +9,7 @@ Size=894,195 Collapsed=0 [Window][Debug Utils] -Pos=25,15 +Pos=37,5 Size=863,335 Collapsed=0 diff --git a/res/shaders/basic.frag b/res/shaders/basic.frag index 3bd6e3a..2a0032d 100644 --- a/res/shaders/basic.frag +++ b/res/shaders/basic.frag @@ -35,8 +35,6 @@ struct PointLight { bool isActive; vec3 position; - float K_c; - float K_l; float K_q; vec3 ambient; @@ -54,8 +52,6 @@ struct SpotLight { float innerCutOff; float outerCutOff; - float K_c; - float K_l; float K_q; vec3 ambient; @@ -77,7 +73,7 @@ void computeShading( out vec3 ambient, out vec3 diffuse, out vec3 specular ); -float computeAttenuation(vec3 lightPos, vec3 fragPos, float K_c, float K_l, float K_q); +float computeAttenuation(vec3 lightPos, vec3 fragPos, float K_q); void main() { @@ -123,7 +119,7 @@ vec3 pointLightContribution(PointLight light, vec3 normal, vec3 fragPos, vec3 vi vec3 ambient, diffuse, specular; computeShading(light.ambient, light.diffuse, light.specular, lightDir, viewDir, normal, ambient, diffuse, specular); - float attenuation = computeAttenuation(light.position, fragPos, light.K_c, light.K_l, light.K_q); + float attenuation = computeAttenuation(light.position, fragPos, light.K_q); ambient *= attenuation; diffuse *= attenuation; specular *= attenuation; @@ -142,7 +138,7 @@ vec3 spotLightContribution(SpotLight light, vec3 normal, vec3 fragPos, vec3 view vec3 ambient, diffuse, specular; computeShading(light.ambient, light.diffuse, light.specular, lightDir, viewDir, normal, ambient, diffuse, specular); - float attenuation = computeAttenuation(light.position, fragPos, light.K_c, light.K_l, light.K_q); + float attenuation = computeAttenuation(light.position, fragPos, light.K_q); ambient *= attenuation; diffuse *= attenuation; specular *= attenuation; @@ -178,10 +174,10 @@ void computeShading( } -float computeAttenuation(vec3 lightPos, vec3 fragPos, float K_c, float K_l, float K_q) { +float computeAttenuation(vec3 lightPos, vec3 fragPos, float K_q) { float distanceLightFragment = length(lightPos - fragPos); - //return 1.0f / (K_c + K_l * distanceLightFragment + K_q * distanceLightFragment * distanceLightFragment);# + return 1.0f / (K_q * distanceLightFragment * distanceLightFragment); } diff --git a/res/shaders/postprocessing.frag b/res/shaders/postprocessing.frag index 6dd7047..dcef925 100644 --- a/res/shaders/postprocessing.frag +++ b/res/shaders/postprocessing.frag @@ -6,12 +6,17 @@ layout(location = 0) out vec4 f_color; in vec2 v_tex_coords; +uniform float u_exposure; + uniform sampler2D u_texture; void main() { vec3 fragmentColor = vec3(texture2D(u_texture, v_tex_coords)); + // Exposure tone mapping + fragmentColor = vec3(1.0) - exp(-fragmentColor * u_exposure); + // Gamma correction fragmentColor = pow(fragmentColor, vec3(1.0/GAMMA)); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a66d9bf..936a4ab 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,6 +13,7 @@ add_executable(Fall-Fever Light.cpp World.cpp Framebuffer.cpp + Shadows.cpp ) target_link_libraries( diff --git a/src/Camera.h b/src/Camera.h index 52ab4b0..73ca37c 100644 --- a/src/Camera.h +++ b/src/Camera.h @@ -1,6 +1,7 @@ #pragma once #include +#include "ShaderProgram.h" class Camera { @@ -17,6 +18,11 @@ public: void translate(glm::vec3 translateVector); void setPosition(glm::vec3 position) { this->position = position; } + void setExposure(ShaderProgram *shaderProgram) { + shaderProgram->setUniform("exposure", exposure); + this->exposure = exposure; + } + void lookAtTarget(glm::vec3 target); void lookForward(); @@ -43,5 +49,6 @@ private: float speed = 2.0f; float fov; + float exposure = 1.0f; }; diff --git a/src/Controller.cpp b/src/Controller.cpp index ffa77e1..2f12890 100644 --- a/src/Controller.cpp +++ b/src/Controller.cpp @@ -81,6 +81,8 @@ void Controller::run() { ShaderProgram skyboxProgram("res/shaders/skybox.vert", "res/shaders/skybox.frag"); ShaderProgram postProcessingProgram("res/shaders/postprocessing.vert", "res/shaders/postprocessing.frag"); + updateExposure(&postProcessingProgram); + Model model_backpack("res/models/backpack.ffo"); //Model model_plant("res/models/plant.ffo"); //Model model_container("res/models/container.ffo"); @@ -126,15 +128,15 @@ void Controller::run() { // ... static bool rotateLightSource = 0; if(rotateLightSource) { - float radius = 25.0; + float radius = 4.0; glm::vec3 newPos = glm::vec3(-cos(glfwGetTime()*0.5), 0.5f, sin(glfwGetTime()*0.5)) * radius; world.getEntities()->operator[](1).setPosition(newPos); } - static glm::vec3 lightColor = glm::vec3(1.f); - world.updatePointLight(0, true, world.getEntities()->operator[](1).getPosition(), lightColor); - world.updateDirectionalLight(true, glm::vec3(-0.2f, -1.0f, -0.3f), lightColor * 0.001f); + static glm::vec3 lightColor = glm::vec3(1.f); static float intensity = 1.0f; + world.updatePointLight(0, true, world.getEntities()->operator[](1).getPosition(), lightColor * intensity); + world.updateDirectionalLight(true, glm::vec3(-0.2f, -1.0f, -0.3f), lightColor * 0.1f); lightProgram.bind(); - lightProgram.setUniform("v_lightColor", lightColor); + lightProgram.setUniform("v_lightColor", lightColor * 100.0f); lightProgram.unbind(); // Render and buffer swap @@ -146,6 +148,10 @@ void Controller::run() { camera->lookForward(); camera->updateVPM(); + // Calc shadows + // ... + + glViewport(0, 0, gameWindow->getWindowWidth(), gameWindow->getWindowHeight()); skybox.draw(camera->getView(), camera->getProj()); world.draw(camera->getViewProj(), camera->getPosition()); pp_framebuffer->unbind(); @@ -153,7 +159,7 @@ void Controller::run() { pp_framebuffer->render(); #ifdef _DEBUG - renderImGui(world.getEntities(), &world.getPointLights()[0], &lightColor, &rotateLightSource); + renderImGui(world.getEntities(), &world.getPointLights()[0], &lightColor, &rotateLightSource, &postProcessingProgram, &intensity); #endif glfwSwapBuffers(gameWindow->getGLFWwindow()); @@ -209,8 +215,14 @@ void Controller::updateWindowSize(ShaderProgram *pp_program) { pp_framebuffer = new Framebuffer(gameWindow->getWindowWidth(), gameWindow->getWindowHeight(), pp_program); } +void Controller::updateExposure(ShaderProgram *shaderProgram) { + shaderProgram->bind(); + shaderProgram->setUniform("u_exposure", exposure); + shaderProgram->unbind(); +} + #ifdef _DEBUG -void Controller::renderImGui(std::vector *entites, PointLight *pointLight, glm::vec3 *lightColor, bool *rotateLightSource) { +void Controller::renderImGui(std::vector *entites, PointLight *pointLight, glm::vec3 *lightColor, bool *rotateLightSource, ShaderProgram *postProcessingProgram, float *intensity) { ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); @@ -218,7 +230,7 @@ void Controller::renderImGui(std::vector *entites, PointLight *pointLigh // render your GUI ImGui::Begin("Debug Utils"); - ImGui::Text("Dragon"); + ImGui::Text("Object"); static float rotation = 0.0; ImGui::SliderFloat("Rotation", &rotation, 0, 2 * M_PI); static float translation[] = {0.0f, 0.0f, 0.0f}; @@ -232,21 +244,24 @@ void Controller::renderImGui(std::vector *entites, PointLight *pointLigh // color picker ImGui::Text("\nLight Source"); - ImGui::Text("Attenuation"); - static float K_c = 1.0f, K_l = 0.09f, K_q = 0.062f; - ImGui::SliderFloat("Constant Term", &K_c, 0, 1.0f*5); - ImGui::SliderFloat("Linear Term", &K_l, 0, 0.09f*5); - ImGui::SliderFloat("Quadratic Term", &K_q, 0, 0.032f*10); + static float K_q = 0.062f; + ImGui::SliderFloat("Attenuation Parameter", &K_q, 0, 1.5f); - pointLight->setParameters(K_c, K_l, K_q); + updateExposure(postProcessingProgram); + pointLight->setParameters(K_q); static float color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - ImGui::Text("Color"); + + ImGui::SliderFloat("Intensity", intensity, 0, 50.f); + ImGui::ColorEdit3("Color", color); lightColor->x = color[0]; lightColor->y = color[1]; lightColor->z = color[2]; + ImGui::Text("\nMiscellaneous"); + ImGui::SliderFloat("Exposure", &exposure, 0, 5.0f); + ImGui::Checkbox("Rotate Lightsource", rotateLightSource); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", diff --git a/src/Controller.h b/src/Controller.h index b9c5760..72f1b3b 100644 --- a/src/Controller.h +++ b/src/Controller.h @@ -27,8 +27,9 @@ private: void limit_framerate(); void updateWindowSize(ShaderProgram *pp_program); + void updateExposure(ShaderProgram *shaderProgram); - void renderImGui(std::vector *entites, PointLight *pointLight, glm::vec3 *lightColor, bool *rotateLightSource); + void renderImGui(std::vector *entites, PointLight *pointLight, glm::vec3 *lightColor, bool *rotateLightSource, ShaderProgram *postProcessingProgram, float *intensity); Window *gameWindow; EventHandler *gameEventHandler; @@ -41,4 +42,6 @@ private: bool wireFrameMode = 0; + float exposure = 1.0f; + }; diff --git a/src/Framebuffer.cpp b/src/Framebuffer.cpp index 1cd48d0..fab34f4 100644 --- a/src/Framebuffer.cpp +++ b/src/Framebuffer.cpp @@ -41,17 +41,56 @@ void Framebuffer::unbind() { } void Framebuffer::render() { - shaderProgram->bind(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, getTextureId()); - GLint location = glGetUniformLocation(shaderProgram->getShaderProgramId(), "u_texture"); - glUniform1i(location, 0); - // A VAO is necessary although no data is stored in it - GLuint temp_vao; - glGenVertexArrays(1, &temp_vao); - glBindVertexArray(temp_vao); - glDrawArrays(GL_TRIANGLES, 0, 3); - glBindVertexArray(0); - shaderProgram->unbind(); + // Disable wireframe mode + GLint wireframe; + glGetIntegerv(GL_POLYGON_MODE, &wireframe); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + shaderProgram->bind(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, getTextureId()); + GLint location = glGetUniformLocation(shaderProgram->getShaderProgramId(), "u_texture"); + glUniform1i(location, 0); + + // A VAO is necessary although no data is stored in it + GLuint temp_vao; + glGenVertexArrays(1, &temp_vao); + glBindVertexArray(temp_vao); + glDrawArrays(GL_TRIANGLES, 0, 3); + glBindVertexArray(0); + + glPolygonMode(GL_FRONT_AND_BACK, wireframe); + shaderProgram->unbind(); +} + + + +DepthMap::DepthMap(int resolution) { + + glGenFramebuffers(1, &depthMapFBO); + + unsigned int depthMap; + glGenTextures(1, &depthMap); + glBindTexture(GL_TEXTURE_2D, depthMap); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, resolution, resolution, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0); + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + +} + +void DepthMap::bind() { + glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); +} + +void DepthMap::unbind() { + glBindFramebuffer(GL_FRAMEBUFFER, 0); } diff --git a/src/Framebuffer.h b/src/Framebuffer.h index cb2bb78..5d01ed6 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -26,4 +26,20 @@ private: ShaderProgram *shaderProgram; +}; + + +class DepthMap { + +public: + + DepthMap(int resolution); + + void bind(); + void unbind(); + +private: + + GLuint depthMapFBO; + }; \ No newline at end of file diff --git a/src/Light.cpp b/src/Light.cpp index 466b6ac..e9573ba 100644 --- a/src/Light.cpp +++ b/src/Light.cpp @@ -18,8 +18,6 @@ void PointLight::update() { shaderProgram->setUniform((_getStructMemberName() + "ambient").c_str(), ambientColor); shaderProgram->setUniform((_getStructMemberName() + "diffuse").c_str(), diffuseColor); shaderProgram->setUniform((_getStructMemberName() + "specular").c_str(), specularColor); - shaderProgram->setUniform((_getStructMemberName() + "K_c").c_str(), K_c); - shaderProgram->setUniform((_getStructMemberName() + "K_l").c_str(), K_l); shaderProgram->setUniform((_getStructMemberName() + "K_q").c_str(), K_q); shaderProgram->unbind(); diff --git a/src/Light.h b/src/Light.h index 32f4cbc..0e3ba06 100644 --- a/src/Light.h +++ b/src/Light.h @@ -60,7 +60,7 @@ public: update(); } - void setParameters(float K_c, float K_l, float K_q) { this->K_c = K_c; this->K_l = K_l; this->K_q = K_q; } + void setParameters(float K_q) { this->K_q = K_q; } void setId(unsigned int id) { lightId = id; } @@ -72,8 +72,7 @@ private: unsigned int lightId; glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f); - float K_c = 1.0f; - float K_l = 0.09f; + float K_q = 0.032f; }; diff --git a/src/Shadows.cpp b/src/Shadows.cpp new file mode 100644 index 0000000..4dc3a54 --- /dev/null +++ b/src/Shadows.cpp @@ -0,0 +1,24 @@ +#include "Shadows.h" + +#include +#include + +Shadows::Shadows() + : depthMap(SHADOW_RES) { + +} + +void Shadows::calculate() { + + glViewport(0, 0, SHADOW_RES, SHADOW_RES); + depthMap.bind(); + glClear(GL_DEPTH_BUFFER_BIT); + // ConfigureShaderAndMatrices(); + float near_plane = 1.0f, far_plane = 7.5f; + glm::mat4 lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane); + glm::mat4 lightView = glm::lookAt(glm::vec3(-0.2f, -1.0f, -0.3f), glm::vec3( 0.0f, 0.0f, 0.0f), glm::vec3( 0.0f, 1.0f, 0.0f)); + glm::mat4 lightSpaceMatrix = lightProjection * lightView; + // RenderScene(); + depthMap.unbind(); + +} diff --git a/src/Shadows.h b/src/Shadows.h new file mode 100644 index 0000000..bbe6fd7 --- /dev/null +++ b/src/Shadows.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Framebuffer.h" + +class Shadows { + +public: + + Shadows(); + + void calculate(); + +private: + + DepthMap depthMap; + + const int SHADOW_RES = 1024; + +}; \ No newline at end of file