| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 | #ifndef FRAMEBUFFER_H#define FRAMEBUFFER_H#include <iostream>#include "utils/ArrayList.h"#include "utils/Size.h"#include "wrapper/Texture.h"template<int N>class Framebuffer final {    ArrayList<Texture, N> textures;    GLuint buffer;public:    template<typename... Args>    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();            if(init[i].linear) {                textures[i].setLinearFilter();            }        }    }    ~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);        ArrayList<GLenum, N> 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
 |