final class FrameBufferObject {
private:
GLuint _fboId;
GLuint _depthBuffer;
Texture _tex;
public:
this(Texture tex, bool depthBuffer = false) in {
assert(tex !is null && tex.isValid());
} body {
glCheck(glGenFramebuffersEXT(1, &this._fboId));
if (!this._fboId)
throw new Exception("Failed to create the frame buffer object");
glCheck(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this._fboId));
if (depthBuffer) {
glCheck(glGenRenderbuffersEXT(1, &this._depthBuffer));
if (!this._depthBuffer)
throw new Exception("Failed to create the attached depth buffer");
glCheck(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, this._depthBuffer));
glCheck(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, tex.width, tex.height));
glCheck(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, this._depthBuffer));
}
this.setTexture(tex);
}
~this() {
glCheck(glDeleteRenderbuffersEXT(1, &this._depthBuffer));
glCheck(glDeleteFramebuffers(1, &this._fboId));
}
void setTexture(Texture tex) in {
assert(tex !is null && tex.isValid());
} body {
glCheck(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex.Id, 0));
if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) {
glCheck(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
throw new Exception("Failed to link the target texture to the frame buffer");
}
this._tex = tex;
}
void draw(Drawable draw) in {
assert(draw !is null);
assert(this._tex !is null && this._tex.isValid());
} body {
glPushAttrib(GL_VIEWPORT_BIT | GL_CURRENT_BIT);
glPushMatrix();
scope(exit) {
glPopAttrib();
glPopMatrix();
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, this._tex.width, this._tex.height);
glOrtho(0, this._tex.width, this._tex.height, 0, 1, -1);
draw.render();
}
void bind() const {
writeln("\tBind FBO ", this._fboId);
glCheck(glBindFramebuffer(GL_FRAMEBUFFER, this._fboId));
}
void unbind() const {
glCheck(glBindFramebuffer(GL_FRAMEBUFFER, 0));
}
}