diff --git a/src/4.advanced_opengl/1.1.depth_testing/depth_testing.cpp b/src/4.advanced_opengl/1.1.depth_testing/depth_testing.cpp index 3c38c6a..bd5ed5f 100644 --- a/src/4.advanced_opengl/1.1.depth_testing/depth_testing.cpp +++ b/src/4.advanced_opengl/1.1.depth_testing/depth_testing.cpp @@ -183,7 +183,7 @@ int main() // render // ------ - glClearColor(0.2f, 0.3f, 0.3f, 1.0f); + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); shader.use(); diff --git a/src/4.advanced_opengl/1.2.depth_testing_view/depth_testing_view.cpp b/src/4.advanced_opengl/1.2.depth_testing_view/depth_testing_view.cpp index ec6ba1a..aaf9074 100644 --- a/src/4.advanced_opengl/1.2.depth_testing_view/depth_testing_view.cpp +++ b/src/4.advanced_opengl/1.2.depth_testing_view/depth_testing_view.cpp @@ -183,7 +183,7 @@ int main() // render // ------ - glClearColor(0.2f, 0.3f, 0.3f, 1.0f); + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); shader.use(); diff --git a/src/4.advanced_opengl/2.stencil_testing/stencil_testing.cpp b/src/4.advanced_opengl/2.stencil_testing/stencil_testing.cpp index 0ff8ebd..26cd2ed 100644 --- a/src/4.advanced_opengl/2.stencil_testing/stencil_testing.cpp +++ b/src/4.advanced_opengl/2.stencil_testing/stencil_testing.cpp @@ -187,7 +187,7 @@ int main() // render // ------ - glClearColor(0.2f, 0.3f, 0.3f, 1.0f); + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // don't forget to clear the stencil buffer! // set uniforms diff --git a/src/4.advanced_opengl/3.1.blending_discard/blending_discard.cpp b/src/4.advanced_opengl/3.1.blending_discard/blending_discard.cpp index 03c341e..df3d0a2 100644 --- a/src/4.advanced_opengl/3.1.blending_discard/blending_discard.cpp +++ b/src/4.advanced_opengl/3.1.blending_discard/blending_discard.cpp @@ -70,7 +70,6 @@ int main() // configure global opengl state // ----------------------------- glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_ALWAYS); // always pass the depth test (same effect as glDisable(GL_DEPTH_TEST)) // build and compile shaders // ------------------------- @@ -183,7 +182,7 @@ int main() // render // ------ - glClearColor(0.2f, 0.3f, 0.3f, 1.0f); + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); diff --git a/src/4.advanced_opengl/3.2.blending_sort/blending_sorted.cpp b/src/4.advanced_opengl/3.2.blending_sort/blending_sorted.cpp index e223649..3905d2b 100644 --- a/src/4.advanced_opengl/3.2.blending_sort/blending_sorted.cpp +++ b/src/4.advanced_opengl/3.2.blending_sort/blending_sorted.cpp @@ -70,7 +70,6 @@ int main() // configure global opengl state // ----------------------------- glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_ALWAYS); // always pass the depth test (same effect as glDisable(GL_DEPTH_TEST)) // build and compile shaders // ------------------------- @@ -183,7 +182,7 @@ int main() // render // ------ - glClearColor(0.2f, 0.3f, 0.3f, 1.0f); + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); diff --git a/src/4.advanced_opengl/5.1.framebuffers/5.1.framebuffers.fs b/src/4.advanced_opengl/5.1.framebuffers/5.1.framebuffers.fs index a6bf09f..b342078 100644 --- a/src/4.advanced_opengl/5.1.framebuffers/5.1.framebuffers.fs +++ b/src/4.advanced_opengl/5.1.framebuffers/5.1.framebuffers.fs @@ -1,11 +1,11 @@ #version 330 core -in vec2 TexCoords; +out vec4 FragColor; -out vec4 color; +in vec2 TexCoords; uniform sampler2D texture1; void main() -{ - color = texture(texture1, TexCoords); +{ + FragColor = texture(texture1, TexCoords); } \ No newline at end of file diff --git a/src/4.advanced_opengl/5.1.framebuffers/5.1.framebuffers.vs b/src/4.advanced_opengl/5.1.framebuffers/5.1.framebuffers.vs index 3abdaa6..ddede39 100644 --- a/src/4.advanced_opengl/5.1.framebuffers/5.1.framebuffers.vs +++ b/src/4.advanced_opengl/5.1.framebuffers/5.1.framebuffers.vs @@ -1,6 +1,6 @@ #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; @@ -10,6 +10,6 @@ uniform mat4 projection; void main() { - gl_Position = projection * view * model * vec4(position, 1.0f); - TexCoords = texCoords; + TexCoords = aTexCoords; + gl_Position = projection * view * model * vec4(aPos, 1.0); } \ No newline at end of file diff --git a/src/4.advanced_opengl/5.1.framebuffers/5.1.framebuffers_screen.fs b/src/4.advanced_opengl/5.1.framebuffers/5.1.framebuffers_screen.fs index 197b3c8..a23a2a8 100644 --- a/src/4.advanced_opengl/5.1.framebuffers/5.1.framebuffers_screen.fs +++ b/src/4.advanced_opengl/5.1.framebuffers/5.1.framebuffers_screen.fs @@ -1,40 +1,12 @@ #version 330 core -in vec2 TexCoords; +out vec4 FragColor; -out vec4 color; +in vec2 TexCoords; uniform sampler2D screenTexture; -const float offset = 1.0 / 300; - void main() { - vec2 offsets[9] = vec2[]( - vec2(-offset, offset), // top-left - vec2(0.0f, offset), // top-center - vec2(offset, offset), // top-right - vec2(-offset, 0.0f), // center-left - vec2(0.0f, 0.0f), // center-center - vec2(offset, 0.0f), // center-right - vec2(-offset, -offset), // bottom-left - vec2(0.0f, -offset), // bottom-center - vec2(offset, -offset) // bottom-right - ); - - float kernel[9] = float[]( - -1, -1, -1, - -1, 9, -1, - -1, -1, -1 - ); - - vec3 sampleTex[9]; - for(int i = 0; i < 9; i++) - { - sampleTex[i] = vec3(texture(screenTexture, TexCoords.st + offsets[i])); - } - vec3 col; - for(int i = 0; i < 9; i++) - col += sampleTex[i] * kernel[i]; - - color = vec4(col, 1.0); -} + vec3 col = texture(screenTexture, TexCoords).rgb; + FragColor = vec4(col, 1.0); +} \ No newline at end of file diff --git a/src/4.advanced_opengl/5.1.framebuffers/5.1.framebuffers_screen.vs b/src/4.advanced_opengl/5.1.framebuffers/5.1.framebuffers_screen.vs index 2f5ad17..1376b62 100644 --- a/src/4.advanced_opengl/5.1.framebuffers/5.1.framebuffers_screen.vs +++ b/src/4.advanced_opengl/5.1.framebuffers/5.1.framebuffers_screen.vs @@ -1,11 +1,11 @@ #version 330 core -layout (location = 0) in vec2 position; -layout (location = 1) in vec2 texCoords; +layout (location = 0) in vec2 aPos; +layout (location = 1) in vec2 aTexCoords; out vec2 TexCoords; void main() { - gl_Position = vec4(position.x, position.y, 0.0f, 1.0f); - TexCoords = texCoords; + TexCoords = aTexCoords; + gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0); } \ No newline at end of file diff --git a/src/4.advanced_opengl/5.1.framebuffers/framebuffers.cpp b/src/4.advanced_opengl/5.1.framebuffers/framebuffers.cpp index 59ebd03..712d53e 100644 --- a/src/4.advanced_opengl/5.1.framebuffers/framebuffers.cpp +++ b/src/4.advanced_opengl/5.1.framebuffers/framebuffers.cpp @@ -1,87 +1,85 @@ -// Std. Includes -#include -#include -using namespace std; - -// 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 -GLuint screenWidth = 800, screenHeight = 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, GLboolean alpha = false); -GLuint generateAttachmentTexture(GLboolean depth, GLboolean stencil); +void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); +void processInput(GLFWwindow *window); +unsigned int loadTexture(const char *path); -// Camera +// settings +const unsigned int SCR_WIDTH = 1280; +const unsigned int SCR_HEIGHT = 720; + +// camera Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); -bool keys[1024]; -GLfloat lastX = 400, lastY = 300; +float lastX = (float)SCR_WIDTH / 2.0; +float lastY = (float)SCR_HEIGHT / 2.0; bool firstMouse = true; -GLfloat deltaTime = 0.0f; -GLfloat lastFrame = 0.0f; +// timing +float deltaTime = 0.0f; +float lastFrame = 0.0f; -// 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(screenWidth, screenHeight, "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 - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + // 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, screenWidth, screenHeight); + // configure global opengl state + // ----------------------------- + glEnable(GL_DEPTH_TEST); - // Setup some OpenGL options - glDepthFunc(GL_LESS); - - // Setup and compile our shaders - Shader shader("framebuffers.vs", "framebuffers.frag"); - Shader screenShader("framebuffers_screen.vs", "framebuffers_screen.frag"); + // build and compile shaders + // ------------------------- + Shader shader("5.1.framebuffers.vs", "5.1.framebuffers.fs"); + Shader screenShader("5.1.framebuffers_screen.vs", "5.1.framebuffers_screen.fs"); - #pragma region "object_initialization" - // Set the object data (buffers, vertex attributes) - GLfloat cubeVertices[] = { - // Positions // Texture Coords + // set up vertex data (and buffer(s)) and configure vertex attributes + // ------------------------------------------------------------------ + float cubeVertices[] = { + // positions // texture Coords -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, @@ -124,18 +122,18 @@ int main() -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f }; - GLfloat floorVertices[] = { - // Positions // Texture Coords (note we set these higher than 1 that together with GL_REPEAT as texture wrapping mode will cause the floor texture to repeat) - 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, + float planeVertices[] = { + // positions // texture Coords + 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, -5.0f, -0.5f, 5.0f, 0.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 2.0f, - 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, + 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 2.0f, - 5.0f, -0.5f, -5.0f, 2.0f, 2.0f + 5.0f, -0.5f, -5.0f, 2.0f, 2.0f }; - GLfloat quadVertices[] = { // Vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates. - // Positions // TexCoords + float quadVertices[] = { // vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates. + // positions // texCoords -1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, @@ -143,253 +141,252 @@ int main() -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f - }; - - // Setup cube VAO - GLuint cubeVAO, cubeVBO; + }; + // cube VAO + unsigned int cubeVAO, cubeVBO; glGenVertexArrays(1, &cubeVAO); glGenBuffers(1, &cubeVBO); glBindVertexArray(cubeVAO); glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, 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))); - glBindVertexArray(0); - // Setup plane VAO - GLuint floorVAO, floorVBO; - glGenVertexArrays(1, &floorVAO); - glGenBuffers(1, &floorVBO); - glBindVertexArray(floorVAO); - glBindBuffer(GL_ARRAY_BUFFER, floorVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(floorVertices), &floorVertices, GL_STATIC_DRAW); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); + // plane VAO + unsigned int planeVAO, planeVBO; + glGenVertexArrays(1, &planeVAO); + glGenBuffers(1, &planeVBO); + glBindVertexArray(planeVAO); + glBindBuffer(GL_ARRAY_BUFFER, planeVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), &planeVertices, 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))); - glBindVertexArray(0); - // Setup screen VAO - GLuint quadVAO, quadVBO; + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); + // screen quad VAO + unsigned int quadVAO, quadVBO; 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, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)(2 * sizeof(GLfloat))); - glBindVertexArray(0); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); - // Load textures - GLuint cubeTexture = loadTexture(FileSystem::getPath("resources/textures/container.jpg").c_str()); - GLuint floorTexture = loadTexture(FileSystem::getPath("resources/textures/metal.png").c_str()); - #pragma endregion + // load textures + // ------------- + unsigned int cubeTexture = loadTexture(FileSystem::getPath("resources/textures/marble.jpg").c_str()); + unsigned int floorTexture = loadTexture(FileSystem::getPath("resources/textures/metal.png").c_str()); - // Framebuffers - GLuint framebuffer; + // shader configuration + // -------------------- + shader.use(); + shader.setInt("texture1", 0); + + screenShader.use(); + screenShader.setInt("screenTexture", 0); + + // framebuffer configuration + // ------------------------- + unsigned int framebuffer; glGenFramebuffers(1, &framebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - // Create a color attachment texture - GLuint textureColorbuffer = generateAttachmentTexture(false, false); + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + // create a color attachment texture + unsigned int textureColorbuffer; + glGenTextures(1, &textureColorbuffer); + glBindTexture(GL_TEXTURE_2D, textureColorbuffer); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureColorbuffer, 0); - // Create a renderbuffer object for depth and stencil attachment (we won't be sampling these) - GLuint rbo; + // create a renderbuffer object for depth and stencil attachment (we won't be sampling these) + unsigned int rbo; glGenRenderbuffers(1, &rbo); - glBindRenderbuffer(GL_RENDERBUFFER, rbo); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, screenWidth, screenHeight); // Use a single renderbuffer object for both a depth AND stencil buffer. - glBindRenderbuffer(GL_RENDERBUFFER, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); // Now actually attach it - // Now that we actually created the framebuffer and added all attachments we want to check if it is actually complete now - if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, SCR_WIDTH, SCR_HEIGHT); // use a single renderbuffer object for both a depth AND stencil buffer. + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); // now actually attach it + // now that we actually created the framebuffer and added all attachments we want to check if it is actually complete now + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << endl; glBindFramebuffer(GL_FRAMEBUFFER, 0); - - // Draw as wireframe + // draw as wireframe //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - // Game loop - while(!glfwWindowShouldClose(window)) + // 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); - - ///////////////////////////////////////////////////// - // Bind to framebuffer and draw to color texture - // as we normally would. - // ////////////////////////////////////////////////// + + // render + // ------ + // bind to framebuffer and draw scene as we normally would to color texture glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - // Clear all attached buffers - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // We're not using stencil buffer so why bother with clearing? + glEnable(GL_DEPTH_TEST); // enable depth testing (is disabled for rendering screen-space quad) - glEnable(GL_DEPTH_TEST); - // Set uniforms - shader.Use(); + // make sure we clear the framebuffer's content + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + shader.use(); glm::mat4 model; glm::mat4 view = camera.GetViewMatrix(); - glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth/(float)screenHeight, 0.1f, 100.0f); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); - - // Floor - glBindVertexArray(floorVAO); - glBindTexture(GL_TEXTURE_2D, floorTexture); - model = glm::mat4(); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - glDrawArrays(GL_TRIANGLES, 0, 6); - glBindVertexArray(0); - // Cubes + glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); + shader.setMat4("view", view); + shader.setMat4("projection", projection); + // cubes glBindVertexArray(cubeVAO); - glBindTexture(GL_TEXTURE_2D, cubeTexture); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, cubeTexture); model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); + shader.setMat4("model", model); glDrawArrays(GL_TRIANGLES, 0, 36); model = glm::mat4(); model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); + shader.setMat4("model", model); glDrawArrays(GL_TRIANGLES, 0, 36); - glBindVertexArray(0); - - ///////////////////////////////////////////////////// - // Bind to default framebuffer again and draw the - // quad plane with attched screen texture. - // ////////////////////////////////////////////////// - glBindFramebuffer(GL_FRAMEBUFFER, 0); - // Clear all relevant buffers - glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Set clear color to white (not really necessery actually, since we won't be able to see behind the quad anyways) - glClear(GL_COLOR_BUFFER_BIT); - glDisable(GL_DEPTH_TEST); // We don't care about depth information when rendering a single quad - - // Draw Screen - screenShader.Use(); - glBindVertexArray(quadVAO); - glBindTexture(GL_TEXTURE_2D, textureColorbuffer); // Use the color attachment texture as the texture of the quad plane + // floor + glBindVertexArray(planeVAO); + glBindTexture(GL_TEXTURE_2D, floorTexture); + shader.setMat4("model", glm::mat4()); glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); + // now bind back to default framebuffer and draw a quad plane with the attached framebuffer color texture + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDisable(GL_DEPTH_TEST); // disable depth test so screen-space quad isn't discarded due to depth test. + // clear all relevant buffers + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // set clear color to white (not really necessery actually, since we won't be able to see behind the quad anyways) + glClear(GL_COLOR_BUFFER_BIT); - // Swap the buffers + screenShader.use(); + glBindVertexArray(quadVAO); + glBindTexture(GL_TEXTURE_2D, textureColorbuffer); // use the color attachment texture as the texture of the quad plane + glDrawArrays(GL_TRIANGLES, 0, 6); + + + // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) + // ------------------------------------------------------------------------------- glfwSwapBuffers(window); + glfwPollEvents(); } - // Clean up - glDeleteFramebuffers(1, &framebuffer); + // optional: de-allocate all resources once they've outlived their purpose: + // ------------------------------------------------------------------------ + glDeleteVertexArrays(1, &cubeVAO); + glDeleteVertexArrays(1, &planeVAO); + glDeleteVertexArrays(1, &quadVAO); + glDeleteBuffers(1, &cubeVBO); + glDeleteBuffers(1, &planeVBO); + glDeleteBuffers(1, &quadVBO); glfwTerminate(); return 0; } -// This function loads a texture from file. Note: texture loading functions like these are usually -// managed by a 'Resource Manager' that manages all resources (like textures, models, audio). -// For learning purposes we'll just define it as a utility function. -GLuint loadTexture(GLchar const * path, GLboolean alpha) +// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly +// --------------------------------------------------------------------------------------------------------- +void processInput(GLFWwindow *window) { - //Generate texture ID and load texture data - GLuint textureID; - glGenTextures(1, &textureID); - int width,height; - unsigned char* image = SOIL_load_image(path, &width, &height, 0, alpha ? SOIL_LOAD_RGBA : SOIL_LOAD_RGB); - // Assign texture to ID - glBindTexture(GL_TEXTURE_2D, textureID); - glTexImage2D(GL_TEXTURE_2D, 0, alpha ? GL_RGBA : GL_RGB, width, height, 0, alpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, image); - glGenerateMipmap(GL_TEXTURE_2D); + if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) + glfwSetWindowShouldClose(window, true); - // Parameters - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, alpha ? GL_CLAMP_TO_EDGE : GL_REPEAT ); // Use GL_MIRRORED_REPEAT to prevent white borders. Due to interpolation it takes value from next repeat - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, alpha ? GL_CLAMP_TO_EDGE : 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; -} - -// Generates a texture that is suited for attachments to a framebuffer -GLuint generateAttachmentTexture(GLboolean depth, GLboolean stencil) -{ - // What enum to use? - GLenum attachment_type; - if(!depth && !stencil) - attachment_type = GL_RGB; - else if(depth && !stencil) - attachment_type = GL_DEPTH_COMPONENT; - else if(!depth && stencil) - attachment_type = GL_STENCIL_INDEX; - - //Generate texture ID and load texture data - GLuint textureID; - glGenTextures(1, &textureID); - glBindTexture(GL_TEXTURE_2D, textureID); - if(!depth && !stencil) - glTexImage2D(GL_TEXTURE_2D, 0, attachment_type, screenWidth, screenHeight, 0, attachment_type, GL_UNSIGNED_BYTE, NULL); - else // Using both a stencil and depth test, needs special format arguments - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, screenWidth, screenHeight, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glBindTexture(GL_TEXTURE_2D, 0); - - return textureID; -} - -#pragma region "User input" - -// 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); } -// Is called whenever a key is pressed/released via GLFW -void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) +// glfw: whenever the window size changed (by OS or user resize) this callback function executes +// --------------------------------------------------------------------------------------------- +void framebuffer_size_callback(GLFWwindow* window, int width, int height) { - if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) - glfwSetWindowShouldClose(window, GL_TRUE); - - if(action == GLFW_PRESS) - keys[key] = true; - else if(action == GLFW_RELEASE) - keys[key] = false; + // make sure the viewport matches the new window dimensions; note that width and + // height will be significantly larger than specified on retina displays. + glViewport(0, 0, width, height); } + +// glfw: whenever the mouse moves, this callback is called +// ------------------------------------------------------- void mouse_callback(GLFWwindow* window, double xpos, double ypos) { - if(firstMouse) + if (firstMouse) { lastX = xpos; lastY = ypos; firstMouse = false; } - GLfloat xoffset = xpos - lastX; - GLfloat yoffset = lastY - ypos; - + float xoffset = xpos - lastX; + float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top + lastX = xpos; lastY = ypos; 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); } -#pragma endregion \ No newline at end of file +// utility function for loading a 2D texture from file +// --------------------------------------------------- +unsigned int loadTexture(char const * path) +{ + 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); + + 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 diff --git a/src/4.advanced_opengl/5.2.framebuffers_exercise1/framebuffers_exercise1.cpp b/src/4.advanced_opengl/5.2.framebuffers_exercise1/framebuffers_exercise1.cpp index 59ebd03..235baf4 100644 --- a/src/4.advanced_opengl/5.2.framebuffers_exercise1/framebuffers_exercise1.cpp +++ b/src/4.advanced_opengl/5.2.framebuffers_exercise1/framebuffers_exercise1.cpp @@ -1,87 +1,85 @@ -// Std. Includes -#include -#include -using namespace std; - -// 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 -GLuint screenWidth = 800, screenHeight = 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, GLboolean alpha = false); -GLuint generateAttachmentTexture(GLboolean depth, GLboolean stencil); +void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); +void processInput(GLFWwindow *window); +unsigned int loadTexture(const char *path); -// Camera +// settings +const unsigned int SCR_WIDTH = 1280; +const unsigned int SCR_HEIGHT = 720; + +// camera Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); -bool keys[1024]; -GLfloat lastX = 400, lastY = 300; +float lastX = (float)SCR_WIDTH / 2.0; +float lastY = (float)SCR_HEIGHT / 2.0; bool firstMouse = true; -GLfloat deltaTime = 0.0f; -GLfloat lastFrame = 0.0f; +// timing +float deltaTime = 0.0f; +float lastFrame = 0.0f; -// 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(screenWidth, screenHeight, "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 - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + // 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, screenWidth, screenHeight); + // configure global opengl state + // ----------------------------- + glEnable(GL_DEPTH_TEST); - // Setup some OpenGL options - glDepthFunc(GL_LESS); - - // Setup and compile our shaders - Shader shader("framebuffers.vs", "framebuffers.frag"); - Shader screenShader("framebuffers_screen.vs", "framebuffers_screen.frag"); + // build and compile shaders + // ------------------------- + Shader shader("5.1.framebuffers.vs", "5.1.framebuffers.fs"); + Shader screenShader("5.1.framebuffers_screen.vs", "5.1.framebuffers_screen.fs"); - #pragma region "object_initialization" - // Set the object data (buffers, vertex attributes) - GLfloat cubeVertices[] = { - // Positions // Texture Coords + // set up vertex data (and buffer(s)) and configure vertex attributes + // ------------------------------------------------------------------ + float cubeVertices[] = { + // positions // texture Coords -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, @@ -124,272 +122,305 @@ int main() -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f }; - GLfloat floorVertices[] = { - // Positions // Texture Coords (note we set these higher than 1 that together with GL_REPEAT as texture wrapping mode will cause the floor texture to repeat) - 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, + float planeVertices[] = { + // positions // texture Coords + 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, -5.0f, -0.5f, 5.0f, 0.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 2.0f, - 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, + 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 2.0f, - 5.0f, -0.5f, -5.0f, 2.0f, 2.0f + 5.0f, -0.5f, -5.0f, 2.0f, 2.0f }; - GLfloat quadVertices[] = { // Vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates. - // Positions // TexCoords - -1.0f, 1.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 0.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 0.0f, + float quadVertices[] = { // vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates. NOTE that this plane is now much smaller and at the top of the screen + // positions // texCoords + -0.3f, 1.0f, 0.0f, 1.0f, + -0.3f, 0.7f, 0.0f, 0.0f, + 0.3f, 0.7f, 1.0f, 0.0f, - -1.0f, 1.0f, 0.0f, 1.0f, - 1.0f, -1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 1.0f - }; - - // Setup cube VAO - GLuint cubeVAO, cubeVBO; + -0.3f, 1.0f, 0.0f, 1.0f, + 0.3f, 0.7f, 1.0f, 0.0f, + 0.3f, 1.0f, 1.0f, 1.0f + }; + // cube VAO + unsigned int cubeVAO, cubeVBO; glGenVertexArrays(1, &cubeVAO); glGenBuffers(1, &cubeVBO); glBindVertexArray(cubeVAO); glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, 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))); - glBindVertexArray(0); - // Setup plane VAO - GLuint floorVAO, floorVBO; - glGenVertexArrays(1, &floorVAO); - glGenBuffers(1, &floorVBO); - glBindVertexArray(floorVAO); - glBindBuffer(GL_ARRAY_BUFFER, floorVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(floorVertices), &floorVertices, GL_STATIC_DRAW); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); + // plane VAO + unsigned int planeVAO, planeVBO; + glGenVertexArrays(1, &planeVAO); + glGenBuffers(1, &planeVBO); + glBindVertexArray(planeVAO); + glBindBuffer(GL_ARRAY_BUFFER, planeVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), &planeVertices, 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))); - glBindVertexArray(0); - // Setup screen VAO - GLuint quadVAO, quadVBO; + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); + // screen quad VAO + unsigned int quadVAO, quadVBO; 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, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)(2 * sizeof(GLfloat))); - glBindVertexArray(0); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); - // Load textures - GLuint cubeTexture = loadTexture(FileSystem::getPath("resources/textures/container.jpg").c_str()); - GLuint floorTexture = loadTexture(FileSystem::getPath("resources/textures/metal.png").c_str()); - #pragma endregion + // load textures + // ------------- + unsigned int cubeTexture = loadTexture(FileSystem::getPath("resources/textures/marble.jpg").c_str()); + unsigned int floorTexture = loadTexture(FileSystem::getPath("resources/textures/metal.png").c_str()); - // Framebuffers - GLuint framebuffer; + // shader configuration + // -------------------- + shader.use(); + shader.setInt("texture1", 0); + + screenShader.use(); + screenShader.setInt("screenTexture", 0); + + // framebuffer configuration + // ------------------------- + unsigned int framebuffer; glGenFramebuffers(1, &framebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - // Create a color attachment texture - GLuint textureColorbuffer = generateAttachmentTexture(false, false); + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + // create a color attachment texture + unsigned int textureColorbuffer; + glGenTextures(1, &textureColorbuffer); + glBindTexture(GL_TEXTURE_2D, textureColorbuffer); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureColorbuffer, 0); - // Create a renderbuffer object for depth and stencil attachment (we won't be sampling these) - GLuint rbo; + // create a renderbuffer object for depth and stencil attachment (we won't be sampling these) + unsigned int rbo; glGenRenderbuffers(1, &rbo); - glBindRenderbuffer(GL_RENDERBUFFER, rbo); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, screenWidth, screenHeight); // Use a single renderbuffer object for both a depth AND stencil buffer. - glBindRenderbuffer(GL_RENDERBUFFER, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); // Now actually attach it - // Now that we actually created the framebuffer and added all attachments we want to check if it is actually complete now - if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, SCR_WIDTH, SCR_HEIGHT); // use a single renderbuffer object for both a depth AND stencil buffer. + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); // now actually attach it + // now that we actually created the framebuffer and added all attachments we want to check if it is actually complete now + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << endl; glBindFramebuffer(GL_FRAMEBUFFER, 0); - - // Draw as wireframe + // draw as wireframe //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - // Game loop - while(!glfwWindowShouldClose(window)) + // 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); - - ///////////////////////////////////////////////////// - // Bind to framebuffer and draw to color texture - // as we normally would. - // ////////////////////////////////////////////////// + + // first render pass: mirror texture. + // bind to framebuffer and draw to color texture as we normally + // would, but with the view camera reversed. + // bind to framebuffer and draw scene as we normally would to color texture + // ------------------------------------------------------------------------ glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - // Clear all attached buffers + glEnable(GL_DEPTH_TEST); // enable depth testing (is disabled for rendering screen-space quad) + + // make sure we clear the framebuffer's content glClearColor(0.1f, 0.1f, 0.1f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // We're not using stencil buffer so why bother with clearing? + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glEnable(GL_DEPTH_TEST); - // Set uniforms - shader.Use(); + shader.use(); glm::mat4 model; + camera.Yaw += 180.0f; // rotate the camera's yaw 180 degrees around + camera.Pitch += 180.0f; // rotate the camera's pitch 180 degrees around + camera.ProcessMouseMovement(0, 0, false); // call this to make sure it updates its camera vectors, note that we disable pitch constrains for this specific case (otherwise we can't reverse camera's pitch values) glm::mat4 view = camera.GetViewMatrix(); - glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth/(float)screenHeight, 0.1f, 100.0f); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); - - // Floor - glBindVertexArray(floorVAO); - glBindTexture(GL_TEXTURE_2D, floorTexture); - model = glm::mat4(); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - glDrawArrays(GL_TRIANGLES, 0, 6); - glBindVertexArray(0); - // Cubes + camera.Yaw -= 180.0f; // reset it back to its original orientation + camera.Pitch -= 180.0f; + camera.ProcessMouseMovement(0, 0, true); + glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); + shader.setMat4("view", view); + shader.setMat4("projection", projection); + // cubes glBindVertexArray(cubeVAO); - glBindTexture(GL_TEXTURE_2D, cubeTexture); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, cubeTexture); model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); + shader.setMat4("model", model); glDrawArrays(GL_TRIANGLES, 0, 36); model = glm::mat4(); model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); + shader.setMat4("model", model); glDrawArrays(GL_TRIANGLES, 0, 36); - glBindVertexArray(0); - - ///////////////////////////////////////////////////// - // Bind to default framebuffer again and draw the - // quad plane with attched screen texture. - // ////////////////////////////////////////////////// - glBindFramebuffer(GL_FRAMEBUFFER, 0); - // Clear all relevant buffers - glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Set clear color to white (not really necessery actually, since we won't be able to see behind the quad anyways) - glClear(GL_COLOR_BUFFER_BIT); - glDisable(GL_DEPTH_TEST); // We don't care about depth information when rendering a single quad - - // Draw Screen - screenShader.Use(); - glBindVertexArray(quadVAO); - glBindTexture(GL_TEXTURE_2D, textureColorbuffer); // Use the color attachment texture as the texture of the quad plane + // floor + glBindVertexArray(planeVAO); + glBindTexture(GL_TEXTURE_2D, floorTexture); + shader.setMat4("model", glm::mat4()); glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); + // second render pass: draw as normal + // ---------------------------------- + glBindFramebuffer(GL_FRAMEBUFFER, 0); - // Swap the buffers + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + model = glm::mat4(); + view = camera.GetViewMatrix(); + shader.setMat4("view", view); + + // cubes + glBindVertexArray(cubeVAO); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, cubeTexture); + model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f)); + shader.setMat4("model", model); + glDrawArrays(GL_TRIANGLES, 0, 36); + model = glm::mat4(); + model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f)); + shader.setMat4("model", model); + glDrawArrays(GL_TRIANGLES, 0, 36); + // floor + glBindVertexArray(planeVAO); + glBindTexture(GL_TEXTURE_2D, floorTexture); + shader.setMat4("model", glm::mat4()); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); + + // now draw the mirror quad with screen texture + // -------------------------------------------- + glDisable(GL_DEPTH_TEST); // disable depth test so screen-space quad isn't discarded due to depth test. + + screenShader.use(); + glBindVertexArray(quadVAO); + glBindTexture(GL_TEXTURE_2D, textureColorbuffer); // use the color attachment texture as the texture of the quad plane + glDrawArrays(GL_TRIANGLES, 0, 6); + + + // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) + // ------------------------------------------------------------------------------- glfwSwapBuffers(window); + glfwPollEvents(); } - // Clean up - glDeleteFramebuffers(1, &framebuffer); + // optional: de-allocate all resources once they've outlived their purpose: + // ------------------------------------------------------------------------ + glDeleteVertexArrays(1, &cubeVAO); + glDeleteVertexArrays(1, &planeVAO); + glDeleteVertexArrays(1, &quadVAO); + glDeleteBuffers(1, &cubeVBO); + glDeleteBuffers(1, &planeVBO); + glDeleteBuffers(1, &quadVBO); glfwTerminate(); return 0; } -// This function loads a texture from file. Note: texture loading functions like these are usually -// managed by a 'Resource Manager' that manages all resources (like textures, models, audio). -// For learning purposes we'll just define it as a utility function. -GLuint loadTexture(GLchar const * path, GLboolean alpha) +// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly +// --------------------------------------------------------------------------------------------------------- +void processInput(GLFWwindow *window) { - //Generate texture ID and load texture data - GLuint textureID; - glGenTextures(1, &textureID); - int width,height; - unsigned char* image = SOIL_load_image(path, &width, &height, 0, alpha ? SOIL_LOAD_RGBA : SOIL_LOAD_RGB); - // Assign texture to ID - glBindTexture(GL_TEXTURE_2D, textureID); - glTexImage2D(GL_TEXTURE_2D, 0, alpha ? GL_RGBA : GL_RGB, width, height, 0, alpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, image); - glGenerateMipmap(GL_TEXTURE_2D); + if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) + glfwSetWindowShouldClose(window, true); - // Parameters - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, alpha ? GL_CLAMP_TO_EDGE : GL_REPEAT ); // Use GL_MIRRORED_REPEAT to prevent white borders. Due to interpolation it takes value from next repeat - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, alpha ? GL_CLAMP_TO_EDGE : 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; -} - -// Generates a texture that is suited for attachments to a framebuffer -GLuint generateAttachmentTexture(GLboolean depth, GLboolean stencil) -{ - // What enum to use? - GLenum attachment_type; - if(!depth && !stencil) - attachment_type = GL_RGB; - else if(depth && !stencil) - attachment_type = GL_DEPTH_COMPONENT; - else if(!depth && stencil) - attachment_type = GL_STENCIL_INDEX; - - //Generate texture ID and load texture data - GLuint textureID; - glGenTextures(1, &textureID); - glBindTexture(GL_TEXTURE_2D, textureID); - if(!depth && !stencil) - glTexImage2D(GL_TEXTURE_2D, 0, attachment_type, screenWidth, screenHeight, 0, attachment_type, GL_UNSIGNED_BYTE, NULL); - else // Using both a stencil and depth test, needs special format arguments - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, screenWidth, screenHeight, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glBindTexture(GL_TEXTURE_2D, 0); - - return textureID; -} - -#pragma region "User input" - -// 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); } -// Is called whenever a key is pressed/released via GLFW -void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) +// glfw: whenever the window size changed (by OS or user resize) this callback function executes +// --------------------------------------------------------------------------------------------- +void framebuffer_size_callback(GLFWwindow* window, int width, int height) { - if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) - glfwSetWindowShouldClose(window, GL_TRUE); - - if(action == GLFW_PRESS) - keys[key] = true; - else if(action == GLFW_RELEASE) - keys[key] = false; + // make sure the viewport matches the new window dimensions; note that width and + // height will be significantly larger than specified on retina displays. + glViewport(0, 0, width, height); } + +// glfw: whenever the mouse moves, this callback is called +// ------------------------------------------------------- void mouse_callback(GLFWwindow* window, double xpos, double ypos) { - if(firstMouse) + if (firstMouse) { lastX = xpos; lastY = ypos; firstMouse = false; } - GLfloat xoffset = xpos - lastX; - GLfloat yoffset = lastY - ypos; - + float xoffset = xpos - lastX; + float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top + lastX = xpos; lastY = ypos; 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); } -#pragma endregion \ No newline at end of file +// utility function for loading a 2D texture from file +// --------------------------------------------------- +unsigned int loadTexture(char const * path) +{ + 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); + + 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 diff --git a/src/4.advanced_opengl/6.1.cubemaps_skybox/6.1.cubemaps.fs b/src/4.advanced_opengl/6.1.cubemaps_skybox/6.1.cubemaps.fs index 3312115..b342078 100644 --- a/src/4.advanced_opengl/6.1.cubemaps_skybox/6.1.cubemaps.fs +++ b/src/4.advanced_opengl/6.1.cubemaps_skybox/6.1.cubemaps.fs @@ -1,14 +1,11 @@ #version 330 core -in vec3 Normal; -in vec3 Position; -out vec4 color; +out vec4 FragColor; -uniform vec3 cameraPos; -uniform samplerCube skybox; +in vec2 TexCoords; + +uniform sampler2D texture1; void main() -{ - vec3 I = normalize(Position - cameraPos); - vec3 R = reflect(I, normalize(Normal)); - color = texture(skybox, R); +{ + FragColor = texture(texture1, TexCoords); } \ No newline at end of file diff --git a/src/4.advanced_opengl/6.1.cubemaps_skybox/6.1.cubemaps.vs b/src/4.advanced_opengl/6.1.cubemaps_skybox/6.1.cubemaps.vs index 8b2fa18..95cb343 100644 --- a/src/4.advanced_opengl/6.1.cubemaps_skybox/6.1.cubemaps.vs +++ b/src/4.advanced_opengl/6.1.cubemaps_skybox/6.1.cubemaps.vs @@ -1,9 +1,8 @@ #version 330 core -layout (location = 0) in vec3 position; -layout (location = 1) in vec3 normal; +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTexCoords; -out vec3 Normal; -out vec3 Position; +out vec2 TexCoords; uniform mat4 model; uniform mat4 view; @@ -11,7 +10,6 @@ uniform mat4 projection; void main() { - gl_Position = projection * view * model * vec4(position, 1.0f); - Normal = mat3(transpose(inverse(model))) * normal; - Position = vec3(model * vec4(position, 1.0f)); -} \ No newline at end of file + TexCoords = aTexCoords; + gl_Position = projection * view * model * vec4(aPos, 1.0f); +} \ No newline at end of file diff --git a/src/4.advanced_opengl/6.1.cubemaps_skybox/6.1.skybox.fs b/src/4.advanced_opengl/6.1.cubemaps_skybox/6.1.skybox.fs index 6bd48f3..5d0e53e 100644 --- a/src/4.advanced_opengl/6.1.cubemaps_skybox/6.1.skybox.fs +++ b/src/4.advanced_opengl/6.1.cubemaps_skybox/6.1.skybox.fs @@ -1,10 +1,11 @@ #version 330 core +out vec4 FragColor; + in vec3 TexCoords; -out vec4 color; uniform samplerCube skybox; void main() { - color = texture(skybox, TexCoords); + FragColor = texture(skybox, TexCoords); } \ No newline at end of file diff --git a/src/4.advanced_opengl/6.1.cubemaps_skybox/6.1.skybox.vs b/src/4.advanced_opengl/6.1.cubemaps_skybox/6.1.skybox.vs index 481432d..0d20a97 100644 --- a/src/4.advanced_opengl/6.1.cubemaps_skybox/6.1.skybox.vs +++ b/src/4.advanced_opengl/6.1.cubemaps_skybox/6.1.skybox.vs @@ -1,14 +1,14 @@ #version 330 core -layout (location = 0) in vec3 position; +layout (location = 0) in vec3 aPos; + out vec3 TexCoords; uniform mat4 projection; uniform mat4 view; - void main() { - vec4 pos = projection * view * vec4(position, 1.0); + TexCoords = aPos; + vec4 pos = projection * view * vec4(aPos, 1.0); gl_Position = pos.xyww; - TexCoords = position; } \ No newline at end of file diff --git a/src/4.advanced_opengl/6.1.cubemaps_skybox/cubemaps_skybox.cpp b/src/4.advanced_opengl/6.1.cubemaps_skybox/cubemaps_skybox.cpp index 99db806..0ab5fff 100644 --- a/src/4.advanced_opengl/6.1.cubemaps_skybox/cubemaps_skybox.cpp +++ b/src/4.advanced_opengl/6.1.cubemaps_skybox/cubemaps_skybox.cpp @@ -1,356 +1,312 @@ -// Std. Includes -#include -#include -using namespace std; - -// 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 -GLuint screenWidth = 800, screenHeight = 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); -GLuint loadCubemap(std::vector faces); +void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); +void processInput(GLFWwindow *window); +unsigned int loadTexture(const char *path); +unsigned int loadCubemap(vector faces); -// Camera +// settings +const unsigned int SCR_WIDTH = 1280; +const unsigned int SCR_HEIGHT = 720; + +// camera Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); -bool keys[1024]; -GLfloat lastX = 400, lastY = 300; +float lastX = (float)SCR_WIDTH / 2.0; +float lastY = (float)SCR_HEIGHT / 2.0; bool firstMouse = true; -GLfloat deltaTime = 0.0f; -GLfloat lastFrame = 0.0f; +// timing +float deltaTime = 0.0f; +float lastFrame = 0.0f; - - -// 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(screenWidth, screenHeight, "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, screenWidth, screenHeight); - - // Setup some OpenGL options + // configure global opengl state + // ----------------------------- glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - // Setup and compile our shaders - Shader shader("cubemaps.vs", "cubemaps.frag"); - Shader skyboxShader("skybox.vs", "skybox.frag"); + // build and compile shaders + // ------------------------- + Shader shader("6.1.cubemaps.vs", "6.1.cubemaps.fs"); + Shader skyboxShader("6.1.skybox.vs", "6.1.skybox.fs"); -#pragma region "object_initialization" - // Set the object data (buffers, vertex attributes) - GLfloat cubeVertices[] = { - // Positions // Normals - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + // set up vertex data (and buffer(s)) and configure vertex attributes + // ------------------------------------------------------------------ + float cubeVertices[] = { + // positions // texture Coords + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, + 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, + 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, + 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f }; - GLfloat skyboxVertices[] = { - // Positions - -1.0f, 1.0f, -1.0f, + float skyboxVertices[] = { + // positions + -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, - 1.0f, -1.0f, -1.0f, - 1.0f, -1.0f, -1.0f, - 1.0f, 1.0f, -1.0f, - -1.0f, 1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, - -1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, - -1.0f, 1.0f, -1.0f, - -1.0f, 1.0f, -1.0f, - -1.0f, 1.0f, 1.0f, - -1.0f, -1.0f, 1.0f, + -1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, - 1.0f, -1.0f, -1.0f, - 1.0f, -1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, -1.0f, - 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, - -1.0f, -1.0f, 1.0f, - -1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 1.0f, - -1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, - -1.0f, 1.0f, -1.0f, - 1.0f, 1.0f, -1.0f, - 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, - -1.0f, -1.0f, 1.0f, - 1.0f, -1.0f, -1.0f, - 1.0f, -1.0f, -1.0f, - -1.0f, -1.0f, 1.0f, - 1.0f, -1.0f, 1.0f + -1.0f, -1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, 1.0f, + 1.0f, -1.0f, 1.0f }; - // Setup cube VAO - GLuint cubeVAO, cubeVBO; + // cube VAO + unsigned int cubeVAO, cubeVBO; glGenVertexArrays(1, &cubeVAO); glGenBuffers(1, &cubeVBO); glBindVertexArray(cubeVAO); glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); - glBindVertexArray(0); - // Setup skybox VAO - GLuint skyboxVAO, skyboxVBO; + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); + // skybox VAO + unsigned int skyboxVAO, skyboxVBO; glGenVertexArrays(1, &skyboxVAO); glGenBuffers(1, &skyboxVBO); glBindVertexArray(skyboxVAO); glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); - glBindVertexArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); -#pragma endregion + // load textures + // ------------- + unsigned int cubeTexture = loadTexture(FileSystem::getPath("resources/textures/marble.jpg").c_str()); - // Cubemap (Skybox) - std::vector faces; - faces.push_back(FileSystem::getPath("resources/textures/skybox/right.jpg")); - faces.push_back(FileSystem::getPath("resources/textures/skybox/left.jpg")); - faces.push_back(FileSystem::getPath("resources/textures/skybox/top.jpg")); - faces.push_back(FileSystem::getPath("resources/textures/skybox/bottom.jpg")); - faces.push_back(FileSystem::getPath("resources/textures/skybox/back.jpg")); - faces.push_back(FileSystem::getPath("resources/textures/skybox/front.jpg")); - GLuint skyboxTexture = loadCubemap(faces); + vector faces + { + FileSystem::getPath("resources/textures/skybox/right.jpg"), + FileSystem::getPath("resources/textures/skybox/left.jpg"), + FileSystem::getPath("resources/textures/skybox/top.jpg"), + FileSystem::getPath("resources/textures/skybox/bottom.jpg"), + FileSystem::getPath("resources/textures/skybox/back.jpg"), + FileSystem::getPath("resources/textures/skybox/front.jpg") + }; + unsigned int cubemapTexture = loadCubemap(faces); - // Draw as wireframe - //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + // shader configuration + // -------------------- + shader.use(); + shader.setInt("texture1", 0); - // Game loop + skyboxShader.use(); + skyboxShader.setInt("skybox", 0); + + // 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 buffers + // render + // ------ glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // Draw scene as normal - shader.Use(); + // draw scene as normal + shader.use(); glm::mat4 model; glm::mat4 view = camera.GetViewMatrix(); - glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth / (float)screenHeight, 0.1f, 100.0f); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); - glUniform3f(glGetUniformLocation(shader.Program, "cameraPos"), camera.Position.x, camera.Position.y, camera.Position.z); - // Cubes + glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); + shader.setMat4("model", model); + shader.setMat4("view", view); + shader.setMat4("projection", projection); + // cubes glBindVertexArray(cubeVAO); - glBindTexture(GL_TEXTURE_CUBE_MAP, skyboxTexture); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, cubeTexture); glDrawArrays(GL_TRIANGLES, 0, 36); glBindVertexArray(0); - // Draw skybox as last - glDepthFunc(GL_LEQUAL); // Change depth function so depth test passes when values are equal to depth buffer's content - skyboxShader.Use(); - view = glm::mat4(glm::mat3(camera.GetViewMatrix())); // Remove any translation component of the view matrix - glUniformMatrix4fv(glGetUniformLocation(skyboxShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); - glUniformMatrix4fv(glGetUniformLocation(skyboxShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); + // draw skybox as last + glDepthFunc(GL_LEQUAL); // change depth function so depth test passes when values are equal to depth buffer's content + skyboxShader.use(); + view = glm::mat4(glm::mat3(camera.GetViewMatrix())); // remove translation from the view matrix + skyboxShader.setMat4("view", view); + skyboxShader.setMat4("projection", projection); // skybox cube glBindVertexArray(skyboxVAO); - glBindTexture(GL_TEXTURE_CUBE_MAP, skyboxTexture); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture); glDrawArrays(GL_TRIANGLES, 0, 36); glBindVertexArray(0); - glDepthFunc(GL_LESS); // Set depth function back to default + glDepthFunc(GL_LESS); // set depth function back to default - - // Swap the buffers + // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) + // ------------------------------------------------------------------------------- glfwSwapBuffers(window); + glfwPollEvents(); } + // optional: de-allocate all resources once they've outlived their purpose: + // ------------------------------------------------------------------------ + glDeleteVertexArrays(1, &cubeVAO); + glDeleteVertexArrays(1, &skyboxVAO); + glDeleteBuffers(1, &cubeVBO); + glDeleteBuffers(1, &skyboxVAO); + glfwTerminate(); return 0; } -// Loads a cubemap texture from 6 individual texture faces -// Order should be: -// +X (right) -// -X (left) -// +Y (top) -// -Y (bottom) -// +Z (front)? (CHECK THIS) -// -Z (back)? -GLuint loadCubemap(std::vector faces) +// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly +// --------------------------------------------------------------------------------------------------------- +void processInput(GLFWwindow *window) { - GLuint textureID; - glGenTextures(1, &textureID); - glActiveTexture(GL_TEXTURE0); + if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) + glfwSetWindowShouldClose(window, true); - int width, height; - unsigned char* image; - - glBindTexture(GL_TEXTURE_CUBE_MAP, textureID); - for (GLuint i = 0; i < faces.size(); i++) - { - image = SOIL_load_image(faces[i].c_str(), &width, &height, 0, SOIL_LOAD_RGB); - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); - } - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - 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); - glBindTexture(GL_TEXTURE_CUBE_MAP, 0); - - return textureID; -} - - -// 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_RGB, 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; -} - -#pragma region "User input" - -// 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); } -// Is called whenever a key is pressed/released via GLFW -void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) +// glfw: whenever the window size changed (by OS or user resize) this callback function executes +// --------------------------------------------------------------------------------------------- +void framebuffer_size_callback(GLFWwindow* window, int width, int height) { - if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) - glfwSetWindowShouldClose(window, GL_TRUE); - - if (action == GLFW_PRESS) - keys[key] = true; - else if (action == GLFW_RELEASE) - keys[key] = false; + // make sure the viewport matches the new window dimensions; note that width and + // height will be significantly larger than specified on retina displays. + glViewport(0, 0, width, height); } + +// glfw: whenever the mouse moves, this callback is called +// ------------------------------------------------------- void mouse_callback(GLFWwindow* window, double xpos, double ypos) { if (firstMouse) @@ -360,8 +316,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; @@ -369,9 +325,87 @@ 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); } -#pragma endregion \ No newline at end of file +// utility function for loading a 2D texture from file +// --------------------------------------------------- +unsigned int loadTexture(char const * path) +{ + 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); + + 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; +} + +// loads a cubemap texture from 6 individual texture faces +// order: +// +X (right) +// -X (left) +// +Y (top) +// -Y (bottom) +// +Z (front) +// -Z (back) +// ------------------------------------------------------- +unsigned int loadCubemap(vector faces) +{ + unsigned int textureID; + glGenTextures(1, &textureID); + glBindTexture(GL_TEXTURE_CUBE_MAP, textureID); + + int width, height, nrComponents; + for (unsigned int i = 0; i < faces.size(); i++) + { + unsigned char *data = stbi_load(faces[i].c_str(), &width, &height, &nrComponents, 0); + if (data) + { + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); + stbi_image_free(data); + } + else + { + std::cout << "Cubemap texture failed to load at path: " << faces[i] << std::endl; + stbi_image_free(data); + } + } + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + 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); + + return textureID; +} \ No newline at end of file diff --git a/src/4.advanced_opengl/6.2.cubemaps_environment_mapping/6.2.cubemaps.fs b/src/4.advanced_opengl/6.2.cubemaps_environment_mapping/6.2.cubemaps.fs index 3312115..b2bf16f 100644 --- a/src/4.advanced_opengl/6.2.cubemaps_environment_mapping/6.2.cubemaps.fs +++ b/src/4.advanced_opengl/6.2.cubemaps_environment_mapping/6.2.cubemaps.fs @@ -1,14 +1,15 @@ #version 330 core +out vec4 FragColor; + in vec3 Normal; in vec3 Position; -out vec4 color; uniform vec3 cameraPos; uniform samplerCube skybox; void main() -{ +{ vec3 I = normalize(Position - cameraPos); vec3 R = reflect(I, normalize(Normal)); - color = texture(skybox, R); + FragColor = vec4(texture(skybox, R).rgb, 1.0); } \ No newline at end of file diff --git a/src/4.advanced_opengl/6.2.cubemaps_environment_mapping/6.2.cubemaps.vs b/src/4.advanced_opengl/6.2.cubemaps_environment_mapping/6.2.cubemaps.vs index 8b2fa18..1447070 100644 --- a/src/4.advanced_opengl/6.2.cubemaps_environment_mapping/6.2.cubemaps.vs +++ b/src/4.advanced_opengl/6.2.cubemaps_environment_mapping/6.2.cubemaps.vs @@ -1,6 +1,6 @@ #version 330 core -layout (location = 0) in vec3 position; -layout (location = 1) in vec3 normal; +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; out vec3 Normal; out vec3 Position; @@ -11,7 +11,7 @@ uniform mat4 projection; void main() { - gl_Position = projection * view * model * vec4(position, 1.0f); - Normal = mat3(transpose(inverse(model))) * normal; - Position = vec3(model * vec4(position, 1.0f)); -} \ No newline at end of file + Normal = mat3(transpose(inverse(model))) * aNormal; + Position = vec3(model * vec4(aPos, 1.0)); + gl_Position = projection * view * model * vec4(aPos, 1.0); +} \ No newline at end of file diff --git a/src/4.advanced_opengl/6.2.cubemaps_environment_mapping/cubemaps_environment_mapping.cpp b/src/4.advanced_opengl/6.2.cubemaps_environment_mapping/cubemaps_environment_mapping.cpp index 99db806..a9946dd 100644 --- a/src/4.advanced_opengl/6.2.cubemaps_environment_mapping/cubemaps_environment_mapping.cpp +++ b/src/4.advanced_opengl/6.2.cubemaps_environment_mapping/cubemaps_environment_mapping.cpp @@ -1,356 +1,311 @@ -// Std. Includes -#include -#include -using namespace std; - -// 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 -GLuint screenWidth = 800, screenHeight = 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); -GLuint loadCubemap(std::vector faces); +void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); +void processInput(GLFWwindow *window); +unsigned int loadTexture(const char *path); +unsigned int loadCubemap(vector faces); -// Camera +// settings +const unsigned int SCR_WIDTH = 1280; +const unsigned int SCR_HEIGHT = 720; + +// camera Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); -bool keys[1024]; -GLfloat lastX = 400, lastY = 300; +float lastX = (float)SCR_WIDTH / 2.0; +float lastY = (float)SCR_HEIGHT / 2.0; bool firstMouse = true; -GLfloat deltaTime = 0.0f; -GLfloat lastFrame = 0.0f; +// timing +float deltaTime = 0.0f; +float lastFrame = 0.0f; - - -// 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(screenWidth, screenHeight, "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, screenWidth, screenHeight); - - // Setup some OpenGL options + // configure global opengl state + // ----------------------------- glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - // Setup and compile our shaders - Shader shader("cubemaps.vs", "cubemaps.frag"); - Shader skyboxShader("skybox.vs", "skybox.frag"); + // build and compile shaders + // ------------------------- + Shader shader("6.2.cubemaps.vs", "6.2.cubemaps.fs"); + Shader skyboxShader("6.1.skybox.vs", "6.1.skybox.fs"); -#pragma region "object_initialization" - // Set the object data (buffers, vertex attributes) - GLfloat cubeVertices[] = { - // Positions // Normals - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + // set up vertex data (and buffer(s)) and configure vertex attributes + // ------------------------------------------------------------------ + float cubeVertices[] = { + // positions // normals + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f }; - GLfloat skyboxVertices[] = { - // Positions - -1.0f, 1.0f, -1.0f, + float skyboxVertices[] = { + // positions + -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, - 1.0f, -1.0f, -1.0f, - 1.0f, -1.0f, -1.0f, - 1.0f, 1.0f, -1.0f, - -1.0f, 1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, - -1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, - -1.0f, 1.0f, -1.0f, - -1.0f, 1.0f, -1.0f, - -1.0f, 1.0f, 1.0f, - -1.0f, -1.0f, 1.0f, + -1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, - 1.0f, -1.0f, -1.0f, - 1.0f, -1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, -1.0f, - 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, - -1.0f, -1.0f, 1.0f, - -1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 1.0f, - -1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, - -1.0f, 1.0f, -1.0f, - 1.0f, 1.0f, -1.0f, - 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, - -1.0f, -1.0f, 1.0f, - 1.0f, -1.0f, -1.0f, - 1.0f, -1.0f, -1.0f, - -1.0f, -1.0f, 1.0f, - 1.0f, -1.0f, 1.0f + -1.0f, -1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, 1.0f, + 1.0f, -1.0f, 1.0f }; - // Setup cube VAO - GLuint cubeVAO, cubeVBO; + // cube VAO + unsigned int cubeVAO, cubeVBO; glGenVertexArrays(1, &cubeVAO); glGenBuffers(1, &cubeVBO); glBindVertexArray(cubeVAO); glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); - glBindVertexArray(0); - // Setup skybox VAO - GLuint skyboxVAO, skyboxVBO; + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float))); + // skybox VAO + unsigned int skyboxVAO, skyboxVBO; glGenVertexArrays(1, &skyboxVAO); glGenBuffers(1, &skyboxVBO); glBindVertexArray(skyboxVAO); glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); - glBindVertexArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); -#pragma endregion + // load textures + // ------------- + vector faces + { + FileSystem::getPath("resources/textures/skybox/right.jpg"), + FileSystem::getPath("resources/textures/skybox/left.jpg"), + FileSystem::getPath("resources/textures/skybox/top.jpg"), + FileSystem::getPath("resources/textures/skybox/bottom.jpg"), + FileSystem::getPath("resources/textures/skybox/back.jpg"), + FileSystem::getPath("resources/textures/skybox/front.jpg") + }; + unsigned int cubemapTexture = loadCubemap(faces); - // Cubemap (Skybox) - std::vector faces; - faces.push_back(FileSystem::getPath("resources/textures/skybox/right.jpg")); - faces.push_back(FileSystem::getPath("resources/textures/skybox/left.jpg")); - faces.push_back(FileSystem::getPath("resources/textures/skybox/top.jpg")); - faces.push_back(FileSystem::getPath("resources/textures/skybox/bottom.jpg")); - faces.push_back(FileSystem::getPath("resources/textures/skybox/back.jpg")); - faces.push_back(FileSystem::getPath("resources/textures/skybox/front.jpg")); - GLuint skyboxTexture = loadCubemap(faces); + // shader configuration + // -------------------- + shader.use(); + shader.setInt("skybox", 0); - // Draw as wireframe - //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + skyboxShader.use(); + skyboxShader.setInt("skybox", 0); - // 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 buffers + // render + // ------ glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // Draw scene as normal - shader.Use(); + // draw scene as normal + shader.use(); glm::mat4 model; glm::mat4 view = camera.GetViewMatrix(); - glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth / (float)screenHeight, 0.1f, 100.0f); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); - glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); - glUniform3f(glGetUniformLocation(shader.Program, "cameraPos"), camera.Position.x, camera.Position.y, camera.Position.z); - // Cubes + glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); + shader.setMat4("model", model); + shader.setMat4("view", view); + shader.setMat4("projection", projection); + shader.setVec3("cameraPos", camera.Position); + // cubes glBindVertexArray(cubeVAO); - glBindTexture(GL_TEXTURE_CUBE_MAP, skyboxTexture); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture); glDrawArrays(GL_TRIANGLES, 0, 36); glBindVertexArray(0); - // Draw skybox as last - glDepthFunc(GL_LEQUAL); // Change depth function so depth test passes when values are equal to depth buffer's content - skyboxShader.Use(); - view = glm::mat4(glm::mat3(camera.GetViewMatrix())); // Remove any translation component of the view matrix - glUniformMatrix4fv(glGetUniformLocation(skyboxShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); - glUniformMatrix4fv(glGetUniformLocation(skyboxShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); + // draw skybox as last + glDepthFunc(GL_LEQUAL); // change depth function so depth test passes when values are equal to depth buffer's content + skyboxShader.use(); + view = glm::mat4(glm::mat3(camera.GetViewMatrix())); // remove translation from the view matrix + skyboxShader.setMat4("view", view); + skyboxShader.setMat4("projection", projection); // skybox cube glBindVertexArray(skyboxVAO); - glBindTexture(GL_TEXTURE_CUBE_MAP, skyboxTexture); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture); glDrawArrays(GL_TRIANGLES, 0, 36); glBindVertexArray(0); - glDepthFunc(GL_LESS); // Set depth function back to default + glDepthFunc(GL_LESS); // set depth function back to default - - // Swap the buffers + // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) + // ------------------------------------------------------------------------------- glfwSwapBuffers(window); + glfwPollEvents(); } + // optional: de-allocate all resources once they've outlived their purpose: + // ------------------------------------------------------------------------ + glDeleteVertexArrays(1, &cubeVAO); + glDeleteVertexArrays(1, &skyboxVAO); + glDeleteBuffers(1, &cubeVBO); + glDeleteBuffers(1, &skyboxVAO); + glfwTerminate(); return 0; } -// Loads a cubemap texture from 6 individual texture faces -// Order should be: -// +X (right) -// -X (left) -// +Y (top) -// -Y (bottom) -// +Z (front)? (CHECK THIS) -// -Z (back)? -GLuint loadCubemap(std::vector faces) +// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly +// --------------------------------------------------------------------------------------------------------- +void processInput(GLFWwindow *window) { - GLuint textureID; - glGenTextures(1, &textureID); - glActiveTexture(GL_TEXTURE0); + if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) + glfwSetWindowShouldClose(window, true); - int width, height; - unsigned char* image; - - glBindTexture(GL_TEXTURE_CUBE_MAP, textureID); - for (GLuint i = 0; i < faces.size(); i++) - { - image = SOIL_load_image(faces[i].c_str(), &width, &height, 0, SOIL_LOAD_RGB); - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); - } - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - 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); - glBindTexture(GL_TEXTURE_CUBE_MAP, 0); - - return textureID; -} - - -// 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_RGB, 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; -} - -#pragma region "User input" - -// 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); } -// Is called whenever a key is pressed/released via GLFW -void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) +// glfw: whenever the window size changed (by OS or user resize) this callback function executes +// --------------------------------------------------------------------------------------------- +void framebuffer_size_callback(GLFWwindow* window, int width, int height) { - if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) - glfwSetWindowShouldClose(window, GL_TRUE); - - if (action == GLFW_PRESS) - keys[key] = true; - else if (action == GLFW_RELEASE) - keys[key] = false; + // make sure the viewport matches the new window dimensions; note that width and + // height will be significantly larger than specified on retina displays. + glViewport(0, 0, width, height); } + +// glfw: whenever the mouse moves, this callback is called +// ------------------------------------------------------- void mouse_callback(GLFWwindow* window, double xpos, double ypos) { if (firstMouse) @@ -360,8 +315,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; @@ -369,9 +324,87 @@ 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); } -#pragma endregion \ No newline at end of file +// utility function for loading a 2D texture from file +// --------------------------------------------------- +unsigned int loadTexture(char const * path) +{ + 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); + + 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; +} + +// loads a cubemap texture from 6 individual texture faces +// order: +// +X (right) +// -X (left) +// +Y (top) +// -Y (bottom) +// +Z (front) +// -Z (back) +// ------------------------------------------------------- +unsigned int loadCubemap(vector faces) +{ + unsigned int textureID; + glGenTextures(1, &textureID); + glBindTexture(GL_TEXTURE_CUBE_MAP, textureID); + + int width, height, nrComponents; + for (unsigned int i = 0; i < faces.size(); i++) + { + unsigned char *data = stbi_load(faces[i].c_str(), &width, &height, &nrComponents, 0); + if (data) + { + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); + stbi_image_free(data); + } + else + { + std::cout << "Cubemap texture failed to load at path: " << faces[i] << std::endl; + stbi_image_free(data); + } + } + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + 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); + + return textureID; +} \ No newline at end of file diff --git a/src/4.advanced_opengl/8.advanced_glsl_ubo/8.advanced_glsl.vs b/src/4.advanced_opengl/8.advanced_glsl_ubo/8.advanced_glsl.vs index 483f553..ffd2fbb 100644 --- a/src/4.advanced_opengl/8.advanced_glsl_ubo/8.advanced_glsl.vs +++ b/src/4.advanced_opengl/8.advanced_glsl_ubo/8.advanced_glsl.vs @@ -1,5 +1,5 @@ #version 330 core -layout (location = 0) in vec3 position; +layout (location = 0) in vec3 aPos; layout (std140) uniform Matrices { @@ -10,5 +10,5 @@ uniform mat4 model; void main() { - gl_Position = projection * view * model * vec4(position, 1.0); + gl_Position = projection * view * model * vec4(aPos, 1.0); } \ No newline at end of file diff --git a/src/4.advanced_opengl/8.advanced_glsl_ubo/8.blue.fs b/src/4.advanced_opengl/8.advanced_glsl_ubo/8.blue.fs index 1927785..04d1e31 100644 --- a/src/4.advanced_opengl/8.advanced_glsl_ubo/8.blue.fs +++ b/src/4.advanced_opengl/8.advanced_glsl_ubo/8.blue.fs @@ -1,7 +1,7 @@ #version 330 core -out vec4 color; +out vec4 FragColor; void main() { - color = vec4(0.0, 0.0, 1.0, 1.0); + FragColor = vec4(0.0, 0.0, 1.0, 1.0); } \ No newline at end of file diff --git a/src/4.advanced_opengl/8.advanced_glsl_ubo/8.green.fs b/src/4.advanced_opengl/8.advanced_glsl_ubo/8.green.fs index 3a81b6c..bfa8031 100644 --- a/src/4.advanced_opengl/8.advanced_glsl_ubo/8.green.fs +++ b/src/4.advanced_opengl/8.advanced_glsl_ubo/8.green.fs @@ -1,7 +1,7 @@ #version 330 core -out vec4 color; +out vec4 FragColor; void main() { - color = vec4(0.0, 1.0, 0.0, 1.0); + FragColor = vec4(0.0, 1.0, 0.0, 1.0); } \ No newline at end of file diff --git a/src/4.advanced_opengl/8.advanced_glsl_ubo/8.red.fs b/src/4.advanced_opengl/8.advanced_glsl_ubo/8.red.fs index 47956bd..1cc4493 100644 --- a/src/4.advanced_opengl/8.advanced_glsl_ubo/8.red.fs +++ b/src/4.advanced_opengl/8.advanced_glsl_ubo/8.red.fs @@ -1,7 +1,7 @@ #version 330 core -out vec4 color; +out vec4 FragColor; void main() { - color = vec4(1.0, 0.0, 0.0, 1.0); + FragColor = vec4(1.0, 0.0, 0.0, 1.0); } \ No newline at end of file diff --git a/src/4.advanced_opengl/8.advanced_glsl_ubo/8.yellow.fs b/src/4.advanced_opengl/8.advanced_glsl_ubo/8.yellow.fs index 54c1c12..6100872 100644 --- a/src/4.advanced_opengl/8.advanced_glsl_ubo/8.yellow.fs +++ b/src/4.advanced_opengl/8.advanced_glsl_ubo/8.yellow.fs @@ -1,7 +1,7 @@ #version 330 core -out vec4 color; +out vec4 FragColor; void main() { - color = vec4(1.0, 1.0, 0.0, 1.0); + FragColor = vec4(1.0, 1.0, 0.0, 1.0); } \ No newline at end of file diff --git a/src/4.advanced_opengl/8.advanced_glsl_ubo/advanced_glsl_ubo.cpp b/src/4.advanced_opengl/8.advanced_glsl_ubo/advanced_glsl_ubo.cpp index 0b24e83..fe868ab 100644 --- a/src/4.advanced_opengl/8.advanced_glsl_ubo/advanced_glsl_ubo.cpp +++ b/src/4.advanced_opengl/8.advanced_glsl_ubo/advanced_glsl_ubo.cpp @@ -1,105 +1,111 @@ -// 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 -GLuint screenWidth = 800, screenHeight = 600; +#include -// Function prototypes -void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode); +void framebuffer_size_callback(GLFWwindow* window, int width, int height); void mouse_callback(GLFWwindow* window, double xpos, double ypos); -void Do_Movement(); +void processInput(GLFWwindow *window); -// Camera +// settings +const unsigned int SCR_WIDTH = 1280; +const unsigned int SCR_HEIGHT = 720; + +// camera Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); -bool keys[1024]; -GLfloat lastX = 400, lastY = 300; +float lastX = (float)SCR_WIDTH / 2.0; +float lastY = (float)SCR_HEIGHT / 2.0; bool firstMouse = true; -GLfloat deltaTime = 0.0f; -GLfloat lastFrame = 0.0f; +// timing +float deltaTime = 0.0f; +float lastFrame = 0.0f; -// 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(screenWidth, screenHeight, "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); - // Options - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + // 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, screenWidth, screenHeight); - - // Setup some OpenGL options + // configure global opengl state + // ----------------------------- glEnable(GL_DEPTH_TEST); - // Setup and compile our shaders - Shader shaderRed("uniform_buffers.vs", "red.frag"); - Shader shaderGreen("uniform_buffers.vs", "green.frag"); - Shader shaderBlue("uniform_buffers.vs", "blue.frag"); - Shader shaderYellow("uniform_buffers.vs", "yellow.frag"); - - #pragma region "object_initialization" - - GLfloat cubeVertices[] = { - -0.5f, -0.5f, -0.5f, + // build and compile shaders + // ------------------------- + Shader shaderRed("8.advanced_glsl.vs", "8.red.fs"); + Shader shaderGreen("8.advanced_glsl.vs", "8.green.fs"); + Shader shaderBlue("8.advanced_glsl.vs", "8.blue.fs"); + Shader shaderYellow("8.advanced_glsl.vs", "8.yellow.fs"); + + // set up vertex data (and buffer(s)) and configure vertex attributes + // ------------------------------------------------------------------ + float cubeVertices[] = { + // positions + -0.5f, -0.5f, -0.5f, + 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, - 0.5f, -0.5f, -0.5f, - 0.5f, 0.5f, -0.5f, - -0.5f, -0.5f, -0.5f, - -0.5f, 0.5f, -0.5f, + 0.5f, 0.5f, -0.5f, + -0.5f, 0.5f, -0.5f, + -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, - 0.5f, -0.5f, 0.5f, + 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, - -0.5f, 0.5f, 0.5f, - -0.5f, 0.5f, -0.5f, + -0.5f, 0.5f, 0.5f, + -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, - -0.5f, 0.5f, 0.5f, + -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, - 0.5f, -0.5f, -0.5f, - 0.5f, 0.5f, -0.5f, - 0.5f, -0.5f, -0.5f, - 0.5f, 0.5f, 0.5f, - 0.5f, -0.5f, 0.5f, + 0.5f, 0.5f, -0.5f, + 0.5f, -0.5f, -0.5f, + 0.5f, -0.5f, -0.5f, + 0.5f, -0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, @@ -108,155 +114,161 @@ int main() -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, - -0.5f, 0.5f, -0.5f, - 0.5f, 0.5f, 0.5f, - 0.5f, 0.5f, -0.5f, - 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, - -0.5f, 0.5f, 0.5f + 0.5f, 0.5f, -0.5f, + 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, + -0.5f, 0.5f, 0.5f, + -0.5f, 0.5f, -0.5f, }; - - // Setup cube VAO - GLuint cubeVAO, cubeVBO; + // cube VAO + unsigned int cubeVAO, cubeVBO; glGenVertexArrays(1, &cubeVAO); glGenBuffers(1, &cubeVBO); glBindVertexArray(cubeVAO); glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); - glBindVertexArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); - #pragma endregion - - // Create a uniform buffer object - // First. We get the relevant block indices - GLuint uniformBlockIndexRed = glGetUniformBlockIndex(shaderRed.Program, "Matrices"); - GLuint uniformBlockIndexGreen = glGetUniformBlockIndex(shaderGreen.Program, "Matrices"); - GLuint uniformBlockIndexBlue = glGetUniformBlockIndex(shaderBlue.Program, "Matrices"); - GLuint uniformBlockIndexYellow = glGetUniformBlockIndex(shaderYellow.Program, "Matrices"); - // Then we link each shader's uniform block to this uniform binding point - glUniformBlockBinding(shaderRed.Program, uniformBlockIndexRed, 0); - glUniformBlockBinding(shaderGreen.Program, uniformBlockIndexGreen, 0); - glUniformBlockBinding(shaderBlue.Program, uniformBlockIndexBlue, 0); - glUniformBlockBinding(shaderYellow.Program, uniformBlockIndexYellow, 0); + // configure a uniform buffer object + // --------------------------------- + // first. We get the relevant block indices + unsigned int uniformBlockIndexRed = glGetUniformBlockIndex(shaderRed.ID, "Matrices"); + unsigned int uniformBlockIndexGreen = glGetUniformBlockIndex(shaderGreen.ID, "Matrices"); + unsigned int uniformBlockIndexBlue = glGetUniformBlockIndex(shaderBlue.ID, "Matrices"); + unsigned int uniformBlockIndexYellow = glGetUniformBlockIndex(shaderYellow.ID, "Matrices"); + // then we link each shader's uniform block to this uniform binding point + glUniformBlockBinding(shaderRed.ID, uniformBlockIndexRed, 0); + glUniformBlockBinding(shaderGreen.ID, uniformBlockIndexGreen, 0); + glUniformBlockBinding(shaderBlue.ID, uniformBlockIndexBlue, 0); + glUniformBlockBinding(shaderYellow.ID, uniformBlockIndexYellow, 0); // Now actually create the buffer - GLuint uboMatrices; + unsigned int uboMatrices; glGenBuffers(1, &uboMatrices); glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices); glBufferData(GL_UNIFORM_BUFFER, 2 * sizeof(glm::mat4), NULL, GL_STATIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); - // Define the range of the buffer that links to a uniform binding point + // define the range of the buffer that links to a uniform binding point glBindBufferRange(GL_UNIFORM_BUFFER, 0, uboMatrices, 0, 2 * sizeof(glm::mat4)); - // Store the projection matrix (we only have to do this once) (note: we're not using zoom anymore by changing the FoV. We only create the projection matrix once now) - glm::mat4 projection = glm::perspective(45.0f, (float)screenWidth/(float)screenHeight, 0.1f, 100.0f); + // store the projection matrix (we only do this once now) (note: we're not using zoom anymore by changing the FoV) + glm::mat4 projection = glm::perspective(45.0f, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), glm::value_ptr(projection)); glBindBuffer(GL_UNIFORM_BUFFER, 0); - - - // Game loop - while(!glfwWindowShouldClose(window)) + + // 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 buffers + // render + // ------ glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - // Set the view and projection matrix in the uniform block - we only have to do this once per loop iteration. - glm::mat4 view = camera.GetViewMatrix(); + // set the view and projection matrix in the uniform block - we only have to do this once per loop iteration. + glm::mat4 view = camera.GetViewMatrix(); glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices); glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(view)); glBindBuffer(GL_UNIFORM_BUFFER, 0); - // Draw 4 cubes + // draw 4 cubes // RED glBindVertexArray(cubeVAO); - shaderRed.Use(); + shaderRed.use(); glm::mat4 model; - model = glm::translate(model, glm::vec3(-0.75f, 0.75f, 0.0f)); // Move top-left - glUniformMatrix4fv(glGetUniformLocation(shaderRed.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - glDrawArrays(GL_TRIANGLES, 0, 36); + model = glm::translate(model, glm::vec3(-0.75f, 0.75f, 0.0f)); // move top-left + shaderRed.setMat4("model", model); + glDrawArrays(GL_TRIANGLES, 0, 36); // GREEN - shaderGreen.Use(); + shaderGreen.use(); model = glm::mat4(); - model = glm::translate(model, glm::vec3(0.75f, 0.75f, 0.0f)); // Move top-right - glUniformMatrix4fv(glGetUniformLocation(shaderGreen.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - glDrawArrays(GL_TRIANGLES, 0, 36); - // BLUE - shaderBlue.Use(); - model = glm::mat4(); - model = glm::translate(model, glm::vec3(-0.75f, -0.75f, 0.0f)); // Move bottom-left - glUniformMatrix4fv(glGetUniformLocation(shaderBlue.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - glDrawArrays(GL_TRIANGLES, 0, 36); + model = glm::translate(model, glm::vec3(0.75f, 0.75f, 0.0f)); // move top-right + shaderGreen.setMat4("model", model); + glDrawArrays(GL_TRIANGLES, 0, 36); // YELLOW - shaderYellow.Use(); + shaderYellow.use(); model = glm::mat4(); - model = glm::translate(model, glm::vec3(0.75f, -0.75f, 0.0f)); // Move bottom-right - glUniformMatrix4fv(glGetUniformLocation(shaderYellow.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); - glDrawArrays(GL_TRIANGLES, 0, 36); - glBindVertexArray(0); + model = glm::translate(model, glm::vec3(-0.75f, -0.75f, 0.0f)); // move bottom-left + shaderYellow.setMat4("model", model); + glDrawArrays(GL_TRIANGLES, 0, 36); + // BLUE + shaderBlue.use(); + model = glm::mat4(); + model = glm::translate(model, glm::vec3(0.75f, -0.75f, 0.0f)); // move bottom-right + shaderBlue.setMat4("model", model); + glDrawArrays(GL_TRIANGLES, 0, 36); - // Swap the buffers + // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) + // ------------------------------------------------------------------------------- glfwSwapBuffers(window); + glfwPollEvents(); } + // optional: de-allocate all resources once they've outlived their purpose: + // ------------------------------------------------------------------------ + glDeleteVertexArrays(1, &cubeVAO); + glDeleteBuffers(1, &cubeVBO); + glfwTerminate(); return 0; } -#pragma region "User input" -// Moves/alters the camera positions based on user input -void Do_Movement() +// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly +// --------------------------------------------------------------------------------------------------------- +void processInput(GLFWwindow *window) { - // Camera controls - if(keys[GLFW_KEY_W]) + 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(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); } -// Is called whenever a key is pressed/released via GLFW -void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) +// glfw: whenever the window size changed (by OS or user resize) this callback function executes +// --------------------------------------------------------------------------------------------- +void framebuffer_size_callback(GLFWwindow* window, int width, int height) { - if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) - glfwSetWindowShouldClose(window, GL_TRUE); - - if(action == GLFW_PRESS) - keys[key] = true; - else if(action == GLFW_RELEASE) - keys[key] = false; + // make sure the viewport matches the new window dimensions; note that width and + // height will be significantly larger than specified on retina displays. + glViewport(0, 0, width, height); } + +// glfw: whenever the mouse moves, this callback is called +// ------------------------------------------------------- void mouse_callback(GLFWwindow* window, double xpos, double ypos) { - if(firstMouse) + if (firstMouse) { lastX = xpos; lastY = ypos; firstMouse = false; } - GLfloat xoffset = xpos - lastX; - GLfloat yoffset = lastY - ypos; - + float xoffset = xpos - lastX; + float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top + lastX = xpos; lastY = ypos; camera.ProcessMouseMovement(xoffset, yoffset); -} - -#pragma endregion \ No newline at end of file +} \ No newline at end of file