138 lines
3.4 KiB
C++
138 lines
3.4 KiB
C++
#include <psemek/gfx/framebuffer.hpp>
|
|
|
|
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(framebuffer && other)
|
|
: id_{other.id_}
|
|
{
|
|
other.id_ = 0;
|
|
}
|
|
|
|
framebuffer & framebuffer::operator = (framebuffer && other)
|
|
{
|
|
if (this == &other) return *this;
|
|
|
|
reset();
|
|
std::swap(id_, other.id_);
|
|
return *this;
|
|
}
|
|
|
|
framebuffer::~framebuffer()
|
|
{
|
|
reset();
|
|
}
|
|
|
|
framebuffer const & framebuffer::null()
|
|
{
|
|
static framebuffer f(nullptr);
|
|
return f;
|
|
}
|
|
|
|
void framebuffer::bind() const
|
|
{
|
|
gl::BindFramebuffer(gl::DRAW_FRAMEBUFFER, id_);
|
|
}
|
|
|
|
void framebuffer::reset()
|
|
{
|
|
if (id_ != 0)
|
|
gl::DeleteFramebuffers(1, &id_);
|
|
id_ = 0;
|
|
}
|
|
|
|
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(texture_2d const & tex)
|
|
{
|
|
bind();
|
|
gl::FramebufferTexture2D(gl::DRAW_FRAMEBUFFER, gl::DEPTH_ATTACHMENT, gl::TEXTURE_2D, tex.id(), 0);
|
|
}
|
|
|
|
void framebuffer::depth(renderbuffer const & rb)
|
|
{
|
|
bind();
|
|
gl::FramebufferRenderbuffer(gl::DRAW_FRAMEBUFFER, gl::DEPTH_ATTACHMENT, gl::RENDERBUFFER, rb.id());
|
|
}
|
|
|
|
void framebuffer::depth_stencil(texture_2d const & tex)
|
|
{
|
|
bind();
|
|
gl::FramebufferTexture2D(gl::DRAW_FRAMEBUFFER, gl::DEPTH_STENCIL_ATTACHMENT, gl::TEXTURE_2D, tex.id(), 0);
|
|
}
|
|
|
|
void framebuffer::depth_stencil(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));
|
|
}
|
|
|
|
framebuffer::framebuffer(std::nullptr_t)
|
|
: id_{0}
|
|
{}
|
|
|
|
}
|