#include "Framebuffer.h" #include namespace Nuake { FrameBuffer::FrameBuffer(bool hasRenderBuffer, Vector2 size) { m_Textures = std::map>(); m_Size = size; m_HasRenderBuffer = hasRenderBuffer; glGenFramebuffers(1, &m_FramebufferID); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FramebufferID); // Create render buffer and attach to frame buffer. if (m_HasRenderBuffer) { glGenRenderbuffers(1, &m_RenderBuffer); glBindRenderbuffer(GL_RENDERBUFFER, m_RenderBuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_Size.x, m_Size.y); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_RenderBuffer); } else { m_RenderBuffer = -1; } // Unbind glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); } FrameBuffer::~FrameBuffer() { glDeleteFramebuffers(1, &m_FramebufferID); glDeleteRenderbuffers(1, &m_RenderBuffer); } void FrameBuffer::SetTexture(Ref texture, GLenum attachment) { m_Textures[attachment] = texture; // Attach texture to the framebuffer. Bind(); texture->AttachToFramebuffer(attachment); // Set draw buffer with dynamic amount of render target. // Surely, this can be optimized. int size = 0; std::vector keys = std::vector(); for (auto& s : m_Textures) { if (s.first == GL_DEPTH_ATTACHMENT) continue; keys.push_back(s.first); size += 1; } if (size > 0) glDrawBuffers(size, &keys[0]); Unbind(); } void FrameBuffer::Clear() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } void FrameBuffer::Bind() { if (ResizeQueued) UpdateSize(m_Size); glBindFramebuffer(GL_FRAMEBUFFER, m_FramebufferID); glViewport(0, 0, m_Size.x, m_Size.y); } void FrameBuffer::Unbind() { glBindFramebuffer(GL_FRAMEBUFFER, 0); } void FrameBuffer::QueueResize(Vector2 size) { ResizeQueued = true; m_Size = size; } void FrameBuffer::UpdateSize(Vector2 size) { m_Size = size; ResizeQueued = false; // Delete frame buffer and render buffer. glDeleteFramebuffers(1, &m_FramebufferID); if(m_HasRenderBuffer) glDeleteRenderbuffers(1, &m_RenderBuffer); // New FBO and RBO. glGenFramebuffers(1, &m_FramebufferID); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FramebufferID); // Recreate resized texture. for (auto& t : m_Textures) { t.second->Resize(size); SetTexture(t.second, t.first); } // Recreate render buffer // TODO: move out render buffer. if (m_HasRenderBuffer) { glGenRenderbuffers(1, &m_RenderBuffer); glBindRenderbuffer(GL_RENDERBUFFER, m_RenderBuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_Size.x, m_Size.y); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_RenderBuffer); } // Unbind. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); } void FrameBuffer::SetDrawBuffer(GLenum draw) { Bind(); //glReadBuffer(draw); Unbind(); } void FrameBuffer::SetReadBuffer(GLenum read) { Bind(); //glReadBuffer(read); Unbind(); } }