#include namespace psemek::gfx { static std::string framebuffer_status_string(GLenum status) { switch (status) { case gl::FRAMEBUFFER_UNDEFINED: return "GL_FRAMEBUFFER_UNDEFINED"; case gl::FRAMEBUFFER_INCOMPLETE_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; case gl::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; case gl::FRAMEBUFFER_UNSUPPORTED: return "GL_FRAMEBUFFER_UNSUPPORTED"; case gl::FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: return "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"; } return "(unknown)"; } framebuffer::framebuffer() { gl::GenFramebuffers(1, &id_); } framebuffer::framebuffer(GLuint id) : id_(id) {} framebuffer::framebuffer(framebuffer && other) : id_(other.id_) { other.id_ = 0; } framebuffer & framebuffer::operator = (framebuffer && other) { if (this == &other) return *this; gl::DeleteFramebuffers(1, &id_); id_ = other.id_; other.id_ = 0; return *this; } framebuffer::~framebuffer() { gl::DeleteFramebuffers(1, &id_); } framebuffer framebuffer::null() { return framebuffer{0}; } void framebuffer::bind() const { gl::BindFramebuffer(gl::DRAW_FRAMEBUFFER, id_); } void framebuffer::color(texture_1d const & tex, int attachment) { bind(); gl::FramebufferTexture2D(gl::DRAW_FRAMEBUFFER, gl::COLOR_ATTACHMENT0 + attachment, gl::TEXTURE_1D, tex.id(), 0); } void framebuffer::color(texture_2d const & tex, int attachment) { bind(); gl::FramebufferTexture2D(gl::DRAW_FRAMEBUFFER, gl::COLOR_ATTACHMENT0 + attachment, gl::TEXTURE_2D, tex.id(), 0); } void framebuffer::color(texture_3d const & tex, int layer, int attachment) { bind(); gl::FramebufferTexture3D(gl::DRAW_FRAMEBUFFER, gl::COLOR_ATTACHMENT0 + attachment, gl::TEXTURE_3D, tex.id(), 0, layer); } void framebuffer::color(texture_2d_array const & tex, int layer, int attachment) { bind(); gl::FramebufferTextureLayer(gl::DRAW_FRAMEBUFFER, gl::COLOR_ATTACHMENT0 + attachment, tex.id(), 0, layer); } void framebuffer::color(renderbuffer const & rb, int attachment) { bind(); gl::FramebufferRenderbuffer(gl::DRAW_FRAMEBUFFER, gl::COLOR_ATTACHMENT0 + attachment, gl::RENDERBUFFER, rb.id()); } void framebuffer::depth(renderbuffer const & rb) { bind(); gl::FramebufferRenderbuffer(gl::DRAW_FRAMEBUFFER, gl::DEPTH_STENCIL_ATTACHMENT, gl::RENDERBUFFER, rb.id()); } GLenum framebuffer::status() const { bind(); return gl::CheckFramebufferStatus(gl::DRAW_FRAMEBUFFER); } bool framebuffer::complete() const { return status() == gl::FRAMEBUFFER_COMPLETE; } void framebuffer::assert_complete() const { if (auto s = status(); s != gl::FRAMEBUFFER_COMPLETE) throw std::runtime_error("Framebuffer incomplete: " + framebuffer_status_string(s)); } }