diff options
Diffstat (limited to 'src/Framebuffer.cpp')
-rw-r--r-- | src/Framebuffer.cpp | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/src/Framebuffer.cpp b/src/Framebuffer.cpp new file mode 100644 index 0000000..7127a57 --- /dev/null +++ b/src/Framebuffer.cpp @@ -0,0 +1,125 @@ +#include "Framebuffer.hpp" +#include "Shader.hpp" +#include <string> +#include "Utility.hpp" + +GLuint quadVao, quadVbo; +Shader *quadShader = nullptr; + +Framebuffer::Framebuffer(unsigned int width, unsigned int height, bool createDepthStencilBuffer) : width(width), height(height) { + if (quadShader == nullptr) { + float quadVertices[] = { + // 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 + }; + + 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))); + quadShader = new Shader("./shaders/fbo.vs", "./shaders/fbo.fs"); + quadShader->Use(); + glUniform1i(glGetUniformLocation(quadShader->Program, "inputTexture"), 1); + glActiveTexture(GL_TEXTURE1); + glCheckError(); + } + + glGenTextures(1, &texColor); + glBindTexture(GL_TEXTURE_2D, texColor); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, 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); + glCheckError(); + + if (createDepthStencilBuffer) { + glGenRenderbuffers(1, &rboDepthStencil); + glBindRenderbuffer(GL_RENDERBUFFER, rboDepthStencil); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); + } + + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColor, 0); + if(createDepthStencilBuffer) + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rboDepthStencil); + glCheckError(); + + GLenum framebufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (framebufferStatus != GL_FRAMEBUFFER_COMPLETE) + throw std::runtime_error("Failed to initialize framebuffer: " + std::to_string(framebufferStatus)); +} + +Framebuffer::~Framebuffer() { + if (rboDepthStencil) + glDeleteRenderbuffers(1, &rboDepthStencil); + if (texColor) + glDeleteTextures(1, &texColor); + + glDeleteFramebuffers(1, &fbo); +} + +void Framebuffer::Activate() { + glViewport(0, 0, width, height); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); +} + +void Framebuffer::RenderTo(Framebuffer &target) { + glBindFramebuffer(GL_FRAMEBUFFER, target.fbo); + glViewport(0, 0, target.width, target.height); + glBindVertexArray(quadVao); + glUseProgram(quadShader->Program); + glBindTexture(GL_TEXTURE_2D, texColor); + glDrawArrays(GL_TRIANGLES, 0, 6); +} + +void Framebuffer::Resize(unsigned int newWidth, unsigned int newHeight) { + width = newWidth; + height = newHeight; + if (texColor) { + glBindTexture(GL_TEXTURE_2D, texColor); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, newWidth, newHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + } + if (rboDepthStencil) { + glBindRenderbuffer(GL_RENDERBUFFER, rboDepthStencil); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); + } +} + +Framebuffer &Framebuffer::GetDefault() +{ + static char fboDefaultData[sizeof(Framebuffer)]; + static Framebuffer *fboDefault = nullptr; + if (fboDefault == nullptr) { + fboDefault = reinterpret_cast<Framebuffer*>(fboDefaultData); + fboDefault->fbo = 0; + fboDefault->width = 1; + fboDefault->height = 1; + fboDefault->texColor = 0; + fboDefault->rboDepthStencil = 0; + } + return *fboDefault; +} + +void Framebuffer::Clear(bool color, bool depth, bool stencil) +{ + Activate(); + GLbitfield clearBits = 0; + if (color) + clearBits |= GL_COLOR_BUFFER_BIT; + if (depth) + clearBits |= GL_DEPTH_BUFFER_BIT; + if (stencil) + clearBits |= GL_STENCIL_BUFFER_BIT; + glClear(clearBits); +} |