diff --git a/21-framebuffers/meson.build b/21-framebuffers/meson.build index 6edf5a7..e5d4f3e 100644 --- a/21-framebuffers/meson.build +++ b/21-framebuffers/meson.build @@ -81,6 +81,8 @@ sources = [ 'src/model.cpp', 'src/scene.cpp', 'src/camera.cpp', + 'src/framebuffer.cpp', + 'src/screen.cpp', ] subdir('tests') diff --git a/21-framebuffers/src/framebuffer.cpp b/21-framebuffers/src/framebuffer.cpp new file mode 100644 index 0000000..a228ae4 --- /dev/null +++ b/21-framebuffers/src/framebuffer.cpp @@ -0,0 +1,59 @@ +#include "framebuffer.hpp" +#include +#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 a color attachment texture + glGenTextures(1, &texture_buffer); + glBindTexture(GL_TEXTURE_2D, texture_buffer); + 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, 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); +} + +void FrameBuffer::begin() { + // target_fb stuff here + glBindFramebuffer(GL_FRAMEBUFFER, target_fb); + glEnable(GL_DEPTH_TEST); + + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +void FrameBuffer::commit() { + // disable the frame buffer + 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); + + // render the screen quad + screen.shader.use(); + glBindVertexArray(screen.target_VAO); + glBindTexture(GL_TEXTURE_2D, texture_buffer); + glDrawArrays(GL_TRIANGLES, 0, 6); +} diff --git a/21-framebuffers/src/framebuffer.hpp b/21-framebuffers/src/framebuffer.hpp new file mode 100644 index 0000000..3675e15 --- /dev/null +++ b/21-framebuffers/src/framebuffer.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "shader.hpp" +#include "screen.hpp" + +struct FrameBuffer { + unsigned int target_fb = 0; + unsigned int target_rbo = 0; + unsigned int texture_buffer = 0; + + void init(); + void begin(); + void commit(); + void draw(Screen& screen); +}; diff --git a/21-framebuffers/src/scene.cpp b/21-framebuffers/src/scene.cpp index f0a825b..b692bd4 100644 --- a/21-framebuffers/src/scene.cpp +++ b/21-framebuffers/src/scene.cpp @@ -40,12 +40,7 @@ void Scene::render(GLFWwindow* window) { // fov, aspect, near plane, far plane projection = glm::perspective(glm::radians(camera.fov), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); - // framebuffer stuff here - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - glEnable(GL_DEPTH_TEST); - - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + framebuffer.begin(); // render the scene shader.use(); @@ -56,18 +51,9 @@ void Scene::render(GLFWwindow* window) { draw_thing(shader, thing); } - // disable the frame buffer - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDisable(GL_DEPTH_TEST); + framebuffer.commit(); - glClearColor(1.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - - // render the screen quad - screen_shader.use(); - glBindVertexArray(quadVAO); - glBindTexture(GL_TEXTURE_2D, textureColorBuffer); - glDrawArrays(GL_TRIANGLES, 0, 6); + framebuffer.draw(screen); } void Scene::cleanup() { diff --git a/21-framebuffers/src/scene.hpp b/21-framebuffers/src/scene.hpp index c636865..ebc9450 100644 --- a/21-framebuffers/src/scene.hpp +++ b/21-framebuffers/src/scene.hpp @@ -11,6 +11,7 @@ #include "model.hpp" #include "camera.hpp" #include "components.hpp" +#include "framebuffer.hpp" #include #include @@ -26,7 +27,8 @@ struct Thing { struct Scene { Shader shader; - Shader screen_shader; + Screen screen; + FrameBuffer framebuffer; std::unordered_map materials; Camera camera; @@ -36,27 +38,10 @@ struct Scene { float deltaTime = 0.0f; float lastFrame = 0.0f; - unsigned int framebuffer = 0; - unsigned int textureColorBuffer = 0; - unsigned int quadVAO = 0; - unsigned int quadVBO = 0; - unsigned int rbo = 0; - - float quadVertices[24] = { - // 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, - - -1.0f, 1.0f, 0.0f, 1.0f, - 1.0f, -1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 1.0f - }; Scene(components::Scene& config): shader{config.shader.vertex_path, config.shader.frag_path}, - screen_shader{config.screen_shader.vertex_path, config.shader.frag_path}, + screen{.shader={config.screen_shader.vertex_path, config.shader.frag_path}}, materials{config.materials}, camera{ .position=config.camera.position, @@ -81,49 +66,12 @@ struct Scene { thing.scale); } - 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(float), (void *)0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); - shader.use(); shader.setInt("texture1", 0); shader.apply_lighting(light); - screen_shader.use(); - screen_shader.setInt("screenTexture", 0); - - // framebuffer config - glGenFramebuffers(1, &framebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - - // framebuffer configuration - // ------------------------- - glGenFramebuffers(1, &framebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - - // create a color attachment texture - 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) - glGenRenderbuffers(1, &rbo); - 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 - - dbc::check(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Frame buffer not complete."); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + framebuffer.init(); + screen.init(); } void update(); diff --git a/21-framebuffers/src/screen.cpp b/21-framebuffers/src/screen.cpp new file mode 100644 index 0000000..cf420ac --- /dev/null +++ b/21-framebuffers/src/screen.cpp @@ -0,0 +1,18 @@ +#include "screen.hpp" +#include +#include + +void Screen::init() { + shader.use(); + shader.setInt("screenTexture", 0); + + glGenVertexArrays(1, &target_VAO); + glGenBuffers(1, &target_VBO); + glBindVertexArray(target_VAO); + glBindBuffer(GL_ARRAY_BUFFER, target_VBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); +} diff --git a/21-framebuffers/src/screen.hpp b/21-framebuffers/src/screen.hpp new file mode 100644 index 0000000..c7a3229 --- /dev/null +++ b/21-framebuffers/src/screen.hpp @@ -0,0 +1,22 @@ +#pragma once +#include "shader.hpp" + +struct Screen { + Shader shader; + unsigned int target_VAO = 0; + unsigned int target_VBO = 0; + + float vertices[24] = { + // 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, + + -1.0f, 1.0f, 0.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f + }; + + void init(); +};