From 20d5811d61fac6bf66ac04a1380535d76d065d7b Mon Sep 17 00:00:00 2001 From: Joey de Vries Date: Sun, 23 Apr 2017 22:43:48 +0200 Subject: [PATCH] Code re-work: HDR --- .../4.normal_mapping/normal_mapping.cpp | 3 +- .../5.1.parallax_mapping/parallax_mapping.cpp | 3 +- .../steep_parallax_mapping.cpp | 3 +- .../parallax_occlusion_mapping.cpp | 3 +- src/5.advanced_lighting/6.hdr/6.hdr.fs | 7 +- src/5.advanced_lighting/6.hdr/6.hdr.vs | 8 +- src/5.advanced_lighting/6.hdr/6.lighting.fs | 12 +- src/5.advanced_lighting/6.hdr/6.lighting.vs | 15 +- src/5.advanced_lighting/6.hdr/hdr.cpp | 557 ++++++++++-------- 9 files changed, 332 insertions(+), 279 deletions(-) diff --git a/src/5.advanced_lighting/4.normal_mapping/normal_mapping.cpp b/src/5.advanced_lighting/4.normal_mapping/normal_mapping.cpp index 4f2139f..39f08bb 100644 --- a/src/5.advanced_lighting/4.normal_mapping/normal_mapping.cpp +++ b/src/5.advanced_lighting/4.normal_mapping/normal_mapping.cpp @@ -145,7 +145,8 @@ int main() return 0; } -// renderQuad() renders a 1x1 quad in NDC +// renders a 1x1 quad in NDC with manually calculated tangent vectors +// ------------------------------------------------------------------ unsigned int quadVAO = 0; unsigned int quadVBO; void renderQuad() diff --git a/src/5.advanced_lighting/5.1.parallax_mapping/parallax_mapping.cpp b/src/5.advanced_lighting/5.1.parallax_mapping/parallax_mapping.cpp index a39661d..2781c18 100644 --- a/src/5.advanced_lighting/5.1.parallax_mapping/parallax_mapping.cpp +++ b/src/5.advanced_lighting/5.1.parallax_mapping/parallax_mapping.cpp @@ -155,7 +155,8 @@ int main() return 0; } -// renderQuad() renders a 1x1 quad in NDC +// renders a 1x1 quad in NDC with manually calculated tangent vectors +// ------------------------------------------------------------------ unsigned int quadVAO = 0; unsigned int quadVBO; void renderQuad() diff --git a/src/5.advanced_lighting/5.2.steep_parallax_mapping/steep_parallax_mapping.cpp b/src/5.advanced_lighting/5.2.steep_parallax_mapping/steep_parallax_mapping.cpp index 81439a5..a409a10 100644 --- a/src/5.advanced_lighting/5.2.steep_parallax_mapping/steep_parallax_mapping.cpp +++ b/src/5.advanced_lighting/5.2.steep_parallax_mapping/steep_parallax_mapping.cpp @@ -155,7 +155,8 @@ int main() return 0; } -// renderQuad() renders a 1x1 quad in NDC +// renders a 1x1 quad in NDC with manually calculated tangent vectors +// ------------------------------------------------------------------ unsigned int quadVAO = 0; unsigned int quadVBO; void renderQuad() diff --git a/src/5.advanced_lighting/5.3.parallax_occlusion_mapping/parallax_occlusion_mapping.cpp b/src/5.advanced_lighting/5.3.parallax_occlusion_mapping/parallax_occlusion_mapping.cpp index e6101ef..7d978d2 100644 --- a/src/5.advanced_lighting/5.3.parallax_occlusion_mapping/parallax_occlusion_mapping.cpp +++ b/src/5.advanced_lighting/5.3.parallax_occlusion_mapping/parallax_occlusion_mapping.cpp @@ -155,7 +155,8 @@ int main() return 0; } -// renderQuad() renders a 1x1 quad in NDC +// renders a 1x1 quad in NDC with manually calculated tangent vectors +// ------------------------------------------------------------------ unsigned int quadVAO = 0; unsigned int quadVBO; void renderQuad() diff --git a/src/5.advanced_lighting/6.hdr/6.hdr.fs b/src/5.advanced_lighting/6.hdr/6.hdr.fs index 7c901b8..b178541 100644 --- a/src/5.advanced_lighting/6.hdr/6.hdr.fs +++ b/src/5.advanced_lighting/6.hdr/6.hdr.fs @@ -1,5 +1,6 @@ #version 330 core -out vec4 color; +out vec4 FragColor; + in vec2 TexCoords; uniform sampler2D hdrBuffer; @@ -18,11 +19,11 @@ 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)); - color = vec4(result, 1.0f); + FragColor = vec4(result, 1.0); } else { vec3 result = pow(hdrColor, vec3(1.0 / gamma)); - color = vec4(result, 1.0); + FragColor = vec4(result, 1.0); } } \ No newline at end of file diff --git a/src/5.advanced_lighting/6.hdr/6.hdr.vs b/src/5.advanced_lighting/6.hdr/6.hdr.vs index 819c18d..9f93e29 100644 --- a/src/5.advanced_lighting/6.hdr/6.hdr.vs +++ b/src/5.advanced_lighting/6.hdr/6.hdr.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/6.hdr/6.lighting.fs b/src/5.advanced_lighting/6.hdr/6.lighting.fs index 8cf2e67..ef4809a 100644 --- a/src/5.advanced_lighting/6.hdr/6.lighting.fs +++ b/src/5.advanced_lighting/6.hdr/6.lighting.fs @@ -20,22 +20,22 @@ 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); for(int i = 0; i < 16; i++) { - // Diffuse + // diffuse vec3 lightDir = normalize(lights[i].Position - fs_in.FragPos); float diff = max(dot(lightDir, normal), 0.0); vec3 diffuse = lights[i].Color * diff * color; vec3 result = diffuse; - // 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; } - FragColor = vec4(ambient + lighting, 1.0f); + FragColor = vec4(ambient + lighting, 1.0); } \ No newline at end of file diff --git a/src/5.advanced_lighting/6.hdr/6.lighting.vs b/src/5.advanced_lighting/6.hdr/6.lighting.vs index bb012d7..fc085e4 100644 --- a/src/5.advanced_lighting/6.hdr/6.lighting.vs +++ b/src/5.advanced_lighting/6.hdr/6.lighting.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; @@ -17,12 +17,13 @@ uniform bool inverse_normals; 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; - vec3 n = inverse_normals ? -normal : normal; + vec3 n = inverse_normals ? -aNormal : aNormal; mat3 normalMatrix = transpose(inverse(mat3(model))); vs_out.Normal = normalize(normalMatrix * n); + + gl_Position = projection * view * model * vec4(aPos, 1.0); } \ No newline at end of file diff --git a/src/5.advanced_lighting/6.hdr/hdr.cpp b/src/5.advanced_lighting/6.hdr/hdr.cpp index a7b96ea..3d0066d 100644 --- a/src/5.advanced_lighting/6.hdr/hdr.cpp +++ b/src/5.advanced_lighting/6.hdr/hdr.cpp @@ -1,118 +1,114 @@ -// 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 hdr = true; +bool hdrKeyPressed = false; +float exposure = 0.1; + +// 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 hdr = true; // Change with 'Space' -GLfloat exposure = 1.0f; // Change with Q and E - -// Global variables -GLuint woodTexture; - -// The MAIN function, from here we start our application and run our Game loop int main() { - // Init GLFW + // 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); - glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); - GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", nullptr, nullptr); // Windowed + // glfw window creation + // -------------------- + GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL); glfwMakeContextCurrent(window); - - // Set the required callback functions - glfwSetKeyCallback(window, key_callback); + 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); - // Options + // tell GLFW to capture our mouse glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); - // Initialize GLEW to setup the OpenGL Function pointers - glewExperimental = GL_TRUE; - glewInit(); + // glad: load all OpenGL function pointers + // --------------------------------------- + if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) + { + std::cout << "Failed to initialize GLAD" << std::endl; + return -1; + } - // Define the viewport dimensions - glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); - - // Setup some OpenGL options + // configure global opengl state + // ----------------------------- glEnable(GL_DEPTH_TEST); - // Setup and compile our shaders - Shader shader("lighting.vs", "lighting.frag"); - Shader hdrShader("hdr.vs", "hdr.frag"); + // build and compile shaders + // ------------------------- + Shader shader("6.lighting.vs", "6.lighting.fs"); + Shader hdrShader("6.hdr.vs", "6.hdr.fs"); - // Light sources - // - Positions - std::vector lightPositions; - lightPositions.push_back(glm::vec3(0.0f, 0.0f, 49.5f)); // back light - lightPositions.push_back(glm::vec3(-1.4f, -1.9f, 9.0f)); - lightPositions.push_back(glm::vec3(0.0f, -1.8f, 4.0f)); - lightPositions.push_back(glm::vec3(0.8f, -1.7f, 6.0f)); - // - Colors - std::vector lightColors; - lightColors.push_back(glm::vec3(200.0f, 200.0f, 200.0f)); - lightColors.push_back(glm::vec3(0.1f, 0.0f, 0.0f)); - lightColors.push_back(glm::vec3(0.0f, 0.0f, 0.2f)); - lightColors.push_back(glm::vec3(0.0f, 0.1f, 0.0f)); + // 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 - // Load textures - woodTexture = loadTexture(FileSystem::getPath("resources/textures/wood.png").c_str()); + // shader configuration + // -------------------- + shader.use(); + shader.setInt("diffuseTexture", 0); + hdrShader.use(); + hdrShader.setInt("hdrBuffer", 0); - // Set up floating point framebuffer to render scene to - GLuint hdrFBO; + // configure floating point framebuffer + // ------------------------------------ + unsigned int hdrFBO; glGenFramebuffers(1, &hdrFBO); - // - Create floating point color buffer - GLuint colorBuffer; + // create floating point color buffer + unsigned int colorBuffer; glGenTextures(1, &colorBuffer); glBindTexture(GL_TEXTURE_2D, colorBuffer); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - // - Create depth buffer (renderbuffer) - GLuint rboDepth; + // create depth buffer (renderbuffer) + unsigned int rboDepth; glGenRenderbuffers(1, &rboDepth); glBindRenderbuffer(GL_RENDERBUFFER, rboDepth); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, SCR_WIDTH, SCR_HEIGHT); - // - Attach buffers + // attach buffers glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth); @@ -120,246 +116,247 @@ int main() std::cout << "Framebuffer not complete!" << std::endl; glBindFramebuffer(GL_FRAMEBUFFER, 0); - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + // lighting info + // ------------- + // positions + std::vector lightPositions; + lightPositions.push_back(glm::vec3( 0.0f, 0.0f, 49.5f)); // back light + lightPositions.push_back(glm::vec3(-1.4f, -1.9f, 9.0f)); + lightPositions.push_back(glm::vec3( 0.0f, -1.8f, 4.0f)); + lightPositions.push_back(glm::vec3( 0.8f, -1.7f, 6.0f)); + // colors + std::vector lightColors; + lightColors.push_back(glm::vec3(200.0f, 200.0f, 200.0f)); + lightColors.push_back(glm::vec3(0.1f, 0.0f, 0.0f)); + lightColors.push_back(glm::vec3(0.0f, 0.0f, 0.2f)); + lightColors.push_back(glm::vec3(0.0f, 0.1f, 0.0f)); - // Game loop + // render loop + // ----------- while (!glfwWindowShouldClose(window)) { - // Set frame time - GLfloat currentFrame = glfwGetTime(); + // per-frame time logic + // -------------------- + float currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; - // Check and call events - glfwPollEvents(); - Do_Movement(); + // input + // ----- + processInput(window); - // 1. Render scene into floating point framebuffer + // render + // ------ + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // 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)); + glm::mat4 view = camera.GetViewMatrix(); + shader.use(); + shader.setMat4("projection", projection); + shader.setMat4("view", view); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, woodTexture); - // - set lighting uniforms - for (GLuint i = 0; i < lightPositions.size(); i++) + // set lighting uniforms + for (unsigned int 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]); + shader.setVec3("lights[" + std::to_string(i) + "].Position", lightPositions[i]); + shader.setVec3("lights[" + std::to_string(i) + "].Color", lightColors[i]); } - glUniform3fv(glGetUniformLocation(shader.Program, "viewPos"), 1, &camera.Position[0]); - // - render tunnel - model = glm::mat4(); + shader.setVec3("viewPos", camera.Position); + // 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(5.0f, 5.0f, 55.0f)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - glUniform1i(glGetUniformLocation(shader.Program, "inverse_normals"), GL_TRUE); - RenderCube(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + model = glm::scale(model, glm::vec3(2.5f, 2.5f, 22.5f)); + shader.setMat4("model", model); + shader.setInt("inverse_normals", true); + renderCube(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); - // 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); - hdrShader.Use(); + // 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); + hdrShader.use(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, colorBuffer); - glUniform1i(glGetUniformLocation(hdrShader.Program, "hdr"), hdr); - glUniform1f(glGetUniformLocation(hdrShader.Program, "exposure"), exposure); - RenderQuad(); + hdrShader.setInt("hdr", hdr); + hdrShader.setFloat("exposure", exposure); + renderQuad(); - std::cout << "exposure: " << exposure << std::endl; + std::cout << "hdr: " << (hdr ? "on" : "off") << "| exposure: " << exposure << std::endl; - // Swap the buffers + // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) + // ------------------------------------------------------------------------------- glfwSwapBuffers(window); + glfwPollEvents(); } glfwTerminate(); return 0; } +// renderCube() renders a 1x1 3D cube in NDC. +// ------------------------------------------------- +unsigned int cubeVAO = 0; +unsigned int cubeVBO = 0; +void renderCube() +{ + // 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); +} -// RenderQuad() Renders a 1x1 quad in NDC, best used for framebuffer color targets -// and post-processing effects. -GLuint quadVAO = 0; -GLuint quadVBO; -void RenderQuad() +// renderQuad() renders a 1x1 XY quad in NDC +// ----------------------------------------- +unsigned int quadVAO = 0; +unsigned int quadVBO; +void renderQuad() { if (quadVAO == 0) { - GLfloat quadVertices[] = { - // Positions // Texture Coords - -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 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, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, }; - // Setup plane VAO + // 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); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); } glBindVertexArray(quadVAO); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindVertexArray(0); } -// RenderCube() Renders a 1x1 3D cube in NDC. -GLuint cubeVAO = 0; -GLuint cubeVBO = 0; -void RenderCube() +// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly +// --------------------------------------------------------------------------------------------------------- +void processInput(GLFWwindow *window) { - // 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 (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) + glfwSetWindowShouldClose(window, true); -// 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) -{ - // 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); - - // 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; - -} - -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]) + float cameraSpeed = 2.5 * deltaTime; + if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) camera.ProcessKeyboard(FORWARD, deltaTime); - if (keys[GLFW_KEY_S]) + if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) camera.ProcessKeyboard(BACKWARD, deltaTime); - if (keys[GLFW_KEY_A]) + if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) camera.ProcessKeyboard(LEFT, deltaTime); - if (keys[GLFW_KEY_D]) + if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) camera.ProcessKeyboard(RIGHT, deltaTime); - if (keys[GLFW_KEY_SPACE] && !keysPressed[GLFW_KEY_SPACE]) + if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS && !hdrKeyPressed) { hdr = !hdr; - keysPressed[GLFW_KEY_SPACE] = true; + hdrKeyPressed = true; } - - // Change exposure of the scene's HDR camera - if (keys[GLFW_KEY_Q]) - exposure -= 0.5 * deltaTime; - else if (keys[GLFW_KEY_E]) - exposure += 0.5 * deltaTime; -} - -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) -{ - if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) - glfwSetWindowShouldClose(window, GL_TRUE); - - if (key >= 0 && key <= 1024) + if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_RELEASE) { - if (action == GLFW_PRESS) - keys[key] = true; - else if (action == GLFW_RELEASE) - { - keys[key] = false; - keysPressed[key] = false; - } + hdrKeyPressed = false; + } + + 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; } } +// 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) +{ + // 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) @@ -369,8 +366,8 @@ void mouse_callback(GLFWwindow* window, double xpos, double 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; @@ -378,7 +375,57 @@ void mouse_callback(GLFWwindow* window, double xpos, double ypos) 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); +} + +// 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