diff --git a/imgui.ini b/imgui.ini index ebf8c46..e90789c 100644 --- a/imgui.ini +++ b/imgui.ini @@ -9,7 +9,7 @@ Size=894,195 Collapsed=0 [Window][Debug Utils] -Pos=39,30 -Size=908,204 +Pos=25,15 +Size=863,335 Collapsed=0 diff --git a/res/shaders/basic.frag b/res/shaders/basic.frag index 9919065..3bd6e3a 100644 --- a/res/shaders/basic.frag +++ b/res/shaders/basic.frag @@ -109,7 +109,7 @@ vec3 directionalLightContribution(DirectionalLight light, vec3 normal, vec3 view vec3 ambient, diffuse, specular; computeShading(light.ambient, light.diffuse, light.specular, lightDir, viewDir, normal, ambient, diffuse, specular); - return (ambient + diffuse + specular) * 0.5f; + return (ambient + diffuse + specular) * 1.0f; } vec3 pointLightContribution(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir) { @@ -181,6 +181,7 @@ void computeShading( float computeAttenuation(vec3 lightPos, vec3 fragPos, float K_c, float K_l, float K_q) { float distanceLightFragment = length(lightPos - fragPos); - return 1.0f / (K_c + K_l * distanceLightFragment + K_q * distanceLightFragment * distanceLightFragment); + //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 new file mode 100644 index 0000000..7fc931b --- /dev/null +++ b/res/shaders/postprocessing.frag @@ -0,0 +1,20 @@ +#version 330 core + +const float GAMMA = 2.0f; + +layout(location = 0) out vec4 f_color; + +in vec2 v_tex_coords; + +uniform sampler2D u_texture; + +void main() { + + vec3 fragmentColor = vec3(texture2D(u_texture, v_tex_coords)); + + // Gamma correction + fragmentColor = pow(fragmentColor, vec3(1.0/GAMMA)); + + f_color = vec4(fragmentColor, 1.0f); + +} \ No newline at end of file diff --git a/res/shaders/postprocessing.vert b/res/shaders/postprocessing.vert new file mode 100644 index 0000000..ecd2527 --- /dev/null +++ b/res/shaders/postprocessing.vert @@ -0,0 +1,11 @@ +#version 330 core + +out vec2 v_tex_coords; + +void main() { + float x = -1.0 + float((gl_VertexID & 1) << 2); + float y = -1.0 + float((gl_VertexID & 2) << 1); + v_tex_coords.x = (x+1.0)*0.5; + v_tex_coords.y = (y+1.0)*0.5; + gl_Position = vec4(x, y, 0, 1); +} \ No newline at end of file diff --git a/res/shaders/skybox.frag b/res/shaders/skybox.frag index ba0bbdd..e13255c 100644 --- a/res/shaders/skybox.frag +++ b/res/shaders/skybox.frag @@ -8,6 +8,9 @@ uniform samplerCube u_skybox; void main() { - f_color = texture(u_skybox, v_texCoord); + + vec3 fragmentColor = vec3(texture(u_skybox, v_texCoord)); + + f_color = vec4(fragmentColor, 1.0f); } \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4723638..a66d9bf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,6 +12,7 @@ add_executable(Fall-Fever Entity.cpp Light.cpp World.cpp + Framebuffer.cpp ) target_link_libraries( diff --git a/src/Controller.cpp b/src/Controller.cpp index 6fff68e..f29205e 100644 --- a/src/Controller.cpp +++ b/src/Controller.cpp @@ -31,7 +31,6 @@ Controller::Controller() { glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_SAMPLES, 4); #ifndef _DEBUG glfwWindowHint(GLFW_MAXIMIZED, GL_TRUE); @@ -69,23 +68,25 @@ Controller::~Controller() { delete gameWindow; delete gameEventHandler; delete camera; + delete pp_framebuffer; glfwTerminate(); } void Controller::run() { - glClearColor(0.15f, 0.15f, 0.15f, 1.0f); + glClearColor(0.0015f, 0.0015f, 0.0015f, 1.0f); ShaderProgram shaderProgram("res/shaders/basic.vert", "res/shaders/basic.frag"); ShaderProgram lightProgram("res/shaders/light.vert", "res/shaders/light.frag"); ShaderProgram skyboxProgram("res/shaders/skybox.vert", "res/shaders/skybox.frag"); + ShaderProgram postProcessingProgram("res/shaders/postprocessing.vert", "res/shaders/postprocessing.frag"); - //Model model_backpack("res/models/backpack.ffo"); + Model model_backpack("res/models/backpack.ffo"); //Model model_plant("res/models/plant.ffo"); //Model model_container("res/models/container.ffo"); Model model_cube("res/models/cube.ffo"); Model model_dragon("res/models/dragon.ffo"); - Model model_ground("res/models/ground.ffo"); + Model model_ground("res/models/wood_floor.ffo"); //Model model_moon("res/models/moon.ffo"); //Model model_hut("res/models/hut.ffo"); //Model model_sphere("res/models/sphere.ffo"); @@ -96,7 +97,7 @@ void Controller::run() { //Entity hut(&model_hut, &shaderProgram); //Entity moon(&model_moon, &shaderProgram); //Entity plant(&model_plant, &shaderProgram); - Entity dragon(&model_dragon, &shaderProgram); + Entity dragon(&model_backpack, &shaderProgram); Entity ground(&model_ground, &shaderProgram); Entity lightSource(&model_cube, &lightProgram); @@ -114,6 +115,8 @@ void Controller::run() { camera->translate(glm::vec3(0.0f, 1.5f, 5.0f)); + pp_framebuffer = new Framebuffer(INIT_WINDOW_WIDTH, INIT_WINDOW_HEIGHT); + // This is the game loop while(!glfwWindowShouldClose(gameWindow->getGLFWwindow())) { // Timing @@ -123,29 +126,44 @@ void Controller::run() { // ... static bool rotateLightSource = 0; if(rotateLightSource) { - float radius = 4.0; + float radius = 25.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(1.0f), lightColor); + world.updateDirectionalLight(true, glm::vec3(-0.2f, -1.0f, -0.3f), lightColor * 0.001f); lightProgram.bind(); lightProgram.setUniform("v_lightColor", lightColor); lightProgram.unbind(); // Render and buffer swap glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + pp_framebuffer->bind(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + camera->lookForward(); camera->updateVPM(); skybox.draw(camera->getView(), camera->getProj()); - world.draw(camera->getViewProj(), camera->getPosition()); + pp_framebuffer->unbind(); + + postProcessingProgram.bind(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, pp_framebuffer->getTextureId()); + GLint location = glGetUniformLocation(postProcessingProgram.getShaderProgramId(), "u_texture"); + glUniform1i(location, 0); + GLuint temp_vao; + glGenVertexArrays(1, &temp_vao); + glBindVertexArray(temp_vao); + glDrawArrays(GL_TRIANGLES, 0, 3); + glBindVertexArray(0); + postProcessingProgram.unbind(); #ifdef _DEBUG - renderImGui(world.getEntities(), &lightColor, &rotateLightSource); + renderImGui(world.getEntities(), &world.getPointLights()[0], &lightColor, &rotateLightSource); #endif glfwSwapBuffers(gameWindow->getGLFWwindow()); @@ -196,10 +214,13 @@ void Controller::error_callback(int error, const char* description) { void Controller::updateWindowSize() { camera->updateAspectRatio(gameWindow->getWindowAspectRatio()); gameEventHandler->setFirstMouseInput(1); + + delete pp_framebuffer; + pp_framebuffer = new Framebuffer(gameWindow->getWindowWidth(), gameWindow->getWindowHeight()); } #ifdef _DEBUG -void Controller::renderImGui(std::vector *entites, glm::vec3 *lightColor, bool *rotateLightSource) { +void Controller::renderImGui(std::vector *entites, PointLight *pointLight, glm::vec3 *lightColor, bool *rotateLightSource) { ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); @@ -210,18 +231,27 @@ void Controller::renderImGui(std::vector *entites, glm::vec3 *lightColor ImGui::Text("Dragon"); static float rotation = 0.0; ImGui::SliderFloat("Rotation", &rotation, 0, 2 * M_PI); - static float translation[] = {0.0f, 0.0f}; - ImGui::SliderFloat2("Position", translation, -4.0, 4.0); + static float translation[] = {0.0f, 0.0f, 0.0f}; + ImGui::SliderFloat3("Position", translation, -4.0, 4.0); static float scale = 0.2f; ImGui::SliderFloat("Scale", &scale, 0.02, 2.0); - entites->operator[](0).setPosition(glm::vec3(translation[0], 0.0f, translation[1])); + entites->operator[](0).setPosition(glm::vec3(translation[0], translation[1], translation[2])); entites->operator[](0).setRotation(glm::vec3(0.f,1.0f,0.f), rotation); entites->operator[](0).setScale(scale); // color picker - ImGui::Text("Light Source"); + 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); + + pointLight->setParameters(K_c, K_l, K_q); + static float color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + ImGui::Text("Color"); ImGui::ColorEdit3("Color", color); lightColor->x = color[0]; lightColor->y = color[1]; diff --git a/src/Controller.h b/src/Controller.h index dfcf5e3..f0d5aa3 100644 --- a/src/Controller.h +++ b/src/Controller.h @@ -8,6 +8,8 @@ #include "ShaderProgram.h" #include "Entity.h" #include "defines.h" +#include "Light.h" +#include "Framebuffer.h" class Controller { @@ -26,12 +28,14 @@ private: void updateWindowSize(); - void renderImGui(std::vector *entites, glm::vec3 *lightColor, bool *rotateLightSource); + void renderImGui(std::vector *entites, PointLight *pointLight, glm::vec3 *lightColor, bool *rotateLightSource); Window *gameWindow; EventHandler *gameEventHandler; Camera *camera; + Framebuffer *pp_framebuffer; + const uint16_t MAX_FPS = 60; double deltaTime; diff --git a/src/Framebuffer.cpp b/src/Framebuffer.cpp new file mode 100644 index 0000000..a84a091 --- /dev/null +++ b/src/Framebuffer.cpp @@ -0,0 +1,39 @@ +#include "Framebuffer.h" + +#include + +Framebuffer::Framebuffer(uint32_t width, uint32_t height) { + + glGenFramebuffers(1, &FBO); + + glGenTextures(2, textures); + + glBindTexture(GL_TEXTURE_2D, textures[0]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glBindTexture(GL_TEXTURE_2D, textures[1]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, width, height, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, 0); + + bind(); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, textures[1], 0); + unbind(); +} + +Framebuffer::~Framebuffer() { + glDeleteFramebuffers(1, &FBO); + glDeleteTextures(2, textures); +} + +void Framebuffer::bind() { + glBindFramebuffer(GL_FRAMEBUFFER, FBO); +} + +void Framebuffer::unbind() { + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} diff --git a/src/Framebuffer.h b/src/Framebuffer.h new file mode 100644 index 0000000..bef9ff5 --- /dev/null +++ b/src/Framebuffer.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +class Framebuffer { + +public: + + Framebuffer(uint32_t width, uint32_t height); + ~Framebuffer(); + + void bind(); + void unbind(); + + GLuint getTextureId() { + return textures[0]; + } + +private: + + GLuint FBO; + GLuint textures[2]; + +}; \ No newline at end of file diff --git a/src/Light.cpp b/src/Light.cpp index 8c745ef..466b6ac 100644 --- a/src/Light.cpp +++ b/src/Light.cpp @@ -45,9 +45,9 @@ void DirectionalLight::update() { shaderProgram->setUniform("u_directionalLight.isActive", isActive); shaderProgram->setUniform("u_directionalLight.direction", direction); - shaderProgram->setUniform("u_directionalLight.ambient", ambientColor * 0.25f); - shaderProgram->setUniform("u_directionalLight.diffuse", diffuseColor * 0.25f); - shaderProgram->setUniform("u_directionalLight.specular", specularColor * 0.25f); + shaderProgram->setUniform("u_directionalLight.ambient", ambientColor); + shaderProgram->setUniform("u_directionalLight.diffuse", diffuseColor); + shaderProgram->setUniform("u_directionalLight.specular", specularColor); shaderProgram->unbind(); diff --git a/src/Light.h b/src/Light.h index a7770a1..32f4cbc 100644 --- a/src/Light.h +++ b/src/Light.h @@ -19,7 +19,7 @@ public: void setColor(glm::vec3 color) { lightColor = color; diffuseColor = lightColor * glm::vec3(1.0f); - ambientColor = diffuseColor * glm::vec3(0.1f); + ambientColor = diffuseColor * glm::vec3(0.002f); specularColor = lightColor * glm::vec3(1.0f); update(); } @@ -29,6 +29,8 @@ public: update(); } + glm::vec3 getColor() { return lightColor; } + protected: Light() = default; @@ -58,6 +60,8 @@ 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 setId(unsigned int id) { lightId = id; } @@ -90,8 +94,6 @@ private: void update() override; - bool isActive = true; - - glm::vec3 direction = glm::vec3(-0.2f, -1.0f, -0.3f); + glm::vec3 direction; }; diff --git a/src/Texture.cpp b/src/Texture.cpp index 13624da..7b762e0 100644 --- a/src/Texture.cpp +++ b/src/Texture.cpp @@ -28,7 +28,10 @@ Texture::Texture(const char* texturePath, uint8_t textureType) { return; } - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureBuffer); + if(textureType == texture_diffuse) + glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureBuffer); + else + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureBuffer); //glGenerateMipmap(GL_TEXTURE_2D); stbi_image_free(textureBuffer); @@ -102,7 +105,7 @@ CubeMap::CubeMap(const char* texturePseudoPath) { return; } - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureBuffer); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_SRGB8_ALPHA8, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureBuffer); stbi_image_free(textureBuffer); diff --git a/src/Window.cpp b/src/Window.cpp index feef9d1..86e5c05 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -42,6 +42,9 @@ Window::Window() { #endif setCatchedCursor(mouseCatched); + // Enable primitive gamma correction + // glEnable(GL_FRAMEBUFFER_SRGB); + // Maximize in release build #ifndef _DEBUG glfwMaximizeWindow(window); diff --git a/src/World.h b/src/World.h index 811365f..9763a44 100644 --- a/src/World.h +++ b/src/World.h @@ -21,6 +21,8 @@ public: std::vector * getEntities() { return &entities; } + PointLight * getPointLights() { return pointLights; } + void draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition); private: