/********************************************************************** * * * cgt - CAMP Graphics Toolbox, Copyright (C) 2012-2015 * * Chair for Computer Aided Medical Procedures * * Technische Universitaet Muenchen, Germany. * * * * * * forked from tgt - Tiny Graphics Toolbox, Copyright (C) 2006-2011 * * Visualization and Computer Graphics Group, Department of * * Computer Science, University of Muenster, Germany. * * * * * * This file is part of the cgt library. This library is free * * software; you can redistribute it and/or modify it under the terms * * of the GNU Lesser General Public License version 2.1 as published * * by the Free Software Foundation. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License in the file "LICENSE.txt" along with this library. * * If not, see . * * * **********************************************************************/ #include "cgt/framebufferobject.h" #include "cgt/logmanager.h" #include // memset namespace cgt { const std::string FramebufferObject::loggerCat_("cgt.FramebufferObject"); FramebufferObject::FramebufferObject() : id_(0) , numColorAttachments_(0) { memset(attachments_, 0, sizeof(Texture*) * (CGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS+2)); generateId(); } FramebufferObject::~FramebufferObject() { glDeleteFramebuffers(1, &id_); } void FramebufferObject::activate() { #if CGT_DEBUG if (cgt::getGlInt(GL_FRAMEBUFFER_BINDING) != 0) LWARNING("Binding a new FBO while another FBO is bound. Do you really want to do this?"); #endif glBindFramebuffer(GL_FRAMEBUFFER, id_); LGL_ERROR; } void FramebufferObject::deactivate() { glBindFramebuffer(GL_FRAMEBUFFER, 0); LGL_ERROR; } void FramebufferObject::attachTexture(Texture* texture, GLenum attachment, int mipLevel, int zSlice) { switch(texture->getType()) { case GL_TEXTURE_1D: glFramebufferTexture1D( GL_FRAMEBUFFER, attachment, GL_TEXTURE_1D, texture->getId(), mipLevel ); break; case GL_TEXTURE_3D: glFramebufferTexture3D( GL_FRAMEBUFFER, attachment, GL_TEXTURE_3D, texture->getId(), mipLevel, zSlice ); break; case GL_TEXTURE_2D_ARRAY: glFramebufferTextureLayer( GL_FRAMEBUFFER, attachment, texture->getId(), mipLevel, zSlice ); break; default: //GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE glFramebufferTexture2D( GL_FRAMEBUFFER, attachment, texture->getType(), texture->getId(), mipLevel ); break; } LGL_ERROR; size_t index = decodeAttachment(attachment); attachments_[index] = texture; if (index < CGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS) ++numColorAttachments_; #ifdef CAMPVIS_DEBUG this->isComplete(); #endif } Texture* FramebufferObject::getTextureAtAttachment(GLenum attachment) { return attachments_[decodeAttachment(attachment)]; } void FramebufferObject::detachTexture(GLenum attachment) { size_t index = decodeAttachment(attachment); if (attachments_[index] != 0) { switch (attachments_[index]->getType()) { case GL_TEXTURE_1D: glFramebufferTexture1D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_1D, 0, 0); break; case GL_TEXTURE_2D_ARRAY: glFramebufferTextureLayerEXT(GL_FRAMEBUFFER, attachment, 0, 0, 0); break; case GL_TEXTURE_3D: glFramebufferTexture3D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_3D, 0, 0, 0); break; default: // GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, 0, 0); break; } attachments_[index] = 0; LGL_ERROR; if (index < CGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS) --numColorAttachments_; } else { LWARNING("Trying to detach unknown texture!"); } } void FramebufferObject::detachAll() { for (GLenum i = 0; i < CGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS; ++i) { if (colorAttachments_[i] != 0) detachTexture(GL_COLOR_ATTACHMENT0 + i); } if (depthAttachment_ != 0) detachTexture(GL_DEPTH_ATTACHMENT); if (stencilAttachment_ != 0) detachTexture(GL_STENCIL_ATTACHMENT); numColorAttachments_ = 0; } bool FramebufferObject::isComplete() const { bool complete = false; GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); switch(status) { case GL_FRAMEBUFFER_COMPLETE: complete = true; break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: LERROR("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: LERROR("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"); break; case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: LERROR("GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"); break; case GL_FRAMEBUFFER_UNDEFINED: LERROR("GL_FRAMEBUFFER_UNDEFINED "); break; case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: LERROR("GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER"); break; case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: LERROR("GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER"); break; case GL_FRAMEBUFFER_UNSUPPORTED: LERROR("GL_FRAMEBUFFER_UNSUPPORTED"); break; default: LERROR("Unknown error!"); } return complete; } bool FramebufferObject::isActive() const { return ((getActiveObject() == id_) && (id_ != 0)); } GLuint FramebufferObject::getActiveObject() { GLint fbo; glGetIntegerv (GL_FRAMEBUFFER_BINDING, &fbo); return static_cast(fbo); } GLuint FramebufferObject::generateId() { id_ = 0; glGenFramebuffers(1, &id_); LGL_ERROR; return id_; } Texture* const * FramebufferObject::getAttachments() const { return attachments_; } const Texture* FramebufferObject::getColorAttachment(size_t index /*= 0*/) const { cgtAssert(index < CGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS, "Index out of bounds!"); return attachments_[index]; } const Texture* FramebufferObject::getDepthAttachment() const { return attachments_[CGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS]; } const Texture* FramebufferObject::getStencilAttachment() const { return attachments_[CGT_FRAMEBUFFEROBJECT_MAX_SUPPORTED_COLOR_ATTACHMENTS+1]; } size_t FramebufferObject::getNumColorAttachments() const { return numColorAttachments_; } } // namespace