#ifndef FRAMEBUFFER_H #define FRAMEBUFFER_H #include #include "utils/List.h" #include "wrapper/Texture.h" #include "utils/Size.h" template class Framebuffer final { List textures; GLuint buffer; public: template Framebuffer(const TextureFormat& a, Args&&... args) : buffer(0) { const int size = sizeof...(args) + 1; TextureFormat init[size] = {a, args...}; static_assert(N == size, "framebuffer size and amount of arguments do not match"); for(int i = 0; i < N; i++) { textures.add(init[i]); textures[i].setClampWrap(); } } ~Framebuffer() { glDeleteFramebuffers(1, &buffer); } Framebuffer(const Framebuffer&) = delete; Framebuffer(Framebuffer&&) = delete; Framebuffer& operator=(const Framebuffer&) = delete; Framebuffer& operator=(Framebuffer&&) = delete; bool init(const Size& size) { glGenFramebuffers(1, &buffer); glBindFramebuffer(GL_FRAMEBUFFER, buffer); List attachments; for(Texture& t : textures) { t.setData(size.width, size.height); if(t.format.depth) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, t.texture, 0); } else { GLenum c = GL_COLOR_ATTACHMENT0 + attachments.getLength(); glFramebufferTexture2D(GL_FRAMEBUFFER, c, GL_TEXTURE_2D, t.texture, 0); attachments.add(c); } } glDrawBuffers(attachments.getLength(), attachments.begin()); return hasError(); } void bindAndClear() { glBindFramebuffer(GL_FRAMEBUFFER, buffer); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } void bindTextureTo(int index, int textureUnit) const { textures[index].bindTo(textureUnit); } void resize(const Size& size) { for(Texture& t : textures) { t.setData(size.width, size.height); } } private: bool hasError() const { GLenum error = glCheckFramebufferStatus(GL_FRAMEBUFFER); if(error == GL_FRAMEBUFFER_COMPLETE) { return false; } switch(error) { case GL_FRAMEBUFFER_UNDEFINED: std::cout << "undefined framebuffer\n"; return true; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: std::cout << "incomplete framebuffer attachment\n"; return true; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: std::cout << "incomplete missing framebuffer attachment\n"; return true; case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: std::cout << "incomplete framebuffer draw buffer\n"; return true; case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: std::cout << "incomplete framebuffer read buffer\n"; return true; case GL_FRAMEBUFFER_UNSUPPORTED: std::cout << "unsupported framebuffer\n"; return true; case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: std::cout << "incomplete framebuffer multisample\n"; return true; case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: std::cout << "incomplete framebuffer layer targets\n"; return true; } return "unknown error"; } }; #endif