diff --git a/30-anti-aliasing/config.json b/30-anti-aliasing/config.json index 4d9a91f..bcaa8db 100644 --- a/30-anti-aliasing/config.json +++ b/30-anti-aliasing/config.json @@ -11,8 +11,8 @@ "geometry_path": "" }, "screen_shader": { - "vertex_path": "shaders/21-screen.vert.glsl", - "frag_path": "shaders/21-screen.frag.glsl", + "vertex_path": "shaders/30-screen.vert.glsl", + "frag_path": "shaders/30-screen.frag.glsl", "geometry_path": "" }, "skybox_shader": { diff --git a/30-anti-aliasing/shaders/30-screen-bw.frag.glsl b/30-anti-aliasing/shaders/30-screen-bw.frag.glsl new file mode 100644 index 0000000..f5279af --- /dev/null +++ b/30-anti-aliasing/shaders/30-screen-bw.frag.glsl @@ -0,0 +1,13 @@ +#version 330 core +out vec4 FragColor; + +in vec2 TexCoords; + +uniform sampler2D screenTexture; + +void main() +{ + vec3 col = texture(screenTexture, TexCoords).rgb; + float grayscale = 0.2126 * col.r + 0.7152 * col.g + 0.0722 * col.b; + FragColor = vec4(vec3(grayscale), 1.0); +} diff --git a/30-anti-aliasing/shaders/30-screen.frag.glsl b/30-anti-aliasing/shaders/30-screen.frag.glsl new file mode 100644 index 0000000..193eab0 --- /dev/null +++ b/30-anti-aliasing/shaders/30-screen.frag.glsl @@ -0,0 +1,11 @@ +#version 330 core +out vec4 FragColor; + +in vec2 TexCoords; + +uniform sampler2D screenTexture; + +void main() +{ + FragColor = texture(screenTexture, TexCoords); +} diff --git a/30-anti-aliasing/shaders/30-screen.vert.glsl b/30-anti-aliasing/shaders/30-screen.vert.glsl new file mode 100644 index 0000000..19a8fe3 --- /dev/null +++ b/30-anti-aliasing/shaders/30-screen.vert.glsl @@ -0,0 +1,11 @@ +#version 330 core +layout (location = 0) in vec2 aPos; +layout (location = 1) in vec2 aTexCoords; + +out vec2 TexCoords; + +void main() +{ + gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0); + TexCoords = aTexCoords; +} diff --git a/30-anti-aliasing/src/framebuffer.cpp b/30-anti-aliasing/src/framebuffer.cpp index a228ae4..4207ad0 100644 --- a/30-anti-aliasing/src/framebuffer.cpp +++ b/30-anti-aliasing/src/framebuffer.cpp @@ -3,15 +3,33 @@ #include void FrameBuffer::init() { - // target_fb config - glGenFramebuffers(1, &target_fb); - glBindFramebuffer(GL_FRAMEBUFFER, target_fb); - // target_fb configuration // ------------------------- glGenFramebuffers(1, &target_fb); glBindFramebuffer(GL_FRAMEBUFFER, target_fb); + // create the multisamples color attachment texture + glGenTextures(1, &texture_multi); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture_multi); + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB, SCR_WIDTH, SCR_HEIGHT, GL_TRUE); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture_multi, 0); + + // create a renderbuffer object for depth and stencil attachment (we won't be sampling these) + glGenRenderbuffers(1, &target_rbo); + glBindRenderbuffer(GL_RENDERBUFFER, target_rbo); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, SCR_WIDTH, SCR_HEIGHT); // 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, target_rbo); // now actually attach it + // now that we actually created the target_fb and added all attachments we want to check if it is actually complete now + + dbc::check(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Frame buffer not complete."); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // intermediate fbo here + glGenFramebuffers(1, &intermediate_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, intermediate_fbo); + // create a color attachment texture glGenTextures(1, &texture_buffer); glBindTexture(GL_TEXTURE_2D, texture_buffer); @@ -20,13 +38,6 @@ void FrameBuffer::init() { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_buffer, 0); - // create a renderbuffer object for depth and stencil attachment (we won't be sampling these) - glGenRenderbuffers(1, &target_rbo); - glBindRenderbuffer(GL_RENDERBUFFER, target_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, target_rbo); // now actually attach it - // now that we actually created the target_fb and added all attachments we want to check if it is actually complete now - dbc::check(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Frame buffer not complete."); glBindFramebuffer(GL_FRAMEBUFFER, 0); } @@ -42,18 +53,20 @@ void FrameBuffer::begin() { void FrameBuffer::commit() { // disable the frame buffer + glBindFramebuffer(GL_READ_FRAMEBUFFER, target_fb); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, intermediate_fbo); + glBlitFramebuffer(0, 0, SCR_WIDTH, SCR_HEIGHT, 0, 0, SCR_WIDTH, SCR_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_FRAMEBUFFER, 0); } void FrameBuffer::draw(Screen& screen) { - glDisable(GL_DEPTH_TEST); - glClearColor(1.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); + glDisable(GL_DEPTH_TEST); - // render the screen quad screen.shader.use(); glBindVertexArray(screen.target_VAO); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture_buffer); glDrawArrays(GL_TRIANGLES, 0, 6); } diff --git a/30-anti-aliasing/src/framebuffer.hpp b/30-anti-aliasing/src/framebuffer.hpp index 3675e15..10bee23 100644 --- a/30-anti-aliasing/src/framebuffer.hpp +++ b/30-anti-aliasing/src/framebuffer.hpp @@ -5,8 +5,10 @@ struct FrameBuffer { unsigned int target_fb = 0; + unsigned int intermediate_fbo = 0; unsigned int target_rbo = 0; unsigned int texture_buffer = 0; + unsigned int texture_multi = 0; void init(); void begin(); diff --git a/30-anti-aliasing/src/main.cpp b/30-anti-aliasing/src/main.cpp index 21119cf..cb1aaca 100644 --- a/30-anti-aliasing/src/main.cpp +++ b/30-anti-aliasing/src/main.cpp @@ -102,6 +102,7 @@ Scene setup() { glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glEnable(GL_CULL_FACE); + glEnable(GL_MULTISAMPLE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); diff --git a/30-anti-aliasing/src/other_main.cpp b/30-anti-aliasing/src/other_main.cpp deleted file mode 100644 index f959028..0000000 --- a/30-anti-aliasing/src/other_main.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include -#include - -#include "shader.hpp" - -#include - -void framebuffer_size_callback(GLFWwindow* window, int width, int height); - - -int main() -{ - // 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); - -#ifdef __APPLE__ - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); -#endif - - // glfw window creation - // -------------------- - GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL); - if (window == NULL) - { - std::cout << "Failed to create GLFW window" << std::endl; - glfwTerminate(); - return -1; - } - glfwMakeContextCurrent(window); - - // glad: load all OpenGL function pointers - // --------------------------------------- - if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) - { - std::cout << "Failed to initialize GLAD" << std::endl; - return -1; - } - - // configure global opengl state - // ----------------------------- - glEnable(GL_DEPTH_TEST); - - // build and compile shaders - // ------------------------- - Shader shader({ - .vertex_path="10.1.instancing.vs", - .frag_path="10.1.instancing.fs", - .geometry_path=""}); - - // generate a list of 100 quad locations/translation-vectors - // --------------------------------------------------------- - glm::vec2 translations[100]; - int index = 0; - float offset = 0.1f; - for (int y = -10; y < 10; y += 2) - { - for (int x = -10; x < 10; x += 2) - { - glm::vec2 translation; - translation.x = (float)x / 10.0f + offset; - translation.y = (float)y / 10.0f + offset; - translations[index++] = translation; - } - } - - // store instance data in an array buffer - // -------------------------------------- - unsigned int instanceVBO; - glGenBuffers(1, &instanceVBO); - glBindBuffer(GL_ARRAY_BUFFER, instanceVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * 100, &translations[0], GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - // set up vertex data (and buffer(s)) and configure vertex attributes - // ------------------------------------------------------------------ - float quadVertices[] = { - // positions // colors - -0.05f, 0.05f, 1.0f, 0.0f, 0.0f, - 0.05f, -0.05f, 0.0f, 1.0f, 0.0f, - -0.05f, -0.05f, 0.0f, 0.0f, 1.0f, - - -0.05f, 0.05f, 1.0f, 0.0f, 0.0f, - 0.05f, -0.05f, 0.0f, 1.0f, 0.0f, - 0.05f, 0.05f, 0.0f, 1.0f, 1.0f - }; - 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, 5 * sizeof(float), (void*)0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(2 * sizeof(float))); - // also set instance data - glEnableVertexAttribArray(2); - glBindBuffer(GL_ARRAY_BUFFER, instanceVBO); // this attribute comes from a different vertex buffer - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glVertexAttribDivisor(2, 1); // tell OpenGL this is an instanced vertex attribute. - - - // render loop - // ----------- - while (!glfwWindowShouldClose(window)) - { - // render - // ------ - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // draw 100 instanced quads - shader.use(); - glBindVertexArray(quadVAO); - glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 100); // 100 triangles of 6 vertices each - glBindVertexArray(0); - - // 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, &quadVAO); - glDeleteBuffers(1, &quadVBO); - - glfwTerminate(); - return 0; -} - -// glfw: whenever the window size changed (by OS or user resize) this callback function executes -// --------------------------------------------------------------------------------------------- -void framebuffer_size_callback(GLFWwindow* window, int width, int height) -{ - // make sure the viewport matches the new window dimensions; note that width and - // height will be significantly larger than specified on retina displays. - glViewport(0, 0, width, height); -}