diff --git a/include/Utils/Qt/qtSimple.h b/include/Utils/Qt/qtSimple.h index e14d0c8351ff9c346bbf096d5ea651d9e3af45c2..a53e25a4a3601e7ae41c2070ababbbff57f019d4 100644 --- a/include/Utils/Qt/qtSimple.h +++ b/include/Utils/Qt/qtSimple.h @@ -279,10 +279,16 @@ public: bool Alt() const { return m_glWidget->Alt(); } /** - * height of OpenGL widget (for classic yy = H-y + * height of OpenGL widget (for classic yy = H-y) */ int getHeight() const { return m_glWidget->getHeight(); } + /** + * width of OpenGL widget + */ + int getWidth() const { return m_glWidget->getWidth(); } + + /** * console QTextEdit ptr */ diff --git a/include/Utils/Shaders/shaderSimpleTexture.h b/include/Utils/Shaders/shaderSimpleTexture.h index d5af709b1a143148fb1386937e13a18e8904908c..f4d348d49e5473fbd89700db077ba0ad49b385af 100644 --- a/include/Utils/Shaders/shaderSimpleTexture.h +++ b/include/Utils/Shaders/shaderSimpleTexture.h @@ -30,6 +30,7 @@ #include "Utils/GLSLShader.h" #include "Utils/clippingShader.h" #include "Utils/textures.h" +#include "Utils/gl_def.h" namespace CGoGN { @@ -68,9 +69,14 @@ public: void setTexture(Utils::GTexture* tex); /** - * activation of texture unit + * activation of texture unit with set texture */ void activeTexture(); + + /** + * activation of texture unit with texture id + */ + void activeTexture(CGoGNGLuint texId); unsigned int setAttributePosition(VBO* vbo); diff --git a/include/Utils/fbo.h b/include/Utils/fbo.h index 98865b281218ea8bcd2d0b96bf8ab2f79d8ac384..02bb910fda52e9130a3a6d81026d3f9256d74326 100644 --- a/include/Utils/fbo.h +++ b/include/Utils/fbo.h @@ -25,7 +25,9 @@ #ifndef __CGoGN_GLSL_FBO__ #define __CGoGN_GLSL_FBO__ +#include #include "Utils/gl_def.h" +#include "Utils/cgognStream.h" #include #include @@ -36,64 +38,196 @@ namespace CGoGN namespace Utils { +// forward declaration +class GLSLShader; + +/** + * Simple Fbo class to do offscreen rendering in OpenGL. + */ class FBO { -public: - /// default constructor - FBO(); - - /** - * constructor with size of frame buffer - * @param width width in pixel - * @param height heigt in pixel - */ - FBO(unsigned int width, unsigned int height); - - /// destructor - ~FBO(); - - /** - * - */ - void attachRender(GLenum internalformat); - - /** - * - */ - void attachTexture(GLenum internalformat, GLint filter = GL_LINEAR); - - void bindTexInput(); - void bindTexInput(int num); - - void bindTexOutput(); - void bindTexOutput(int num); - void unbind(); - - void setSize(unsigned int width, unsigned int height) - { - m_width = width; - m_height = height; - } +public: - void checkFBO(); + /** + * Constructor. + * \param width Width of the Fbo in pixels + * \param heigth Height of the Fbo in pixels + */ + FBO(unsigned int width, unsigned int height); + + /** + * Destructor. + */ + ~FBO(); + + /** + * Attach a render buffer to the Fbo.\n + * If another render buffer is already attached, it will be deleted and replaced with the new one.\n + * When calling this function, no Fbo should be bound.\n + * \param internalFormat Internal format of the render buffer : GL_DEPTH_COMPONENT, GL_STENCIL_INDEX, or GL_DEPTH_STENCIL + */ +// void attachRenderbuffer(GLenum internalFormat); + + /** + * Attach a color texture to the Fbo.\n + * This function fails if the maximum number of attached color textures is already reached.\n + * When calling this function, no Fbo should be bound.\n + * @param internalFormat Internal format of the texture : GL_RGBA, GL_RGB, GL_RGBA32F, or GL_RGB32F + * @param filter Filter used to minify or magnify the texture (default value is GL_LINEAR) + * @return id of attachement + */ + int createAttachColorTexture(GLenum internalFormat, GLint filter = GL_LINEAR); + + /** + * Attach a color texture to the Fbo.\n + * This function fails if the maximum number of attached color textures is already reached.\n + * When calling this function, no Fbo should be bound.\n + * @param textureId id of texture to attach (default is 0: texture us creatated with internal format) + * @return id of attachement + */ + int attachColorTexture(CGoGNGLuint textureId); + + /** + * Create and attach a depth texture to the Fbo.\n + * This function fails if a depth texture was already attached to the Fbo.\n + * When calling this function, no Fbo should be bound.\n + * @param filter Filter used to minify or magnify the texture (default value is GL_LINEAR) + * @return true if creation & attachment success + */ + bool createAttachDepthTexture(GLint filter = GL_LINEAR); + + /** + * Attach a depth texture to the Fbo.\n + * This function fails if a depth texture was already attached to the Fbo.\n + * When calling this function, no Fbo should be bound.\n + * @param textureId depth texture from another FBO, with getDepthTexId + * @return true if attachment success + */ + bool attachDepthTexture(CGoGNGLuint textureId); + + + /** + * Enable every color attachments of the Fbo.\n + * Useless for Fbos containing only one color attachment.\n + * When calling this function, this Fbo must be bound.\n + */ + void enableAllColorAttachments(); + + /** + * Enable a specific color attachment of the Fbo.\n + * Useless for Fbos containing only one color attachment.\n + * When calling this function, this Fbo must be bound.\n + * \param num Number of the color attachment that should be enabled + */ + void enableColorAttachment(int num); + + /** + * Get an attached color texture id. + * \param att Number of the color texture (the number is equivalent to the color attachment) + * \returns Color texture id + */ + CGoGNGLuint getColorTexId(int att); + + /** + * Get the attached depth texture id. + * \returns Depth texture id + */ + CGoGNGLuint getDepthTexId(); + + /** + * draw full screen attached texture + * @param attach id of attachment + */ + void draw(int attach=0); + + /** + * draw full screen attached texture + * @param attach id of attachment + */ + void drawWithDepth(int attach=0); + + /** + * draw full screen attached texture + * @param attach id of attachment + */ + void drawWithDepth(int attach, CGoGNGLuint depthTexId); + + /** + * + */ + static void draw(Utils::GLSLShader* shader); + + /** + * Bind this Fbo.\n + * When calling this function, no Fbo should be bound.\n + */ + void bind(); + + /** + * Unbind this Fbo.\n + */ + void unbind(); + + /** + * Call glFlush(), unbind this Fbo, call glDrawBuffer(GL_BACK).\n + */ + void safeUnbind(); + + /** + * Check the completeness of this Fbo.\n + * When calling this function, no Fbo should be bound.\n + */ + void checkFBO(); + + /** + * \returns Width of the Fbo in pixels. + */ + unsigned int getWidth() const; + + /** + * \returns Height of the Fbo in pixels. + */ + unsigned int getHeight() const; protected: - unsigned int m_width; - unsigned int m_height; - - int m_maxColorAttachments; - - CGoGNGLuint m_fboID; - CGoGNGLuint m_renderID; - std::vector m_texID; - - - CGoGNGLenumTable m_attachmentPoints; + /// Width (in pixels) of the Fbo. + unsigned int m_width; + + /// Height (in pixels) of the Fbo. + unsigned int m_height; + + /// Maximum number of color attachments. + int m_maxColorAttachments; + + /// Fbo id. + CGoGNGLuint m_fboId; + + /// Render buffer id. + CGoGNGLuint m_renderBufferId; + + /// Color textures ids (up to m_maxColorAttachments color textures). + std::vector m_colorTexId; + + /// Depth textures ids (only one depth texture actually). + std::vector m_depthTexId; + + /// Color attachments of the Fbo. + CGoGNGLenumTable m_colorAttachmentPoints; + + /// Original viewport (x, y, width, height), saved when binding the Fbo, restored when unbinding it. + GLint m_oldViewport[4]; + + /// Indicates wether the Fbo is bound or not. + bool m_bound; + + /// Indicates wether any Fbo is bound or not. + static bool sm_anyFboBound; }; -} -} +} // namespace Utils + +} // namespace CGoGN #endif /* FRAMEBUFFER_HPP */ diff --git a/include/Utils/gl_def.h b/include/Utils/gl_def.h index 32f09593dc968df2e044ef692260f34fdac55bf0..7735a844ef2a32ac04f36bd21d9156cd56f7c90f 100644 --- a/include/Utils/gl_def.h +++ b/include/Utils/gl_def.h @@ -32,6 +32,8 @@ #include +#include "Utils/cgognStream.h" + namespace CGoGN { @@ -65,6 +67,21 @@ typedef FalsePtr CGoGNGLenumTable; #endif +inline void glCheckErrors() +{ + GLenum glError = glGetError(); + if (glError != GL_NO_ERROR) + CGoGNerr<<"GL error: " << gluErrorString(glError) << CGoGNendl; +} + +inline void glCheckErrors(const std::string& message) +{ + GLenum glError = glGetError(); + if (glError != GL_NO_ERROR) + CGoGNerr<< message <<" : " << gluErrorString(glError) << CGoGNendl; +} + + } diff --git a/src/Utils/Shaders/shaderSimpleTexture.cpp b/src/Utils/Shaders/shaderSimpleTexture.cpp index 8f13da75069fb85056c7707f0707b24f58df7b91..ec501d29f85ca226b01f9bbec0ef87696611fbb5 100644 --- a/src/Utils/Shaders/shaderSimpleTexture.cpp +++ b/src/Utils/Shaders/shaderSimpleTexture.cpp @@ -24,6 +24,7 @@ #ifdef WITH_QT +#include #include "Utils/Shaders/shaderSimpleTexture.h" @@ -69,7 +70,7 @@ ShaderSimpleTexture::ShaderSimpleTexture() loadShadersFromMemory(glxvert.c_str(), glxfrag.c_str()); - *m_unif_unit = glGetUniformLocation(this->program_handler(), "textureUnit"); + m_unif_unit = glGetUniformLocation(this->program_handler(), "textureUnit"); } void ShaderSimpleTexture::setTextureUnit(GLenum texture_unit) @@ -87,11 +88,15 @@ void ShaderSimpleTexture::setTexture(Utils::GTexture* tex) void ShaderSimpleTexture::activeTexture() { - glActiveTexture(GL_TEXTURE0+m_unit); + glActiveTexture(GL_TEXTURE0 + m_unit); m_tex_ptr->bind(); } - +void ShaderSimpleTexture::activeTexture(CGoGNGLuint texId) +{ + glActiveTexture(GL_TEXTURE0 + m_unit); + glBindTexture(GL_TEXTURE_2D, *texId); +} unsigned int ShaderSimpleTexture::setAttributePosition(VBO* vbo) { @@ -107,9 +112,14 @@ unsigned int ShaderSimpleTexture::setAttributeTexCoord(VBO* vbo) void ShaderSimpleTexture::restoreUniformsAttribs() { + m_unif_unit = glGetUniformLocation(this->program_handler(), "textureUnit"); + bindVA_VBO("VertexPosition", m_vboPos); bindVA_VBO("VertexTexCoord", m_vboTexCoord); + + this->bind(); glUniform1iARB(*m_unif_unit,m_unit); + this->unbind(); } } // namespace Utils diff --git a/src/Utils/fbo.cpp b/src/Utils/fbo.cpp index b057b1ede0940f9677df187241a7674549ff5946..4b90668fae79ef6193e627bf8d982f7ae9e3b02b 100644 --- a/src/Utils/fbo.cpp +++ b/src/Utils/fbo.cpp @@ -22,6 +22,7 @@ * * *******************************************************************************/ #include "Utils/fbo.h" +#include "Utils/textureSticker.h" namespace CGoGN { @@ -29,168 +30,462 @@ namespace CGoGN namespace Utils { -FBO::FBO() -{ - glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &m_maxColorAttachments); - *m_attachmentPoints = new GLenum[m_maxColorAttachments]; - - glGenFramebuffers(1, &(*m_fboID)); -} +// Initialize static variables and constants +bool FBO::sm_anyFboBound = false; FBO::FBO(unsigned int width, unsigned int height) + : m_width (width) + , m_height (height) + , m_maxColorAttachments (0) + , m_fboId (CGoGNGLuint(0)) + , m_renderBufferId (CGoGNGLuint(0)) + , m_colorAttachmentPoints (CGoGNGLenumTable(NULL)) + , m_bound (false) { - glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &m_maxColorAttachments); - *m_attachmentPoints = new GLenum[m_maxColorAttachments]; - - glGenFramebuffers(1, &(*m_fboID)); - - m_width = width; - m_height = height; + // Generate Fbo + glGenFramebuffers(1, &(*m_fboId)); + + // Get the maximum number of available color attachments + glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &m_maxColorAttachments); + *m_colorAttachmentPoints = new GLenum[m_maxColorAttachments]; } FBO::~FBO() { - GLuint tex_id; + GLuint textureId; + + for (unsigned int i = 0; i < m_colorTexId.size(); i++) + { + textureId = *(m_colorTexId.at(i)); + if (glIsTexture(textureId)) + glDeleteTextures(1, &textureId); + } + + for (unsigned int i = 0; i < m_depthTexId.size(); i++) + { + textureId = *(m_depthTexId.at(i)); + if (glIsTexture(textureId)) + glDeleteTextures(1, &textureId); + } + + if (glIsRenderbuffer(*m_renderBufferId)) + glDeleteRenderbuffers(1, &(*m_renderBufferId)); + + if (glIsFramebuffer(*m_fboId)) + glDeleteFramebuffers(1, &(*m_fboId)); + + delete[] *m_colorAttachmentPoints; +} - for( unsigned int i = 0; i < m_texID.size(); ++i ) { - tex_id = *(m_texID.at(i)); - glDeleteTextures(1, &tex_id); - } +/* +void FBO::attachRenderbuffer(GLenum internalFormat) +{ + if (sm_anyFboBound) + { + CGoGNerr << "FBO::AttachRenderbuffer : No Fbo should be bound when attaching a render buffer." << CGoGNendl; + return; + } + + GLenum attachment; + GLuint renderBufferId; + + switch (internalFormat) + { + case GL_DEPTH_COMPONENT : + attachment = GL_DEPTH_ATTACHMENT; + break; + + case GL_STENCIL_INDEX : + attachment = GL_STENCIL_ATTACHMENT; + break; + + case GL_DEPTH_STENCIL : + attachment = GL_DEPTH_STENCIL_ATTACHMENT; + break; + + default : + CGoGNerr << "FBO::AttachRenderbuffer : Bad internal format." << CGoGNendl; + return; + break; + } + + // Delete old render buffer if it exists + if (glIsRenderbuffer(*m_renderBufferId)) + glDeleteRenderbuffers(1, &(*m_renderBufferId)); + + // Generate render buffer + glGenRenderbuffers(1, &renderBufferId); + glBindRenderbuffer(GL_RENDERBUFFER, renderBufferId); + glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, m_width, m_height); + + // Attach render buffer to Fbo + glBindFramebuffer(GL_FRAMEBUFFER, *m_fboId); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, renderBufferId); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + *m_renderBufferId = renderBufferId; +} +*/ - glDeleteFramebuffers(1, &(*m_fboID)); - delete[] *m_attachmentPoints; +int FBO::createAttachColorTexture(GLenum internalFormat, GLint filter) +{ + if (sm_anyFboBound) + { + CGoGNerr << "FBO::AttachColorTexture : No Fbo should be bound when attaching a texture." << CGoGNendl; + return -1; + } + + if ((int) m_colorTexId.size() == m_maxColorAttachments) + { + CGoGNerr << "FBO::AttachColorTexture : The maximum number of color textures has been exceeded." << CGoGNendl; + return -1; + } + + GLenum attachment; + GLenum format; + GLenum type; + GLuint textureId; + + attachment = GL_COLOR_ATTACHMENT0 + m_colorTexId.size(); + + switch (internalFormat) + { + // four components + case GL_RGBA : + format = GL_RGBA; + type = GL_FLOAT; + break; + + case GL_RGBA32F : + format = GL_RGBA; + type = GL_FLOAT; + break; + + // three components + case GL_RGB : + format = GL_RGB; + type = GL_FLOAT; + break; + + case GL_RGB32F : + format = GL_RGB; + type = GL_FLOAT; + break; + + // two components + case GL_RG32F: + format = GL_RG; + type = GL_FLOAT; + break; + + case GL_RG: + format = GL_RG; + type = GL_FLOAT; + break; + + // one component + case GL_R32F: + format = GL_RED; + type = GL_FLOAT; + break; + + case GL_RED: + format = GL_RED; + type = GL_FLOAT; + break; + default : + CGoGNerr << "FBO::AttachColorTexture : Specified internal format not handled." << CGoGNendl; + return false; + break; + } + + // Generate texture + glGenTextures(1, &textureId); + glBindTexture(GL_TEXTURE_2D, textureId); + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_width, m_height, 0, format, type, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + // Attach texture to Fbo + glBindFramebuffer(GL_FRAMEBUFFER, *m_fboId); + glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, textureId, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + m_colorTexId.push_back(CGoGNGLuint(textureId)); + unsigned int num = m_colorTexId.size() - 1; + (*m_colorAttachmentPoints)[num] = attachment; + + return int(num); } -void FBO::attachRender(GLenum internalformat) +int FBO::attachColorTexture(CGoGNGLuint textureId) { - GLenum attachment; - GLuint renderID; + if (sm_anyFboBound) + { + CGoGNerr << "FBO::AttachColorTexture : No Fbo should be bound when attaching a texture." << CGoGNendl; + return -1; + } - if( internalformat == GL_DEPTH_COMPONENT ) { - attachment = GL_DEPTH_ATTACHMENT; - } + if ((int) m_colorTexId.size() == m_maxColorAttachments) + { + CGoGNerr << "FBO::AttachColorTexture : The maximum number of color textures has been exceeded." << CGoGNendl; + return -1; + } - else if( internalformat == GL_STENCIL_INDEX ) { - attachment = GL_STENCIL_ATTACHMENT; - } + GLenum attachment; - else if( internalformat == GL_DEPTH_STENCIL ) { - attachment = GL_DEPTH_STENCIL_ATTACHMENT; - } + attachment = GL_COLOR_ATTACHMENT0 + m_colorTexId.size(); - else { - std::cout << "FBO::attachRender : Bad Internal Format" << std::endl; - return; - } + // Attach texture to Fbo + glBindFramebuffer(GL_FRAMEBUFFER, *m_fboId); + glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, *textureId, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); - glGenRenderbuffers(1, &renderID); - glBindFramebuffer(GL_FRAMEBUFFER, *m_fboID); - glBindRenderbuffer(GL_RENDERBUFFER, renderID); - glRenderbufferStorage(GL_RENDERBUFFER, internalformat, m_width, m_height); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, - GL_RENDERBUFFER, renderID); + m_colorTexId.push_back(textureId); + unsigned int num = m_colorTexId.size() - 1; + (*m_colorAttachmentPoints)[num] = attachment; - *m_renderID = renderID; + return int(num); } -void FBO::attachTexture(GLenum internalformat, GLint filter) + +bool FBO::createAttachDepthTexture(GLint filter) { - GLenum attachment; - GLenum format; - GLenum type; - GLuint texID; + if (sm_anyFboBound) + { + CGoGNerr << "FBO::AttachDepthTexture : No Fbo should be bound when attaching a texture." << CGoGNendl; + return false; + } + + if( int(m_depthTexId.size()) == 1 ) + { + std::cout << "FBO::AttachDepthTexture : Only one depth texture can be attached." << std::endl; + return false; + } + + GLenum attachment; + GLenum internalFormat; + GLenum format; + GLenum type; + GLuint textureId; + + attachment = GL_DEPTH_ATTACHMENT; + internalFormat = GL_DEPTH_COMPONENT24; + format = GL_DEPTH_COMPONENT; + type = GL_FLOAT; + + // Generate texture + glGenTextures(1, &textureId); + glBindTexture(GL_TEXTURE_2D, textureId); + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_width, m_height, 0, format, type, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + // Attach texture to Fbo + glBindFramebuffer(GL_FRAMEBUFFER, *m_fboId); + glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, textureId, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + m_depthTexId.push_back(CGoGNGLuint(textureId)); + return true; +} - if( int(m_texID.size()) == m_maxColorAttachments ) { - std::cout << "FBO::attachTexture : The number of texture has been exceeded" << std::endl; - return; - } - attachment = GL_COLOR_ATTACHMENT0 + m_texID.size(); +bool FBO::attachDepthTexture(CGoGNGLuint textureId) +{ + if (sm_anyFboBound) + { + CGoGNerr << "FBO::AttachDepthTexture : No Fbo should be bound when attaching a texture." << CGoGNendl; + return false; + } + + if( int(m_depthTexId.size()) == 1 ) + { + std::cout << "FBO::AttachDepthTexture : Only one depth texture can be attached." << std::endl; + return false; + } + + GLenum attachment = GL_DEPTH_ATTACHMENT; + + // Attach texture to Fbo + glBindFramebuffer(GL_FRAMEBUFFER, *m_fboId); + glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, *textureId, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + m_depthTexId.push_back(textureId); + return true; +} - if( internalformat == GL_RGBA ) { - format = GL_RGBA; - type = GL_FLOAT; - } - if( internalformat == GL_RGB ) { - format = GL_RGB; - type = GL_FLOAT; - } +void FBO::enableAllColorAttachments() +{ + if (!m_bound) + { + CGoGNerr << "FBO::EnableColorAttachments : Fbo must be bound when enabling color attachments." << CGoGNendl; + return; + } - if( internalformat == GL_RGBA32F ) { - format = GL_RGBA; - type = GL_FLOAT; - } + glDrawBuffers(m_colorTexId.size(), *m_colorAttachmentPoints); +} - if( internalformat == GL_RGB32F ) { - format = GL_RGB; - type = GL_FLOAT; - } +void FBO::enableColorAttachment(int num) +{ + if (!m_bound) + { + CGoGNerr << "FBO::EnableColorAttachments : Fbo must be bound when enabling color attachments." << CGoGNendl; + return; + } - glGenTextures(1, &texID); - glBindFramebuffer(GL_FRAMEBUFFER, *m_fboID); - glBindTexture(GL_TEXTURE_2D, texID); - glTexImage2D(GL_TEXTURE_2D, 0, internalformat, m_width, - m_height, 0, format, type, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glDrawBuffers(1, &(*m_colorAttachmentPoints)[num]); +} - glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, - GL_TEXTURE_2D, texID, 0); +CGoGNGLuint FBO::getColorTexId(int num) +{ + if ((int) m_colorTexId.size() > num) + return m_colorTexId[num]; + else + return CGoGNGLuint(0); +} - m_texID.push_back(CGoGNGLuint(texID)); - (*m_attachmentPoints)[m_texID.size() - 1] = attachment; +CGoGNGLuint FBO::getDepthTexId() +{ + if ((int) m_depthTexId.size() > 0) + return m_depthTexId[0]; + else + return CGoGNGLuint(0); } -void FBO::bindTexInput() +void FBO::draw(int attach) { - for( unsigned int i = 0; i < m_texID.size(); ++i ) { - glActiveTexture(GL_TEXTURE0 + i); - glBindTexture(GL_TEXTURE_2D, *(m_texID[i])); - } + Utils::TextureSticker::fullScreenTexture(this->getColorTexId(attach)); } -void FBO::bindTexInput(int num) +void FBO::drawWithDepth(int attach) { - glBindTexture(GL_TEXTURE_2D, *(m_texID[num])); + Utils::TextureSticker::fullScreenTextureDepth(this->getColorTexId(attach),this->getDepthTexId()); } -void FBO::bindTexOutput() +void FBO::drawWithDepth(int attach, CGoGNGLuint depthTexId) { - glBindFramebuffer(GL_FRAMEBUFFER, *m_fboID); + Utils::TextureSticker::fullScreenTextureDepth(this->getColorTexId(attach), depthTexId); +} - if( m_texID.size() == 1 ) { - glDrawBuffer((*m_attachmentPoints)[0]); - } - else { - glDrawBuffers(m_texID.size(), *m_attachmentPoints); - } +void FBO::draw(Utils::GLSLShader* shader) +{ + Utils::TextureSticker::fullScreenShader(shader); } -void FBO::bindTexOutput(int num) +void FBO::bind() { - glBindFramebuffer(GL_FRAMEBUFFER, *m_fboID); - glDrawBuffer((*m_attachmentPoints)[num]); + if (m_bound) + { + CGoGNerr << "FBO::Bind : This Fbo is already bound." << CGoGNendl; + return; + } + + if (sm_anyFboBound) + { + CGoGNerr << "FBO::Bind : Only one Fbo can be bound at the same time." << CGoGNendl; + return; + } + + // Bind this Fbo + glBindFramebuffer(GL_FRAMEBUFFER, *m_fboId); + m_bound = true; + sm_anyFboBound = true; + + // Get current viewport + glGetIntegerv(GL_VIEWPORT, m_oldViewport); + + // Set the viewport to the size of the Fbo + glViewport(0, 0, m_width, m_height); } void FBO::unbind() { - glBindFramebuffer(GL_FRAMEBUFFER, 0); + if (m_bound) + { + // Unbind this Fbo + glBindFramebuffer(GL_FRAMEBUFFER, 0); + m_bound = false; + sm_anyFboBound = false; + + // Reset the viewport to the main framebuffer size + glViewport(m_oldViewport[0], m_oldViewport[1], m_oldViewport[2], m_oldViewport[3]); + } } -void FBO::checkFBO() +void FBO::safeUnbind() { - GLenum status; - - glBindFramebuffer(GL_FRAMEBUFFER, *m_fboID); - status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + glFlush(); + unbind(); + glDrawBuffer(GL_BACK); +} - if(status != GL_FRAMEBUFFER_COMPLETE) { - std::cout << "FBO STATUS ERROR : " << status << std::endl; +void FBO::checkFBO() +{ + if (sm_anyFboBound) + { + CGoGNerr << "FBO::CheckFBO : No Fbo should be bound when checking a Fbo's status." << CGoGNendl; + return; + } + + GLenum status; + + // Get Fbo status + glBindFramebuffer(GL_FRAMEBUFFER, *m_fboId); + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + if (status != GL_FRAMEBUFFER_COMPLETE) + std::cout << "Fbo status error : " << status << std::endl; + + switch (status) { + case GL_FRAMEBUFFER_COMPLETE: + break; + case GL_FRAMEBUFFER_UNDEFINED: + std::cout << "GL_FRAMEBUFFER_UNDEFINED" << std::endl; + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + std::cout << "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT" << std::endl; + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + std::cout << "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT" << std::endl; + break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: + std::cout << "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER" << std::endl; + break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: + std::cout << "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER" << std::endl; + break; + case GL_FRAMEBUFFER_UNSUPPORTED: + std::cout << "GL_FRAMEBUFFER_UNSUPPORTED" << std::endl; + break; + case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: + std::cout << "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" << std::endl; + break; + case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: + std::cout << "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS" << std::endl; + break; } } +unsigned int FBO::getWidth() const +{ + return m_width; } + +unsigned int FBO::getHeight() const +{ + return m_height; } +} // namespace Utils + +} // namespace CGoGN +