From ecd23d4de0786f1b5dbe1d1811439f99dc064c0e Mon Sep 17 00:00:00 2001 From: Joey de Vries Date: Fri, 26 May 2017 15:00:56 +0200 Subject: [PATCH] All PBR tuts updated. --- .../ibl_irradiance_conversion.cpp | 415 +++++++-------- .../2.1.2.ibl_irradiance/ibl_irradiance.cpp | 451 ++++++++-------- src/6.pbr/2.2.1.ibl_specular/ibl_specular.cpp | 499 ++++++++---------- .../ibl_specular_textured.cpp | 68 +-- 4 files changed, 682 insertions(+), 751 deletions(-) diff --git a/src/6.pbr/2.1.1.ibl_irradiance_conversion/ibl_irradiance_conversion.cpp b/src/6.pbr/2.1.1.ibl_irradiance_conversion/ibl_irradiance_conversion.cpp index d5bbc5a..717125e 100644 --- a/src/6.pbr/2.1.1.ibl_irradiance_conversion/ibl_irradiance_conversion.cpp +++ b/src/6.pbr/2.1.1.ibl_irradiance_conversion/ibl_irradiance_conversion.cpp @@ -1,100 +1,100 @@ -// Std. Includes -#include - -// 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 "stb_image.h" +#include -// Properties -const GLuint SCR_WIDTH = 1280, SCR_HEIGHT = 720; - -// 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 scroll_callback(GLFWwindow* window, double xoffset, double yoffset); +void processInput(GLFWwindow *window); void renderSphere(); void renderCube(); // camera Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); +float lastX = 800.0f / 2.0; +float lastY = 600.0 / 2.0; +bool firstMouse = true; -// timing -GLfloat deltaTime = 0.0f; -GLfloat lastFrame = 0.0f; +float deltaTime = 0.0f; +float lastFrame = 0.0f; + +// settings +const unsigned int SCR_WIDTH = 1280; +const unsigned int SCR_HEIGHT = 720; -// The MAIN function, from here we start the application and run the Game loop int main() { - // GLFW Init - // --------- + // 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_SAMPLES, 4); - glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - 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); - - // GLFW config - // ----------- - 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); - + + // 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(); - glGetError(); + // glad: load all OpenGL function pointers + // --------------------------------------- + if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) + { + std::cout << "Failed to initialize GLAD" << std::endl; + return -1; + } - // Setup OpenGL state - // ------------------------- + // configure global opengl state + // ----------------------------- glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); // set depth function to less than AND equal for skybox depth trick. - // load and initialize shaders - // ---------------------- + // build and compile shaders + // ------------------------- Shader pbrShader("2.1.1.pbr.vs", "2.1.1.pbr.frag"); Shader equirectangularToCubemapShader("2.1.1.cubemap.vs", "2.1.1.equirectangular_to_cubemap.frag"); Shader backgroundShader("2.1.1.background.vs", "2.1.1.background.frag"); - pbrShader.Use(); - glUniform3f(glGetUniformLocation(pbrShader.Program, "albedo"), 0.5f, 0.0f, 0.0f); - glUniform1f(glGetUniformLocation(pbrShader.Program, "ao"), 1.0f); - backgroundShader.Use(); - glUniform1i(glGetUniformLocation(backgroundShader.Program, "environmentMap"), 0); + pbrShader.use(); + pbrShader.setVec3("albedo", 0.5f, 0.0f, 0.0f); + pbrShader.setFloat("ao", 1.0f); + + backgroundShader.use(); + backgroundShader.setInt("environmentMap", 0); + // lights // ------ glm::vec3 lightPositions[] = { glm::vec3(-10.0f, 10.0f, 10.0f), - glm::vec3(10.0f, 10.0f, 10.0f), + glm::vec3( 10.0f, 10.0f, 10.0f), glm::vec3(-10.0f, -10.0f, 10.0f), - glm::vec3(10.0f, -10.0f, 10.0f), + glm::vec3( 10.0f, -10.0f, 10.0f), }; glm::vec3 lightColors[] = { glm::vec3(300.0f, 300.0f, 300.0f), @@ -154,35 +154,35 @@ int main() glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // pbr: set up projection and view matrices for capturing data onto the 6 cubemap face directions // ---------------------------------------------------------------------------------------------- glm::mat4 captureProjection = glm::perspective(glm::radians(90.0f), 1.0f, 0.1f, 10.0f); - glm::mat4 captureViews[] = + glm::mat4 captureViews[] = { - glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)), + glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)), glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)), - glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)), - glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f)), - glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f, 0.0f, 1.0f), glm::vec3(0.0f, -1.0f, 0.0f)), - glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f, 0.0f, -1.0f), glm::vec3(0.0f, -1.0f, 0.0f)) + glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)), + glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f)), + glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, -1.0f, 0.0f)), + glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, -1.0f, 0.0f)) }; // pbr: convert HDR equirectangular environment map to cubemap equivalent // ---------------------------------------------------------------------- - equirectangularToCubemapShader.Use(); - glUniform1i(glGetUniformLocation(equirectangularToCubemapShader.Program, "equirectangularMap"), 0); + equirectangularToCubemapShader.use(); + equirectangularToCubemapShader.setInt("equirectangularMap", 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, hdrTexture); - glUniformMatrix4fv(glGetUniformLocation(equirectangularToCubemapShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(captureProjection)); + equirectangularToCubemapShader.setMat4("projection", captureProjection); glViewport(0, 0, 512, 512); // don't forget to configure the viewport to the capture dimensions. glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); for (unsigned int i = 0; i < 6; ++i) { - glUniformMatrix4fv(glGetUniformLocation(equirectangularToCubemapShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(captureViews[i])); + equirectangularToCubemapShader.setMat4("view", captureViews[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, envCubemap, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -193,47 +193,52 @@ int main() // initialize static shader uniforms before rendering // -------------------------------------------------- glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); - pbrShader.Use(); - glUniformMatrix4fv(glGetUniformLocation(pbrShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); - backgroundShader.Use(); - glUniformMatrix4fv(glGetUniformLocation(backgroundShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); + pbrShader.use(); + pbrShader.setMat4("projection", projection); + backgroundShader.use(); + backgroundShader.setMat4("projection", projection); - // then before rendering, configure the viewport to the actual screen dimensions - glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); + // then before rendering, configure the viewport to the original framebuffer's screen dimensions + int scrWidth, scrHeight; + glfwGetFramebufferSize(window, &scrWidth, &scrHeight); + glViewport(0, 0, scrWidth, scrHeight); - // 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); - // clear the colorbuffer - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + // render + // ------ + glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - // render scene, supplying the convoluted irradiance map to the final shader. + // render scene, supplying the convoluted irradiance map to the final shader. // ------------------------------------------------------------------------------------------ - pbrShader.Use(); + pbrShader.use(); glm::mat4 view = camera.GetViewMatrix(); - glUniformMatrix4fv(glGetUniformLocation(pbrShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); - glUniform3fv(glGetUniformLocation(pbrShader.Program, "camPos"), 1, &camera.Position[0]); + pbrShader.setMat4("view", view); + pbrShader.setVec3("camPos", camera.Position); // render rows*column number of spheres with material properties defined by textures (they all have the same material properties) glm::mat4 model; for (int row = 0; row < nrRows; ++row) { - glUniform1f(glGetUniformLocation(pbrShader.Program, "metallic"), (float)row / (float)nrRows); + pbrShader.setFloat("metallic", (float)row / (float)nrRows); for (int col = 0; col < nrColumns; ++col) { // we clamp the roughness to 0.025 - 1.0 as perfectly smooth surfaces (roughness of 0.0) tend to look a bit off // on direct lighting. - glUniform1f(glGetUniformLocation(pbrShader.Program, "roughness"), glm::clamp((float)col / (float)nrColumns, 0.05f, 1.0f)); + pbrShader.setFloat("roughness", glm::clamp((float)col / (float)nrColumns, 0.05f, 1.0f)); model = glm::mat4(); model = glm::translate(model, glm::vec3( @@ -241,11 +246,12 @@ int main() (float)(row - (nrRows / 2)) * spacing, -2.0f )); - glUniformMatrix4fv(glGetUniformLocation(pbrShader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); + pbrShader.setMat4("model", model); renderSphere(); } } + // render light source (simply re-render sphere at light positions) // this looks a bit off as we use the same shader, but it'll make their positions obvious and // keeps the codeprint small. @@ -253,40 +259,99 @@ int main() { glm::vec3 newPos = lightPositions[i] + glm::vec3(sin(glfwGetTime() * 5.0) * 5.0, 0.0, 0.0); newPos = lightPositions[i]; - glUniform3fv(glGetUniformLocation(pbrShader.Program, ("lightPositions[" + std::to_string(i) + "]").c_str()), 1, &newPos[0]);\ - glUniform3fv(glGetUniformLocation(pbrShader.Program, ("lightColors[" + std::to_string(i) + "]").c_str()), 1, &lightColors[i][0]); + pbrShader.setVec3("lightPositions[" + std::to_string(i) + "]", newPos); + pbrShader.setVec3("lightColors[" + std::to_string(i) + "]", lightColors[i]); model = glm::mat4(); model = glm::translate(model, newPos); model = glm::scale(model, glm::vec3(0.5f)); - glUniformMatrix4fv(glGetUniformLocation(pbrShader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); + pbrShader.setMat4("model", model); renderSphere(); } // render skybox (render as last to prevent overdraw) - backgroundShader.Use(); - glUniformMatrix4fv(glGetUniformLocation(backgroundShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); + backgroundShader.use(); + backgroundShader.setMat4("view", view); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap); renderCube(); - /* equirectangularToCubemapShader.Use(); - glUniformMatrix4fv(glGetUniformLocation(equirectangularToCubemapShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); + /* equirectangularToCubemapShader.Use(); + equirectangularToCubemapShader.setMat4("view", view"); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, hdrTexture); renderCube();*/ - // Swap the buffers + // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) + // ------------------------------------------------------------------------------- glfwSwapBuffers(window); + glfwPollEvents(); } + // glfw: terminate, clearing all previously allocated GLFW resources. + // ------------------------------------------------------------------ glfwTerminate(); return 0; } +// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly +// --------------------------------------------------------------------------------------------------------- +void processInput(GLFWwindow *window) +{ + if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) + glfwSetWindowShouldClose(window, true); + + 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); +} + +// 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) + { + lastX = xpos; + lastY = ypos; + firstMouse = false; + } + + float xoffset = xpos - lastX; + float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top + + lastX = xpos; + lastY = 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); +} // renders (and builds at first invocation) a sphere +// ------------------------------------------------- unsigned int sphereVAO = 0; unsigned int indexCount; void renderSphere() @@ -371,150 +436,88 @@ void renderSphere() glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW); float stride = (3 + 2 + 3) * sizeof(float); glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, (GLvoid*)(3 * sizeof(float))); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, (void*)(3 * sizeof(float))); glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)(5 * sizeof(float))); + glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, stride, (void*)(5 * sizeof(float))); } glBindVertexArray(sphereVAO); glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0); } -// RenderCube() Renders a 1x1 3D cube in NDC. -GLuint cubeVAO = 0; -GLuint cubeVBO = 0; + +// renderCube() renders a 1x1 3D cube in NDC. +// ------------------------------------------------- +unsigned int cubeVAO = 0; +unsigned int cubeVBO = 0; void renderCube() { - // Initialize (if necessary) + // initialize (if necessary) if (cubeVAO == 0) { - GLfloat 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 + 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, 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, 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 + // 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, 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 + // 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 + // fill buffer glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - // Link vertex attributes + // link vertex attributes glBindVertexArray(cubeVAO); glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); + 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(GLfloat), (GLvoid*)(6 * sizeof(GLfloat))); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } - // Render Cube + // render Cube glBindVertexArray(cubeVAO); glDrawArrays(GL_TRIANGLES, 0, 36); glBindVertexArray(0); -} - -#pragma region "User input" - -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); -} - -// 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 (action == GLFW_PRESS) - keys[key] = true; - else if (action == GLFW_RELEASE) - { - keys[key] = false; - keysPressed[key] = false; - } - } -} - -GLfloat lastX = 400, lastY = 300; -bool firstMouse = true; -// Moves/alters the camera positions based on user input -void mouse_callback(GLFWwindow* window, double xpos, double ypos) -{ - if (firstMouse) - { - lastX = xpos; - lastY = ypos; - firstMouse = false; - } - - GLfloat xoffset = xpos - lastX; - GLfloat yoffset = lastY - ypos; - - lastX = xpos; - lastY = ypos; - - camera.ProcessMouseMovement(xoffset, yoffset); -} - -void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) -{ - camera.ProcessMouseScroll(yoffset); -} - -#pragma endregion \ No newline at end of file +} \ No newline at end of file diff --git a/src/6.pbr/2.1.2.ibl_irradiance/ibl_irradiance.cpp b/src/6.pbr/2.1.2.ibl_irradiance/ibl_irradiance.cpp index 68b5a62..07614eb 100644 --- a/src/6.pbr/2.1.2.ibl_irradiance/ibl_irradiance.cpp +++ b/src/6.pbr/2.1.2.ibl_irradiance/ibl_irradiance.cpp @@ -1,102 +1,102 @@ -// Std. Includes -#include - -// 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 "stb_image.h" +#include -// Properties -const GLuint SCR_WIDTH = 1280, SCR_HEIGHT = 720; - -// 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 scroll_callback(GLFWwindow* window, double xoffset, double yoffset); +void processInput(GLFWwindow *window); void renderSphere(); void renderCube(); // camera Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); +float lastX = 800.0f / 2.0; +float lastY = 600.0 / 2.0; +bool firstMouse = true; -// timing -GLfloat deltaTime = 0.0f; -GLfloat lastFrame = 0.0f; +float deltaTime = 0.0f; +float lastFrame = 0.0f; + +// settings +const unsigned int SCR_WIDTH = 1280; +const unsigned int SCR_HEIGHT = 720; -// The MAIN function, from here we start the application and run the Game loop int main() { - // GLFW Init - // --------- + // 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_SAMPLES, 4); - glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - 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); - - // GLFW config - // ----------- - 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); + // 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(); - glGetError(); + // glad: load all OpenGL function pointers + // --------------------------------------- + if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) + { + std::cout << "Failed to initialize GLAD" << std::endl; + return -1; + } - // Setup OpenGL state - // ------------------------- + // configure global opengl state + // ----------------------------- glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); // set depth function to less than AND equal for skybox depth trick. - // load and initialize shaders - // ---------------------- + // build and compile shaders + // ------------------------- Shader pbrShader("2.1.2.pbr.vs", "2.1.2.pbr.frag"); Shader equirectangularToCubemapShader("2.1.2.cubemap.vs", "2.1.2.equirectangular_to_cubemap.frag"); Shader irradianceShader("2.1.2.cubemap.vs", "2.1.2.irradiance_convolution.frag"); Shader backgroundShader("2.1.2.background.vs", "2.1.2.background.frag"); - pbrShader.Use(); - glUniform1i(glGetUniformLocation(pbrShader.Program, "irradianceMap"), 0); - glUniform3f(glGetUniformLocation(pbrShader.Program, "albedo"), 0.5f, 0.0f, 0.0f); - glUniform1f(glGetUniformLocation(pbrShader.Program, "ao"), 1.0f); - backgroundShader.Use(); - glUniform1i(glGetUniformLocation(backgroundShader.Program, "environmentMap"), 0); + pbrShader.use(); + pbrShader.setInt("irradianceMap", 0); + pbrShader.setVec3("albedo", 0.5f, 0.0f, 0.0f); + pbrShader.setFloat("ao", 1.0f); + + backgroundShader.use(); + backgroundShader.setInt("environmentMap", 0); + // lights // ------ glm::vec3 lightPositions[] = { glm::vec3(-10.0f, 10.0f, 10.0f), - glm::vec3(10.0f, 10.0f, 10.0f), + glm::vec3( 10.0f, 10.0f, 10.0f), glm::vec3(-10.0f, -10.0f, 10.0f), - glm::vec3(10.0f, -10.0f, 10.0f), + glm::vec3( 10.0f, -10.0f, 10.0f), }; glm::vec3 lightColors[] = { glm::vec3(300.0f, 300.0f, 300.0f), @@ -156,7 +156,7 @@ int main() glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // pbr: set up projection and view matrices for capturing data onto the 6 cubemap face directions @@ -174,17 +174,17 @@ int main() // pbr: convert HDR equirectangular environment map to cubemap equivalent // ---------------------------------------------------------------------- - equirectangularToCubemapShader.Use(); - glUniform1i(glGetUniformLocation(equirectangularToCubemapShader.Program, "equirectangularMap"), 0); + equirectangularToCubemapShader.use(); + equirectangularToCubemapShader.setInt("equirectangularMap", 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, hdrTexture); - glUniformMatrix4fv(glGetUniformLocation(equirectangularToCubemapShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(captureProjection)); + equirectangularToCubemapShader.setMat4("projection", captureProjection); glViewport(0, 0, 512, 512); // don't forget to configure the viewport to the capture dimensions. glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); for (unsigned int i = 0; i < 6; ++i) { - glUniformMatrix4fv(glGetUniformLocation(equirectangularToCubemapShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(captureViews[i])); + equirectangularToCubemapShader.setMat4("view", captureViews[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, envCubemap, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -213,17 +213,17 @@ int main() // pbr: solve diffuse integral by convolution to create an irradiance (cube)map. // ----------------------------------------------------------------------------- - irradianceShader.Use(); - glUniform1i(glGetUniformLocation(irradianceShader.Program, "environmentMap"), 0); + irradianceShader.use(); + irradianceShader.setInt("environmentMap", 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap); - glUniformMatrix4fv(glGetUniformLocation(irradianceShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(captureProjection)); + irradianceShader.setMat4("projection", captureProjection); glViewport(0, 0, 32, 32); // don't forget to configure the viewport to the capture dimensions. glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); for (unsigned int i = 0; i < 6; ++i) { - glUniformMatrix4fv(glGetUniformLocation(irradianceShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(captureViews[i])); + irradianceShader.setMat4("view", captureViews[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, irradianceMap, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -231,41 +231,46 @@ int main() } glBindFramebuffer(GL_FRAMEBUFFER, 0); - // initialize static shader uniforms before rendering // -------------------------------------------------- glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); - pbrShader.Use(); - glUniformMatrix4fv(glGetUniformLocation(pbrShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); - backgroundShader.Use(); - glUniformMatrix4fv(glGetUniformLocation(backgroundShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); + pbrShader.use(); + pbrShader.setMat4("projection", projection); + backgroundShader.use(); + backgroundShader.setMat4("projection", projection); - // then before rendering, configure the viewport to the actual screen dimensions - glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); + // then before rendering, configure the viewport to the original framebuffer's screen dimensions + int scrWidth, scrHeight; + glfwGetFramebufferSize(window, &scrWidth, &scrHeight); + glViewport(0, 0, scrWidth, scrHeight); - // 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); - // clear the colorbuffer - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + // render + // ------ + glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - // render scene, supplying the convoluted irradiance map to the final shader. + // render scene, supplying the convoluted irradiance map to the final shader. // ------------------------------------------------------------------------------------------ - pbrShader.Use(); + pbrShader.use(); glm::mat4 view = camera.GetViewMatrix(); - glUniformMatrix4fv(glGetUniformLocation(pbrShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); - glUniform3fv(glGetUniformLocation(pbrShader.Program, "camPos"), 1, &camera.Position[0]); + pbrShader.setMat4("view", view); + pbrShader.setVec3("camPos", camera.Position); + // bind pre-computed IBL data glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, irradianceMap); @@ -273,12 +278,12 @@ int main() glm::mat4 model; for (int row = 0; row < nrRows; ++row) { - glUniform1f(glGetUniformLocation(pbrShader.Program, "metallic"), (float)row / (float)nrRows); + pbrShader.setFloat("metallic", (float)row / (float)nrRows); for (int col = 0; col < nrColumns; ++col) { // we clamp the roughness to 0.025 - 1.0 as perfectly smooth surfaces (roughness of 0.0) tend to look a bit off // on direct lighting. - glUniform1f(glGetUniformLocation(pbrShader.Program, "roughness"), glm::clamp((float)col / (float)nrColumns, 0.05f, 1.0f)); + pbrShader.setFloat("roughness", glm::clamp((float)col / (float)nrColumns, 0.05f, 1.0f)); model = glm::mat4(); model = glm::translate(model, glm::vec3( @@ -286,11 +291,12 @@ int main() (float)(row - (nrRows / 2)) * spacing, -2.0f )); - glUniformMatrix4fv(glGetUniformLocation(pbrShader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); + pbrShader.setMat4("model", model); renderSphere(); } } + // render light source (simply re-render sphere at light positions) // this looks a bit off as we use the same shader, but it'll make their positions obvious and // keeps the codeprint small. @@ -298,34 +304,94 @@ int main() { glm::vec3 newPos = lightPositions[i] + glm::vec3(sin(glfwGetTime() * 5.0) * 5.0, 0.0, 0.0); newPos = lightPositions[i]; - glUniform3fv(glGetUniformLocation(pbrShader.Program, ("lightPositions[" + std::to_string(i) + "]").c_str()), 1, &newPos[0]); \ - glUniform3fv(glGetUniformLocation(pbrShader.Program, ("lightColors[" + std::to_string(i) + "]").c_str()), 1, &lightColors[i][0]); + pbrShader.setVec3("lightPositions[" + std::to_string(i) + "]", newPos); + pbrShader.setVec3("lightColors[" + std::to_string(i) + "]", lightColors[i]); model = glm::mat4(); model = glm::translate(model, newPos); model = glm::scale(model, glm::vec3(0.5f)); - glUniformMatrix4fv(glGetUniformLocation(pbrShader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); + pbrShader.setMat4("model", model); renderSphere(); } // render skybox (render as last to prevent overdraw) - backgroundShader.Use(); - glUniformMatrix4fv(glGetUniformLocation(backgroundShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); + backgroundShader.use(); + backgroundShader.setMat4("view", view); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap); //glBindTexture(GL_TEXTURE_CUBE_MAP, irradianceMap); // display irradiance map renderCube(); - // Swap the buffers + + // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) + // ------------------------------------------------------------------------------- glfwSwapBuffers(window); + glfwPollEvents(); } + // glfw: terminate, clearing all previously allocated GLFW resources. + // ------------------------------------------------------------------ glfwTerminate(); return 0; } +// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly +// --------------------------------------------------------------------------------------------------------- +void processInput(GLFWwindow *window) +{ + if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) + glfwSetWindowShouldClose(window, true); + + 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); +} + +// 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) + { + lastX = xpos; + lastY = ypos; + firstMouse = false; + } + + float xoffset = xpos - lastX; + float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top + + lastX = xpos; + lastY = 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); +} // renders (and builds at first invocation) a sphere +// ------------------------------------------------- unsigned int sphereVAO = 0; unsigned int indexCount; void renderSphere() @@ -410,191 +476,88 @@ void renderSphere() glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW); float stride = (3 + 2 + 3) * sizeof(float); glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, (GLvoid*)(3 * sizeof(float))); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, (void*)(3 * sizeof(float))); glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)(5 * sizeof(float))); + glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, stride, (void*)(5 * sizeof(float))); } glBindVertexArray(sphereVAO); glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0); } -// RenderCube() Renders a 1x1 3D cube in NDC. -GLuint cubeVAO = 0; -GLuint cubeVBO = 0; + +// renderCube() renders a 1x1 3D cube in NDC. +// ------------------------------------------------- +unsigned int cubeVAO = 0; +unsigned int cubeVBO = 0; void renderCube() { - // Initialize (if necessary) + // initialize (if necessary) if (cubeVAO == 0) { - GLfloat 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 + 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, 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, 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 + // 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, 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 + // 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 + // fill buffer glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - // Link vertex attributes + // link vertex attributes glBindVertexArray(cubeVAO); glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); + 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(GLfloat), (GLvoid*)(6 * sizeof(GLfloat))); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } - // Render Cube + // render Cube glBindVertexArray(cubeVAO); glDrawArrays(GL_TRIANGLES, 0, 36); 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. -unsigned int loadTexture(char const * path) -{ - //Generate texture ID and load texture data - unsigned int textureID; - glGenTextures(1, &textureID); - int width, height, nrComponents; - unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0); - if (data) - { - GLenum format; - if (nrComponents == 1) - format = GL_RED; - else if (nrComponents == 3) - format = GL_RGB; - else if (nrComponents == 4) - format = GL_RGBA; - - glBindTexture(GL_TEXTURE_2D, textureID); - glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); - 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); - - stbi_image_free(data); - } - else - { - std::cout << "Texture failed to load at path: " << path << std::endl; - stbi_image_free(data); - } - - return textureID; -} - -#pragma region "User input" - -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); -} - -// 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 (action == GLFW_PRESS) - keys[key] = true; - else if (action == GLFW_RELEASE) - { - keys[key] = false; - keysPressed[key] = false; - } - } -} - -GLfloat lastX = 400, lastY = 300; -bool firstMouse = true; -// Moves/alters the camera positions based on user input -void mouse_callback(GLFWwindow* window, double xpos, double ypos) -{ - if (firstMouse) - { - lastX = xpos; - lastY = ypos; - firstMouse = false; - } - - GLfloat xoffset = xpos - lastX; - GLfloat yoffset = lastY - ypos; - - lastX = xpos; - lastY = ypos; - - camera.ProcessMouseMovement(xoffset, yoffset); -} - -void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) -{ - camera.ProcessMouseScroll(yoffset); -} - -#pragma endregion \ No newline at end of file +} \ No newline at end of file diff --git a/src/6.pbr/2.2.1.ibl_specular/ibl_specular.cpp b/src/6.pbr/2.2.1.ibl_specular/ibl_specular.cpp index 8d2becb..2e50884 100644 --- a/src/6.pbr/2.2.1.ibl_specular/ibl_specular.cpp +++ b/src/6.pbr/2.2.1.ibl_specular/ibl_specular.cpp @@ -1,86 +1,84 @@ -// Std. Includes -#include - -// 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 "stb_image.h" +#include -// Properties -const GLuint SCR_WIDTH = 1280, SCR_HEIGHT = 720; - -// 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 scroll_callback(GLFWwindow* window, double xoffset, double yoffset); +void processInput(GLFWwindow *window); void renderSphere(); void renderCube(); -void RenderQuad(); +void renderQuad(); // camera Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); +float lastX = 800.0f / 2.0; +float lastY = 600.0 / 2.0; +bool firstMouse = true; -// timing -GLfloat deltaTime = 0.0f; -GLfloat lastFrame = 0.0f; +float deltaTime = 0.0f; +float lastFrame = 0.0f; + +// settings +const unsigned int SCR_WIDTH = 1280; +const unsigned int SCR_HEIGHT = 720; -// The MAIN function, from here we start the application and run the Game loop int main() { - // GLFW Init - // --------- + // 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_SAMPLES, 4); - glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - 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); - - // GLFW config - // ----------- - 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); + // 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(); - glGetError(); + // glad: load all OpenGL function pointers + // --------------------------------------- + if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) + { + std::cout << "Failed to initialize GLAD" << std::endl; + return -1; + } - // Setup OpenGL state - // ------------------ + // configure global opengl state + // ----------------------------- glEnable(GL_DEPTH_TEST); // set depth function to less than AND equal for skybox depth trick. - glDepthFunc(GL_LEQUAL); + glDepthFunc(GL_LEQUAL); // enable seamless cubemap sampling for lower mip levels in the pre-filter map. glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); - // load and initialize shaders - // --------------------------- + // build and compile shaders + // ------------------------- Shader pbrShader("2.2.1.pbr.vs", "2.2.1.pbr.frag"); Shader equirectangularToCubemapShader("2.2.1.cubemap.vs", "2.2.1.equirectangular_to_cubemap.frag"); Shader irradianceShader("2.2.1.cubemap.vs", "2.2.1.irradiance_convolution.frag"); @@ -88,23 +86,24 @@ int main() Shader brdfShader("2.2.1.brdf.vs", "2.2.1.brdf.frag"); Shader backgroundShader("2.2.1.background.vs", "2.2.1.background.frag"); - pbrShader.Use(); - glUniform1i(glGetUniformLocation(pbrShader.Program, "irradianceMap"), 0); - glUniform1i(glGetUniformLocation(pbrShader.Program, "prefilterMap"), 1); - glUniform1i(glGetUniformLocation(pbrShader.Program, "brdfLUT"), 2); - glUniform3f(glGetUniformLocation(pbrShader.Program, "albedo"), 0.5f, 0.0f, 0.0f); - glUniform1f(glGetUniformLocation(pbrShader.Program, "ao"), 1.0f); + pbrShader.use(); + pbrShader.setInt("irradianceMap", 0); + pbrShader.setInt("prefilterMap", 1); + pbrShader.setInt("brdfLUT", 2); + pbrShader.setVec3("albedo", 0.5f, 0.0f, 0.0f); + pbrShader.setFloat("ao", 1.0f); - backgroundShader.Use(); - glUniform1i(glGetUniformLocation(backgroundShader.Program, "environmentMap"), 0); + backgroundShader.use(); + backgroundShader.setInt("environmentMap", 0); + // lights // ------ glm::vec3 lightPositions[] = { glm::vec3(-10.0f, 10.0f, 10.0f), - glm::vec3(10.0f, 10.0f, 10.0f), + glm::vec3( 10.0f, 10.0f, 10.0f), glm::vec3(-10.0f, -10.0f, 10.0f), - glm::vec3(10.0f, -10.0f, 10.0f), + glm::vec3( 10.0f, -10.0f, 10.0f), }; glm::vec3 lightColors[] = { glm::vec3(300.0f, 300.0f, 300.0f), @@ -182,17 +181,17 @@ int main() // pbr: convert HDR equirectangular environment map to cubemap equivalent // ---------------------------------------------------------------------- - equirectangularToCubemapShader.Use(); - glUniform1i(glGetUniformLocation(equirectangularToCubemapShader.Program, "equirectangularMap"), 0); + equirectangularToCubemapShader.use(); + equirectangularToCubemapShader.setInt("equirectangularMap", 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, hdrTexture); - glUniformMatrix4fv(glGetUniformLocation(equirectangularToCubemapShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(captureProjection)); + equirectangularToCubemapShader.setMat4("projection", captureProjection); glViewport(0, 0, 512, 512); // don't forget to configure the viewport to the capture dimensions. glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); for (unsigned int i = 0; i < 6; ++i) { - glUniformMatrix4fv(glGetUniformLocation(equirectangularToCubemapShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(captureViews[i])); + equirectangularToCubemapShader.setMat4("view", captureViews[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, envCubemap, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -225,17 +224,17 @@ int main() // pbr: solve diffuse integral by convolution to create an irradiance (cube)map. // ----------------------------------------------------------------------------- - irradianceShader.Use(); - glUniform1i(glGetUniformLocation(irradianceShader.Program, "environmentMap"), 0); + irradianceShader.use(); + irradianceShader.setInt("environmentMap", 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap); - glUniformMatrix4fv(glGetUniformLocation(irradianceShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(captureProjection)); + irradianceShader.setMat4("projection", captureProjection); glViewport(0, 0, 32, 32); // don't forget to configure the viewport to the capture dimensions. glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); for (unsigned int i = 0; i < 6; ++i) { - glUniformMatrix4fv(glGetUniformLocation(irradianceShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(captureViews[i])); + irradianceShader.setMat4("view", captureViews[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, irradianceMap, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -262,11 +261,11 @@ int main() // pbr: run a quasi monte-carlo simulation on the environment lighting to create a prefilter (cube)map. // ---------------------------------------------------------------------------------------------------- - prefilterShader.Use(); - glUniform1i(glGetUniformLocation(prefilterShader.Program, "environmentMap"), 0); + prefilterShader.use(); + prefilterShader.setInt("environmentMap", 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap); - glUniformMatrix4fv(glGetUniformLocation(prefilterShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(captureProjection)); + prefilterShader.setMat4("projection", captureProjection); glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); unsigned int maxMipLevels = 5; @@ -280,10 +279,10 @@ int main() glViewport(0, 0, mipWidth, mipHeight); float roughness = (float)mip / (float)(maxMipLevels - 1); - glUniform1f(glGetUniformLocation(prefilterShader.Program, "roughness"), roughness); + prefilterShader.setFloat("roughness", roughness); for (unsigned int i = 0; i < 6; ++i) { - glUniformMatrix4fv(glGetUniformLocation(prefilterShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(captureViews[i])); + prefilterShader.setMat4("view", captureViews[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, prefilterMap, mip); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -313,9 +312,9 @@ int main() glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, brdfLUTTexture, 0); glViewport(0, 0, 512, 512); - brdfShader.Use(); + brdfShader.use(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - RenderQuad(); + renderQuad(); glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -323,37 +322,43 @@ int main() // initialize static shader uniforms before rendering // -------------------------------------------------- glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); - pbrShader.Use(); - glUniformMatrix4fv(glGetUniformLocation(pbrShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); - backgroundShader.Use(); - glUniformMatrix4fv(glGetUniformLocation(backgroundShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); + pbrShader.use(); + pbrShader.setMat4("projection", projection); + backgroundShader.use(); + backgroundShader.setMat4("projection", projection); - // then before rendering, configure the viewport to the actual screen dimensions - glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); + // then before rendering, configure the viewport to the original framebuffer's screen dimensions + int scrWidth, scrHeight; + glfwGetFramebufferSize(window, &scrWidth, &scrHeight); + glViewport(0, 0, scrWidth, scrHeight); - // 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); - // clear the colorbuffer - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + // render + // ------ + glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - // render scene, supplying the convoluted irradiance map to the final shader. + // render scene, supplying the convoluted irradiance map to the final shader. // ------------------------------------------------------------------------------------------ - pbrShader.Use(); + pbrShader.use(); glm::mat4 view = camera.GetViewMatrix(); - glUniformMatrix4fv(glGetUniformLocation(pbrShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); - glUniform3fv(glGetUniformLocation(pbrShader.Program, "camPos"), 1, &camera.Position[0]); + pbrShader.setMat4("view", view); + pbrShader.setVec3("camPos", camera.Position); + // bind pre-computed IBL data glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, irradianceMap); glActiveTexture(GL_TEXTURE1); @@ -365,12 +370,12 @@ int main() glm::mat4 model; for (int row = 0; row < nrRows; ++row) { - glUniform1f(glGetUniformLocation(pbrShader.Program, "metallic"), (float)row / (float)nrRows); + pbrShader.setFloat("metallic", (float)row / (float)nrRows); for (int col = 0; col < nrColumns; ++col) { // we clamp the roughness to 0.025 - 1.0 as perfectly smooth surfaces (roughness of 0.0) tend to look a bit off // on direct lighting. - glUniform1f(glGetUniformLocation(pbrShader.Program, "roughness"), glm::clamp((float)col / (float)nrColumns, 0.05f, 1.0f)); + pbrShader.setFloat("roughness", glm::clamp((float)col / (float)nrColumns, 0.05f, 1.0f)); model = glm::mat4(); model = glm::translate(model, glm::vec3( @@ -378,11 +383,12 @@ int main() (float)(row - (nrRows / 2)) * spacing, -2.0f )); - glUniformMatrix4fv(glGetUniformLocation(pbrShader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); + pbrShader.setMat4("model", model); renderSphere(); } } + // render light source (simply re-render sphere at light positions) // this looks a bit off as we use the same shader, but it'll make their positions obvious and // keeps the codeprint small. @@ -390,39 +396,100 @@ int main() { glm::vec3 newPos = lightPositions[i] + glm::vec3(sin(glfwGetTime() * 5.0) * 5.0, 0.0, 0.0); newPos = lightPositions[i]; - glUniform3fv(glGetUniformLocation(pbrShader.Program, ("lightPositions[" + std::to_string(i) + "]").c_str()), 1, &newPos[0]); \ - glUniform3fv(glGetUniformLocation(pbrShader.Program, ("lightColors[" + std::to_string(i) + "]").c_str()), 1, &lightColors[i][0]); + pbrShader.setVec3("lightPositions[" + std::to_string(i) + "]", newPos); + pbrShader.setVec3("lightColors[" + std::to_string(i) + "]", lightColors[i]); model = glm::mat4(); model = glm::translate(model, newPos); model = glm::scale(model, glm::vec3(0.5f)); - glUniformMatrix4fv(glGetUniformLocation(pbrShader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); + pbrShader.setMat4("model", model); renderSphere(); } // render skybox (render as last to prevent overdraw) - backgroundShader.Use(); - glUniformMatrix4fv(glGetUniformLocation(backgroundShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); + backgroundShader.use(); + backgroundShader.setMat4("view", view); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap); //glBindTexture(GL_TEXTURE_CUBE_MAP, irradianceMap); // display irradiance map //glBindTexture(GL_TEXTURE_CUBE_MAP, prefilterMap); // display prefilter map renderCube(); + // render BRDF map to screen //brdfShader.Use(); - //RenderQuad(); + //renderQuad(); - // Swap the buffers + + // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) + // ------------------------------------------------------------------------------- glfwSwapBuffers(window); + glfwPollEvents(); } + // glfw: terminate, clearing all previously allocated GLFW resources. + // ------------------------------------------------------------------ glfwTerminate(); return 0; } +// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly +// --------------------------------------------------------------------------------------------------------- +void processInput(GLFWwindow *window) +{ + if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) + glfwSetWindowShouldClose(window, true); + + 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); +} + +// 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) + { + lastX = xpos; + lastY = ypos; + firstMouse = false; + } + + float xoffset = xpos - lastX; + float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top + + lastX = xpos; + lastY = 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); +} // renders (and builds at first invocation) a sphere +// ------------------------------------------------- unsigned int sphereVAO = 0; unsigned int indexCount; void renderSphere() @@ -507,221 +574,119 @@ void renderSphere() glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW); float stride = (3 + 2 + 3) * sizeof(float); glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, (GLvoid*)(3 * sizeof(float))); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, (void*)(3 * sizeof(float))); glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)(5 * sizeof(float))); + glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, stride, (void*)(5 * sizeof(float))); } glBindVertexArray(sphereVAO); glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0); } -// RenderCube() Renders a 1x1 3D cube in NDC. -GLuint cubeVAO = 0; -GLuint cubeVBO = 0; + +// renderCube() renders a 1x1 3D cube in NDC. +// ------------------------------------------------- +unsigned int cubeVAO = 0; +unsigned int cubeVBO = 0; void renderCube() { - // Initialize (if necessary) + // initialize (if necessary) if (cubeVAO == 0) { - GLfloat 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 + 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, 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, 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 + // 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, 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 + // 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 + // fill buffer glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - // Link vertex attributes + // link vertex attributes glBindVertexArray(cubeVAO); glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); + 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(GLfloat), (GLvoid*)(6 * sizeof(GLfloat))); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } - // Render Cube + // render Cube glBindVertexArray(cubeVAO); glDrawArrays(GL_TRIANGLES, 0, 36); glBindVertexArray(0); } -// RenderQuad() Renders a 1x1 XY quad in NDC -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) + 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); -} - -// 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. -unsigned int loadTexture(char const * path) -{ - //Generate texture ID and load texture data - unsigned int textureID; - glGenTextures(1, &textureID); - int width, height, nrComponents; - unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0); - if (data) - { - GLenum format; - if (nrComponents == 1) - format = GL_RED; - else if (nrComponents == 3) - format = GL_RGB; - else if (nrComponents == 4) - format = GL_RGBA; - - glBindTexture(GL_TEXTURE_2D, textureID); - glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); - 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); - - stbi_image_free(data); - } - else - { - std::cout << "Texture failed to load at path: " << path << std::endl; - stbi_image_free(data); - } - - return textureID; -} - -#pragma region "User input" - -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); -} - -// 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 (action == GLFW_PRESS) - keys[key] = true; - else if (action == GLFW_RELEASE) - { - keys[key] = false; - keysPressed[key] = false; - } - } -} - -GLfloat lastX = 400, lastY = 300; -bool firstMouse = true; -// Moves/alters the camera positions based on user input -void mouse_callback(GLFWwindow* window, double xpos, double ypos) -{ - if (firstMouse) - { - lastX = xpos; - lastY = ypos; - firstMouse = false; - } - - GLfloat xoffset = xpos - lastX; - GLfloat yoffset = lastY - ypos; - - lastX = xpos; - lastY = ypos; - - camera.ProcessMouseMovement(xoffset, yoffset); -} - -void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) -{ - camera.ProcessMouseScroll(yoffset); -} - -#pragma endregion \ No newline at end of file +} \ No newline at end of file diff --git a/src/6.pbr/2.2.2.ibl_specular_textured/ibl_specular_textured.cpp b/src/6.pbr/2.2.2.ibl_specular_textured/ibl_specular_textured.cpp index f1de453..3cfab06 100644 --- a/src/6.pbr/2.2.2.ibl_specular_textured/ibl_specular_textured.cpp +++ b/src/6.pbr/2.2.2.ibl_specular_textured/ibl_specular_textured.cpp @@ -698,48 +698,48 @@ void renderCube() 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 + // 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, 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, 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 + // 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, 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 + // 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);