diff --git a/src/5.advanced_lighting/6.hdr/hdr.cpp b/src/5.advanced_lighting/6.hdr/hdr.cpp index 3d0066d..a4dd49c 100644 --- a/src/5.advanced_lighting/6.hdr/hdr.cpp +++ b/src/5.advanced_lighting/6.hdr/hdr.cpp @@ -26,7 +26,7 @@ const unsigned int SCR_WIDTH = 1280; const unsigned int SCR_HEIGHT = 720; bool hdr = true; bool hdrKeyPressed = false; -float exposure = 0.1; +float exposure = 1.0f; // camera Camera camera(glm::vec3(0.0f, 0.0f, 5.0f)); @@ -85,13 +85,6 @@ int main() // ------------- unsigned int woodTexture = loadTexture(FileSystem::getPath("resources/textures/wood.png").c_str(), true); // note that we're loading the texture as an SRGB texture - // shader configuration - // -------------------- - shader.use(); - shader.setInt("diffuseTexture", 0); - hdrShader.use(); - hdrShader.setInt("hdrBuffer", 0); - // configure floating point framebuffer // ------------------------------------ unsigned int hdrFBO; @@ -131,6 +124,13 @@ int main() lightColors.push_back(glm::vec3(0.0f, 0.0f, 0.2f)); lightColors.push_back(glm::vec3(0.0f, 0.1f, 0.0f)); + // shader configuration + // -------------------- + shader.use(); + shader.setInt("diffuseTexture", 0); + hdrShader.use(); + hdrShader.setInt("hdrBuffer", 0); + // render loop // ----------- while (!glfwWindowShouldClose(window)) @@ -171,7 +171,7 @@ int main() // render tunnel glm::mat4 model = glm::mat4(); model = glm::translate(model, glm::vec3(0.0f, 0.0f, 25.0)); - model = glm::scale(model, glm::vec3(2.5f, 2.5f, 22.5f)); + model = glm::scale(model, glm::vec3(2.5f, 2.5f, 27.5f)); shader.setMat4("model", model); shader.setInt("inverse_normals", true); renderCube(); diff --git a/src/5.advanced_lighting/7.bloom/7.bloom.fs b/src/5.advanced_lighting/7.bloom/7.bloom.fs index 84a5c29..dcb9eb4 100644 --- a/src/5.advanced_lighting/7.bloom/7.bloom.fs +++ b/src/5.advanced_lighting/7.bloom/7.bloom.fs @@ -21,29 +21,29 @@ void main() { vec3 color = texture(diffuseTexture, fs_in.TexCoords).rgb; vec3 normal = normalize(fs_in.Normal); - // Ambient + // ambient vec3 ambient = 0.0 * color; - // Lighting - vec3 lighting = vec3(0.0f); + // lighting + vec3 lighting = vec3(0.0); vec3 viewDir = normalize(viewPos - fs_in.FragPos); for(int i = 0; i < 4; i++) { - // Diffuse + // diffuse vec3 lightDir = normalize(lights[i].Position - fs_in.FragPos); float diff = max(dot(lightDir, normal), 0.0); vec3 result = lights[i].Color * diff * color; - // Attenuation (use quadratic as we have gamma correction) + // attenuation (use quadratic as we have gamma correction) float distance = length(fs_in.FragPos - lights[i].Position); result *= 1.0 / (distance * distance); lighting += result; } vec3 result = ambient + lighting; - // Check whether result is higher than some threshold, if so, output as bloom threshold color + // check whether result is higher than some threshold, if so, output as bloom threshold color float brightness = dot(result, vec3(0.2126, 0.7152, 0.0722)); if(brightness > 1.0) BrightColor = vec4(result, 1.0); // else // BloomColor = vec4(0.0, 0.0, 0.0, 1.0); - FragColor = vec4(result, 1.0f); + FragColor = vec4(result, 1.0); } \ No newline at end of file diff --git a/src/5.advanced_lighting/7.bloom/7.bloom.vs b/src/5.advanced_lighting/7.bloom/7.bloom.vs index 400d350..0548593 100644 --- a/src/5.advanced_lighting/7.bloom/7.bloom.vs +++ b/src/5.advanced_lighting/7.bloom/7.bloom.vs @@ -1,7 +1,7 @@ #version 330 core -layout (location = 0) in vec3 position; -layout (location = 1) in vec3 normal; -layout (location = 2) in vec2 texCoords; +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; out VS_OUT { vec3 FragPos; @@ -15,10 +15,11 @@ uniform mat4 model; void main() { - gl_Position = projection * view * model * vec4(position, 1.0f); - vs_out.FragPos = vec3(model * vec4(position, 1.0)); - vs_out.TexCoords = texCoords; + vs_out.FragPos = vec3(model * vec4(aPos, 1.0)); + vs_out.TexCoords = aTexCoords; mat3 normalMatrix = transpose(inverse(mat3(model))); - vs_out.Normal = normalize(normalMatrix * normal); + vs_out.Normal = normalize(normalMatrix * aNormal); + + gl_Position = projection * view * model * vec4(aPos, 1.0); } \ No newline at end of file diff --git a/src/5.advanced_lighting/7.bloom/7.bloom_final.fs b/src/5.advanced_lighting/7.bloom/7.bloom_final.fs index ee435c7..c09f11e 100644 --- a/src/5.advanced_lighting/7.bloom/7.bloom_final.fs +++ b/src/5.advanced_lighting/7.bloom/7.bloom_final.fs @@ -1,5 +1,6 @@ #version 330 core out vec4 FragColor; + in vec2 TexCoords; uniform sampler2D scene; @@ -18,5 +19,5 @@ void main() vec3 result = vec3(1.0) - exp(-hdrColor * exposure); // also gamma correct while we're at it result = pow(result, vec3(1.0 / gamma)); - FragColor = vec4(result, 1.0f); + FragColor = vec4(result, 1.0); } \ No newline at end of file diff --git a/src/5.advanced_lighting/7.bloom/7.bloom_final.vs b/src/5.advanced_lighting/7.bloom/7.bloom_final.vs index 819c18d..9f93e29 100644 --- a/src/5.advanced_lighting/7.bloom/7.bloom_final.vs +++ b/src/5.advanced_lighting/7.bloom/7.bloom_final.vs @@ -1,11 +1,11 @@ #version 330 core -layout (location = 0) in vec3 position; -layout (location = 1) in vec2 texCoords; +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTexCoords; out vec2 TexCoords; void main() { - gl_Position = vec4(position, 1.0f); - TexCoords = texCoords; + TexCoords = aTexCoords; + gl_Position = vec4(aPos, 1.0); } \ No newline at end of file diff --git a/src/5.advanced_lighting/7.bloom/7.blur.fs b/src/5.advanced_lighting/7.bloom/7.blur.fs index 7152ba4..c876037 100644 --- a/src/5.advanced_lighting/7.bloom/7.blur.fs +++ b/src/5.advanced_lighting/7.bloom/7.blur.fs @@ -1,5 +1,6 @@ #version 330 core out vec4 FragColor; + in vec2 TexCoords; uniform sampler2D image; diff --git a/src/5.advanced_lighting/7.bloom/7.blur.vs b/src/5.advanced_lighting/7.bloom/7.blur.vs index 819c18d..9f93e29 100644 --- a/src/5.advanced_lighting/7.bloom/7.blur.vs +++ b/src/5.advanced_lighting/7.bloom/7.blur.vs @@ -1,11 +1,11 @@ #version 330 core -layout (location = 0) in vec3 position; -layout (location = 1) in vec2 texCoords; +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTexCoords; out vec2 TexCoords; void main() { - gl_Position = vec4(position, 1.0f); - TexCoords = texCoords; + TexCoords = aTexCoords; + gl_Position = vec4(aPos, 1.0); } \ No newline at end of file diff --git a/src/5.advanced_lighting/7.bloom/bloom.cpp b/src/5.advanced_lighting/7.bloom/bloom.cpp index e75452b..b097b03 100644 --- a/src/5.advanced_lighting/7.bloom/bloom.cpp +++ b/src/5.advanced_lighting/7.bloom/bloom.cpp @@ -1,482 +1,540 @@ -// GLEW -#define GLEW_STATIC -#include - -// GLFW +#include #include +#include -// GL includes -#include -#include - -// GLM Mathemtics #include #include #include -// Other Libs -#include #include +#include +#include +#include -// Properties -const GLuint SCR_WIDTH = 800, SCR_HEIGHT = 600; +#include -// Function prototypes -void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode); -void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); +void framebuffer_size_callback(GLFWwindow* window, int width, int height); void mouse_callback(GLFWwindow* window, double xpos, double ypos); -void Do_Movement(); -GLuint loadTexture(GLchar const * path); -void RenderScene(Shader &shader); -void RenderCube(); -void RenderQuad(); +void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); +void processInput(GLFWwindow *window); +unsigned int loadTexture(const char *path, bool gammaCorrection); +void renderQuad(); +void renderCube(); -// Camera +// settings +const unsigned int SCR_WIDTH = 1280; +const unsigned int SCR_HEIGHT = 720; +bool bloom = true; +bool bloomKeyPressed = false; +float exposure = 1.0f; + +// camera Camera camera(glm::vec3(0.0f, 0.0f, 5.0f)); +float lastX = (float)SCR_WIDTH / 2.0; +float lastY = (float)SCR_HEIGHT / 2.0; +bool firstMouse = true; -// Delta -GLfloat deltaTime = 0.0f; -GLfloat lastFrame = 0.0f; +// timing +float deltaTime = 0.0f; +float lastFrame = 0.0f; -// Options -GLboolean bloom = true; // Change with 'Space' -GLfloat exposure = 1.0f; // Change with Q and E - -// The MAIN function, from here we start our application and run our Game loop int main() { - // Init GLFW - glfwInit(); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); + // glfw: initialize and configure + // ------------------------------ + glfwInit(); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", nullptr, nullptr); // Windowed - glfwMakeContextCurrent(window); + // glfw window creation + // -------------------- + GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL); + glfwMakeContextCurrent(window); + if (window == NULL) + { + std::cout << "Failed to create GLFW window" << std::endl; + glfwTerminate(); + return -1; + } + glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); + glfwSetCursorPosCallback(window, mouse_callback); + glfwSetScrollCallback(window, scroll_callback); - // Set the required callback functions - glfwSetKeyCallback(window, key_callback); - glfwSetCursorPosCallback(window, mouse_callback); - glfwSetScrollCallback(window, scroll_callback); + // tell GLFW to capture our mouse + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); - // Options - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + // glad: load all OpenGL function pointers + // --------------------------------------- + if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) + { + std::cout << "Failed to initialize GLAD" << std::endl; + return -1; + } - // Initialize GLEW to setup the OpenGL Function pointers - glewExperimental = GL_TRUE; - glewInit(); + // configure global opengl state + // ----------------------------- + glEnable(GL_DEPTH_TEST); - // Define the viewport dimensions - glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); + // build and compile shaders + // ------------------------- + Shader shader("7.bloom.vs", "7.bloom.fs"); + Shader shaderLight("7.bloom.vs", "7.light_box.fs"); + Shader shaderBlur("7.blur.vs", "7.blur.fs"); + Shader shaderBloomFinal("7.bloom_final.vs", "7.bloom_final.fs"); - // Setup some OpenGL options - glEnable(GL_DEPTH_TEST); + // load textures + // ------------- + unsigned int woodTexture = loadTexture(FileSystem::getPath("resources/textures/wood.png").c_str(), true); // note that we're loading the texture as an SRGB texture + unsigned int containerTexture = loadTexture(FileSystem::getPath("resources/textures/container2.png").c_str(), true); // note that we're loading the texture as an SRGB texture - // Setup and compile our shaders - Shader shader("bloom.vs", "bloom.frag"); - Shader shaderLight("bloom.vs", "light_box.frag"); - Shader shaderBlur("blur.vs", "blur.frag"); - Shader shaderBloomFinal("bloom_final.vs", "bloom_final.frag"); + // configure (floating point) framebuffers + // --------------------------------------- + unsigned int hdrFBO; + glGenFramebuffers(1, &hdrFBO); + glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO); + // create 2 floating point color buffers (1 for normal rendering, other for brightness treshold values) + unsigned int colorBuffers[2]; + glGenTextures(2, colorBuffers); + for (unsigned int i = 0; i < 2; i++) + { + glBindTexture(GL_TEXTURE_2D, colorBuffers[i]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // we clamp to the edge as the blur filter would otherwise sample repeated texture values! + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + // attach texture to framebuffer + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, colorBuffers[i], 0); + } + // create and attach depth buffer (renderbuffer) + unsigned int rboDepth; + glGenRenderbuffers(1, &rboDepth); + glBindRenderbuffer(GL_RENDERBUFFER, rboDepth); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, SCR_WIDTH, SCR_HEIGHT); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth); + // tell OpenGL which color attachments we'll use (of this framebuffer) for rendering + unsigned int attachments[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; + glDrawBuffers(2, attachments); + // finally check if framebuffer is complete + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + std::cout << "Framebuffer not complete!" << std::endl; + glBindFramebuffer(GL_FRAMEBUFFER, 0); - // Set samplers - shaderBloomFinal.Use(); - glUniform1i(glGetUniformLocation(shaderBloomFinal.Program, "scene"), 0); - glUniform1i(glGetUniformLocation(shaderBloomFinal.Program, "bloomBlur"), 1); + // ping-pong-framebuffer for blurring + unsigned int pingpongFBO[2]; + unsigned int pingpongColorbuffers[2]; + glGenFramebuffers(2, pingpongFBO); + glGenTextures(2, pingpongColorbuffers); + for (unsigned int i = 0; i < 2; i++) + { + glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[i]); + glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[i]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // we clamp to the edge as the blur filter would otherwise sample repeated texture values! + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pingpongColorbuffers[i], 0); + // also check if framebuffers are complete (no need for depth buffer) + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + std::cout << "Framebuffer not complete!" << std::endl; + } - // Light sources - // - Positions - std::vector lightPositions; - lightPositions.push_back(glm::vec3(0.0f, 0.5f, 1.5f)); // back light - lightPositions.push_back(glm::vec3(-4.0f, 0.5f, -3.0f)); - lightPositions.push_back(glm::vec3(3.0f, 0.5f, 1.0f)); - lightPositions.push_back(glm::vec3(-.8f, 2.4f, -1.0f)); - // - Colors - std::vector lightColors; - lightColors.push_back(glm::vec3(5.0f, 5.0f, 5.0f)); - lightColors.push_back(glm::vec3(5.5f, 0.0f, 0.0f)); - lightColors.push_back(glm::vec3(0.0f, 0.0f, 15.0f)); - lightColors.push_back(glm::vec3(0.0f, 1.5f, 0.0f)); + // lighting info + // ------------- + // positions + std::vector lightPositions; + lightPositions.push_back(glm::vec3( 0.0f, 0.5f, 1.5f)); + lightPositions.push_back(glm::vec3(-4.0f, 0.5f, -3.0f)); + lightPositions.push_back(glm::vec3( 3.0f, 0.5f, 1.0f)); + lightPositions.push_back(glm::vec3(-.8f, 2.4f, -1.0f)); + // colors + std::vector lightColors; + lightColors.push_back(glm::vec3(2.0f, 2.0f, 2.0f)); + lightColors.push_back(glm::vec3(1.5f, 0.0f, 0.0f)); + lightColors.push_back(glm::vec3(0.0f, 0.0f, 1.5f)); + lightColors.push_back(glm::vec3(0.0f, 1.5f, 0.0f)); - // Load textures - GLuint woodTexture = loadTexture(FileSystem::getPath("resources/textures/wood.png").c_str()); - GLuint containerTexture = loadTexture(FileSystem::getPath("resources/textures/container2.png").c_str()); - // Set up floating point framebuffer to render scene to - GLuint hdrFBO; - glGenFramebuffers(1, &hdrFBO); - glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO); - // - Create 2 floating point color buffers (1 for normal rendering, other for brightness treshold values) - GLuint colorBuffers[2]; - glGenTextures(2, colorBuffers); - for (GLuint i = 0; i < 2; i++) - { - glBindTexture(GL_TEXTURE_2D, colorBuffers[i]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // We clamp to the edge as the blur filter would otherwise sample repeated texture values! - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - // attach texture to framebuffer - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, colorBuffers[i], 0); - } - // - Create and attach depth buffer (renderbuffer) - GLuint rboDepth; - glGenRenderbuffers(1, &rboDepth); - glBindRenderbuffer(GL_RENDERBUFFER, rboDepth); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, SCR_WIDTH, SCR_HEIGHT); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth); - // - Tell OpenGL which color attachments we'll use (of this framebuffer) for rendering - GLuint attachments[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; - glDrawBuffers(2, attachments); - // - Finally check if framebuffer is complete - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - std::cout << "Framebuffer not complete!" << std::endl; - glBindFramebuffer(GL_FRAMEBUFFER, 0); + // shader configuration + // -------------------- + shader.use(); + shader.setInt("diffuseTexture", 0); + shaderBlur.use(); + shaderBlur.setInt("image", 0); + shaderBloomFinal.use(); + shaderBloomFinal.setInt("scene", 0); + shaderBloomFinal.setInt("bloomBlur", 1); - // Ping pong framebuffer for blurring - GLuint pingpongFBO[2]; - GLuint pingpongColorbuffers[2]; - glGenFramebuffers(2, pingpongFBO); - glGenTextures(2, pingpongColorbuffers); - for (GLuint i = 0; i < 2; i++) - { - glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[i]); - glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[i]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // We clamp to the edge as the blur filter would otherwise sample repeated texture values! - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pingpongColorbuffers[i], 0); - // Also check if framebuffers are complete (no need for depth buffer) - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - std::cout << "Framebuffer not complete!" << std::endl; - } + // render loop + // ----------- + while (!glfwWindowShouldClose(window)) + { + // per-frame time logic + // -------------------- + float currentFrame = glfwGetTime(); + deltaTime = currentFrame - lastFrame; + lastFrame = currentFrame; - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + // input + // ----- + processInput(window); - // Game loop - while (!glfwWindowShouldClose(window)) - { - // Set frame time - GLfloat currentFrame = glfwGetTime(); - deltaTime = currentFrame - lastFrame; - lastFrame = currentFrame; + // render + // ------ + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - // Check and call events - glfwPollEvents(); - Do_Movement(); + // 1. render scene into floating point framebuffer + // ----------------------------------------------- + glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); + glm::mat4 view = camera.GetViewMatrix(); + glm::mat4 model; + shader.use(); + shader.setMat4("projection", projection); + shader.setMat4("view", view); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, woodTexture); + // set lighting uniforms + for (unsigned int i = 0; i < lightPositions.size(); i++) + { + shader.setVec3("lights[" + std::to_string(i) + "].Position", lightPositions[i]); + shader.setVec3("lights[" + std::to_string(i) + "].Color", lightColors[i]); + } + shader.setVec3("viewPos", camera.Position); + // create one large cube that acts as the floor + model = glm::mat4(); + model = glm::translate(model, glm::vec3(0.0f, -1.0f, 0.0)); + model = glm::scale(model, glm::vec3(12.5f, 0.5f, 12.5f)); + shader.setMat4("model", model); + shader.setMat4("model", model); + renderCube(); + // then create multiple cubes as the scenery + glBindTexture(GL_TEXTURE_2D, containerTexture); + model = glm::mat4(); + model = glm::translate(model, glm::vec3(0.0f, 1.5f, 0.0)); + model = glm::scale(model, glm::vec3(0.5f)); + shader.setMat4("model", model); + renderCube(); - // 1. Render scene into floating point framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)SCR_WIDTH / (GLfloat)SCR_HEIGHT, 0.1f, 100.0f); - glm::mat4 view = camera.GetViewMatrix(); - glm::mat4 model; - shader.Use(); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, woodTexture); - // - set lighting uniforms - for (GLuint i = 0; i < lightPositions.size(); i++) - { - glUniform3fv(glGetUniformLocation(shader.Program, ("lights[" + std::to_string(i) + "].Position").c_str()), 1, &lightPositions[i][0]); - glUniform3fv(glGetUniformLocation(shader.Program, ("lights[" + std::to_string(i) + "].Color").c_str()), 1, &lightColors[i][0]); - } - glUniform3fv(glGetUniformLocation(shader.Program, "viewPos"), 1, &camera.Position[0]); - // - create one large cube that acts as the floor - model = glm::mat4(); - model = glm::translate(model, glm::vec3(0.0f, -1.0f, 0.0)); - model = glm::scale(model, glm::vec3(25.0f, 1.0f, 25.0f)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - RenderCube(); - // - then create multiple cubes as the scenery - glBindTexture(GL_TEXTURE_2D, containerTexture); - model = glm::mat4(); - model = glm::translate(model, glm::vec3(0.0f, 1.5f, 0.0)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - RenderCube(); - model = glm::mat4(); - model = glm::translate(model, glm::vec3(2.0f, 0.0f, 1.0)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - RenderCube(); - model = glm::mat4(); - model = glm::translate(model, glm::vec3(-1.0f, -1.0f, 2.0)); - model = glm::rotate(model, 60.0f, glm::normalize(glm::vec3(1.0, 0.0, 1.0))); - model = glm::scale(model, glm::vec3(2.0)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - RenderCube(); - model = glm::mat4(); - model = glm::translate(model, glm::vec3(0.0f, 2.7f, 4.0)); - model = glm::rotate(model, 23.0f, glm::normalize(glm::vec3(1.0, 0.0, 1.0))); - model = glm::scale(model, glm::vec3(2.5)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - RenderCube(); - model = glm::mat4(); - model = glm::translate(model, glm::vec3(-2.0f, 1.0f, -3.0)); - model = glm::rotate(model, 124.0f, glm::normalize(glm::vec3(1.0, 0.0, 1.0))); - model = glm::scale(model, glm::vec3(2.0)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - RenderCube(); - RenderCube(); - model = glm::mat4(); - model = glm::translate(model, glm::vec3(-3.0f, 0.0f, 0.0)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - RenderCube(); - // - finally show all the light sources as bright cubes - shaderLight.Use(); - glUniformMatrix4fv(glGetUniformLocation(shaderLight.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); - glUniformMatrix4fv(glGetUniformLocation(shaderLight.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); + model = glm::mat4(); + model = glm::translate(model, glm::vec3(2.0f, 0.0f, 1.0)); + model = glm::scale(model, glm::vec3(0.5f)); + shader.setMat4("model", model); + renderCube(); - for (GLuint i = 0; i < lightPositions.size(); i++) - { - model = glm::mat4(); - model = glm::translate(model, glm::vec3(lightPositions[i])); - model = glm::scale(model, glm::vec3(0.5f)); - glUniformMatrix4fv(glGetUniformLocation(shaderLight.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - glUniform3fv(glGetUniformLocation(shaderLight.Program, "lightColor"), 1, &lightColors[i][0]); - RenderCube(); - } - glBindFramebuffer(GL_FRAMEBUFFER, 0); + model = glm::mat4(); + model = glm::translate(model, glm::vec3(-1.0f, -1.0f, 2.0)); + model = glm::rotate(model, glm::radians(60.0f), glm::normalize(glm::vec3(1.0, 0.0, 1.0))); + shader.setMat4("model", model); + renderCube(); - // 2. Blur bright fragments w/ two-pass Gaussian Blur - GLboolean horizontal = true, first_iteration = true; - GLuint amount = 10; - shaderBlur.Use(); - for (GLuint i = 0; i < amount; i++) - { - glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[horizontal]); - glUniform1i(glGetUniformLocation(shaderBlur.Program, "horizontal"), horizontal); - glBindTexture(GL_TEXTURE_2D, first_iteration ? colorBuffers[1] : pingpongColorbuffers[!horizontal]); // bind texture of other framebuffer (or scene if first iteration) - RenderQuad(); - horizontal = !horizontal; - if (first_iteration) - first_iteration = false; - } - glBindFramebuffer(GL_FRAMEBUFFER, 0); + model = glm::mat4(); + model = glm::translate(model, glm::vec3(0.0f, 2.7f, 4.0)); + model = glm::rotate(model, glm::radians(23.0f), glm::normalize(glm::vec3(1.0, 0.0, 1.0))); + model = glm::scale(model, glm::vec3(1.25)); + shader.setMat4("model", model); + renderCube(); - // 2. Now render floating point color buffer to 2D quad and tonemap HDR colors to default framebuffer's (clamped) color range - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - shaderBloomFinal.Use(); - glActiveTexture(GL_TEXTURE0); + model = glm::mat4(); + model = glm::translate(model, glm::vec3(-2.0f, 1.0f, -3.0)); + model = glm::rotate(model, glm::radians(124.0f), glm::normalize(glm::vec3(1.0, 0.0, 1.0))); + shader.setMat4("model", model); + renderCube(); + + model = glm::mat4(); + model = glm::translate(model, glm::vec3(-3.0f, 0.0f, 0.0)); + model = glm::scale(model, glm::vec3(0.5f)); + shader.setMat4("model", model); + renderCube(); + + // finally show all the light sources as bright cubes + shaderLight.use(); + shaderLight.setMat4("projection", projection); + shaderLight.setMat4("view", view); + + for (unsigned int i = 0; i < lightPositions.size(); i++) + { + model = glm::mat4(); + model = glm::translate(model, glm::vec3(lightPositions[i])); + model = glm::scale(model, glm::vec3(0.25f)); + shaderLight.setMat4("model", model); + shaderLight.setVec3("lightColor", lightColors[i]); + renderCube(); + } + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // 2. blur bright fragments with two-pass Gaussian Blur + // -------------------------------------------------- + bool horizontal = true, first_iteration = true; + unsigned int amount = 10; + shaderBlur.use(); + for (unsigned int i = 0; i < amount; i++) + { + glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[horizontal]); + shaderBlur.setInt("horizontal", horizontal); + glBindTexture(GL_TEXTURE_2D, first_iteration ? colorBuffers[1] : pingpongColorbuffers[!horizontal]); // bind texture of other framebuffer (or scene if first iteration) + renderQuad(); + horizontal = !horizontal; + if (first_iteration) + first_iteration = false; + } + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // 3. now render floating point color buffer to 2D quad and tonemap HDR colors to default framebuffer's (clamped) color range + // -------------------------------------------------------------------------------------------------------------------------- + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + shaderBloomFinal.use(); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, colorBuffers[0]); - //glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[!horizontal]); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[!horizontal]); - glUniform1i(glGetUniformLocation(shaderBloomFinal.Program, "bloom"), bloom); - glUniform1f(glGetUniformLocation(shaderBloomFinal.Program, "exposure"), exposure); - RenderQuad(); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[!horizontal]); + shaderBloomFinal.setInt("bloom", bloom); + shaderBloomFinal.setFloat("exposure", exposure); + renderQuad(); + std::cout << "bloom: " << (bloom ? "on" : "off") << "| exposure: " << exposure << std::endl; - // Swap the buffers - glfwSwapBuffers(window); - } + // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) + // ------------------------------------------------------------------------------- + glfwSwapBuffers(window); + glfwPollEvents(); + } - glfwTerminate(); - return 0; + glfwTerminate(); + return 0; } - -// RenderQuad() Renders a 1x1 quad in NDC, best used for framebuffer color targets -// and post-processing effects. -GLuint quadVAO = 0; -GLuint quadVBO; -void RenderQuad() +// renderCube() renders a 1x1 3D cube in NDC. +// ------------------------------------------------- +unsigned int cubeVAO = 0; +unsigned int cubeVBO = 0; +void renderCube() { - if (quadVAO == 0) - { - GLfloat quadVertices[] = { - // Positions // Texture Coords - -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, - }; - // Setup plane VAO - glGenVertexArrays(1, &quadVAO); - glGenBuffers(1, &quadVBO); - glBindVertexArray(quadVAO); - glBindBuffer(GL_ARRAY_BUFFER, quadVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); - } - glBindVertexArray(quadVAO); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glBindVertexArray(0); + // initialize (if necessary) + if (cubeVAO == 0) + { + float vertices[] = { + // back face + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right + 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left + -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, // top-left + // front face + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left + 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right + -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // top-left + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left + // left face + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right + -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-left + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left + -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-right + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right + // right face + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right + 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-right + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left + 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-left + // bottom face + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right + 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, // top-left + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left + -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-right + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right + // top face + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left + 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-right + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left + -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f // bottom-left + }; + glGenVertexArrays(1, &cubeVAO); + glGenBuffers(1, &cubeVBO); + // fill buffer + glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + // link vertex attributes + glBindVertexArray(cubeVAO); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + } + // render Cube + glBindVertexArray(cubeVAO); + glDrawArrays(GL_TRIANGLES, 0, 36); + glBindVertexArray(0); } -// RenderCube() Renders a 1x1 3D cube in NDC. -GLuint cubeVAO = 0; -GLuint cubeVBO = 0; -void RenderCube() +// renderQuad() renders a 1x1 XY quad in NDC +// ----------------------------------------- +unsigned int quadVAO = 0; +unsigned int quadVBO; +void renderQuad() { - // Initialize (if necessary) - if (cubeVAO == 0) - { - GLfloat vertices[] = { - // Back face - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // Bottom-left - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, // bottom-right - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,// top-left - // Front face - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, // bottom-right - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // top-left - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left - // Left face - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-left - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-right - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right - // Right face - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-right - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-left - // Bottom face - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, // top-left - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,// bottom-left - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-right - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right - // Top face - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,// top-left - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-right - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,// top-left - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f // bottom-left - }; - glGenVertexArrays(1, &cubeVAO); - glGenBuffers(1, &cubeVBO); - // Fill buffer - glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - // Link vertex attributes - glBindVertexArray(cubeVAO); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); - glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat))); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - } - // Render Cube - glBindVertexArray(cubeVAO); - glDrawArrays(GL_TRIANGLES, 0, 36); - glBindVertexArray(0); + if (quadVAO == 0) + { + float quadVertices[] = { + // positions // texture Coords + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + }; + // setup plane VAO + glGenVertexArrays(1, &quadVAO); + glGenBuffers(1, &quadVBO); + glBindVertexArray(quadVAO); + glBindBuffer(GL_ARRAY_BUFFER, quadVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); + } + glBindVertexArray(quadVAO); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glBindVertexArray(0); } -// This function loads a texture from file. Note: texture loading functions like these are usually -// managed by a 'Resource Manager' that manages all resources (like textures, models, audio). -// For learning purposes we'll just define it as a utility function. -GLuint loadTexture(GLchar const * path) +// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly +// --------------------------------------------------------------------------------------------------------- +void processInput(GLFWwindow *window) { - // Generate texture ID and load texture data - GLuint textureID; - glGenTextures(1, &textureID); - int width, height; - unsigned char* image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB); - // Assign texture to ID - glBindTexture(GL_TEXTURE_2D, textureID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); - glGenerateMipmap(GL_TEXTURE_2D); + if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) + glfwSetWindowShouldClose(window, true); - // Parameters - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glBindTexture(GL_TEXTURE_2D, 0); - SOIL_free_image_data(image); - return textureID; + float cameraSpeed = 2.5 * deltaTime; + if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) + camera.ProcessKeyboard(FORWARD, deltaTime); + if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) + camera.ProcessKeyboard(BACKWARD, deltaTime); + if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) + camera.ProcessKeyboard(LEFT, deltaTime); + if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) + camera.ProcessKeyboard(RIGHT, deltaTime); -} - -bool keys[1024]; -bool keysPressed[1024]; -// Moves/alters the camera positions based on user input -void Do_Movement() -{ - // Camera controls - if (keys[GLFW_KEY_W]) - camera.ProcessKeyboard(FORWARD, deltaTime); - if (keys[GLFW_KEY_S]) - camera.ProcessKeyboard(BACKWARD, deltaTime); - if (keys[GLFW_KEY_A]) - camera.ProcessKeyboard(LEFT, deltaTime); - if (keys[GLFW_KEY_D]) - camera.ProcessKeyboard(RIGHT, deltaTime); - - if (keys[GLFW_KEY_SPACE] && !keysPressed[GLFW_KEY_SPACE]) - { + if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS && !bloomKeyPressed) + { bloom = !bloom; - keysPressed[GLFW_KEY_SPACE] = true; - } + bloomKeyPressed = true; + } + if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_RELEASE) + { + bloomKeyPressed = false; + } - // Change parallax height scale - if (keys[GLFW_KEY_Q]) - exposure -= 0.5 * deltaTime; - else if (keys[GLFW_KEY_E]) - exposure += 0.5 * deltaTime; + if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) + { + if (exposure > 0.0f) + exposure -= 0.001f; + else + exposure = 0.0f; + } + else if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS) + { + exposure += 0.001f; + } } -GLfloat lastX = 400, lastY = 300; -bool firstMouse = true; -// Is called whenever a key is pressed/released via GLFW -void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) +// glfw: whenever the window size changed (by OS or user resize) this callback function executes +// --------------------------------------------------------------------------------------------- +void framebuffer_size_callback(GLFWwindow* window, int width, int height) { - if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) - glfwSetWindowShouldClose(window, GL_TRUE); - - if (key >= 0 && key <= 1024) - { - if (action == GLFW_PRESS) - keys[key] = true; - else if (action == GLFW_RELEASE) - { - keys[key] = false; - keysPressed[key] = false; - } - } + // make sure the viewport matches the new window dimensions; note that width and + // height will be significantly larger than specified on retina displays. + glViewport(0, 0, width, height); } + +// glfw: whenever the mouse moves, this callback is called +// ------------------------------------------------------- void mouse_callback(GLFWwindow* window, double xpos, double ypos) { - if (firstMouse) - { - lastX = xpos; - lastY = ypos; - firstMouse = false; - } + if (firstMouse) + { + lastX = xpos; + lastY = ypos; + firstMouse = false; + } - GLfloat xoffset = xpos - lastX; - GLfloat yoffset = lastY - ypos; + float xoffset = xpos - lastX; + float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top - lastX = xpos; - lastY = ypos; + lastX = xpos; + lastY = ypos; - camera.ProcessMouseMovement(xoffset, yoffset); + camera.ProcessMouseMovement(xoffset, yoffset); } +// glfw: whenever the mouse scroll wheel scrolls, this callback is called +// ---------------------------------------------------------------------- void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { - camera.ProcessMouseScroll(yoffset); + camera.ProcessMouseScroll(yoffset); +} + +// utility function for loading a 2D texture from file +// --------------------------------------------------- +unsigned int loadTexture(char const * path, bool gammaCorrection) +{ + unsigned int textureID; + glGenTextures(1, &textureID); + + int width, height, nrComponents; + unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0); + if (data) + { + GLenum internalFormat; + GLenum dataFormat; + if (nrComponents == 1) + { + internalFormat = dataFormat = GL_RED; + } + else if (nrComponents == 3) + { + internalFormat = gammaCorrection ? GL_SRGB : GL_RGB; + dataFormat = GL_RGB; + } + else if (nrComponents == 4) + { + internalFormat = gammaCorrection ? GL_SRGB_ALPHA : GL_RGBA; + dataFormat = GL_RGBA; + } + + glBindTexture(GL_TEXTURE_2D, textureID); + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, dataFormat, GL_UNSIGNED_BYTE, data); + glGenerateMipmap(GL_TEXTURE_2D); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + stbi_image_free(data); + } + else + { + std::cout << "Texture failed to load at path: " << path << std::endl; + stbi_image_free(data); + } + + return textureID; } \ No newline at end of file