//////////////////////////////////////////////////////////////////////////////// // Copyright (c) 2011, Computer Graphics Group RWTH Aachen University // // All rights reserved. // //////////////////////////////////////////////////////////////////////////////// #ifndef ACGL_RESOURCE_FRAMEBUFFER_HH #define ACGL_RESOURCE_FRAMEBUFFER_HH #include #include #include #include #include #include namespace ACGL{ namespace Resource{ class FrameBuffer { // =================================================================================================== \/ // ============================================================================================ STATIC \/ // =================================================================================================== \/ private: static GLuint msBuffers[8]; // ==================================================================================================== \/ // ============================================================================================ STRUCTS \/ // ==================================================================================================== \/ public: //! An attachment can be a texture or a render buffer struct Attachment { std::string name; SharedTexture texture; SharedRenderBuffer renderBuffer; }; // ===================================================================================================== \/ // ============================================================================================ TYPEDEFS \/ // ===================================================================================================== \/ public: typedef std::vector< Attachment > AttachmentVec; // ========================================================================================================= \/ // ============================================================================================ CONSTRUCTORS \/ // ========================================================================================================= \/ public: FrameBuffer(GLsizei _width, GLsizei _height) : mContext(0), mWidth(_width), mHeight(_height), mDrawBuffers(0), mColorAttachments(), mDepthAttachment() { glGenFramebuffers(1, &mContext); mDepthAttachment.name = ""; mDepthAttachment.texture = SharedTexture(); mDepthAttachment.renderBuffer = SharedRenderBuffer(); } virtual ~FrameBuffer(void) { if(mContext != 0) glDeleteFramebuffers(1, &mContext); } // ==================================================================================================== \/ // ============================================================================================ GETTERS \/ // ==================================================================================================== \/ public: inline GLuint getContext (void) const { return mContext; } inline GLsizei getWidth (void) const { return mWidth; } inline GLsizei getHeight (void) const { return mHeight; } inline GLsizei getDrawBuffers (void) const { return mDrawBuffers; } inline const AttachmentVec& getColorAttachments (void) const { return mColorAttachments; } inline const Attachment& getDepthAttachment (void) const { return mDepthAttachment; } // ===================================================================================================== \/ // ============================================================================================ WRAPPERS \/ // ===================================================================================================== \/ public: inline void bindAsRenderTarget(void) const { glBindFramebuffer(GL_FRAMEBUFFER, mContext); glDrawBuffers(mDrawBuffers, msBuffers); } inline void bind(void) const { glBindFramebuffer(GL_FRAMEBUFFER, mContext); } inline void setDrawBuffers(void) const { glDrawBuffers(mDrawBuffers, msBuffers); } inline void setViewport(void) const { glViewport(0, 0, mWidth, mHeight); } inline bool attachColorRenderBuffer(const SharedRenderBuffer& _renderBuffer) { if(_renderBuffer->getWidth() != mWidth && _renderBuffer->getHeight() != mHeight) { Utils::error() << "Attached render buffer for color has a wrong size!" << std::endl; return false; } glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + mDrawBuffers, GL_RENDERBUFFER, _renderBuffer->getContext()); mDrawBuffers++; Attachment attachment = {"", SharedTexture(), _renderBuffer}; mColorAttachments.push_back(attachment); return true; } inline bool attachColorTexture(const SharedTexture& _texture) { if(_texture->getWidth() != mWidth && _texture->getHeight() != mHeight) { Utils::error() << "Attached texture for color has a wrong size!" << std::endl; return false; } glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + mDrawBuffers, _texture->getTarget(), _texture->getContext(), 0); mDrawBuffers++; Attachment attachment = {"", _texture, SharedRenderBuffer()}; mColorAttachments.push_back(attachment); return true; } inline bool setDepthRenderBuffer(const SharedRenderBuffer& _renderBuffer) { if(_renderBuffer->getWidth() != mWidth && _renderBuffer->getHeight() != mHeight) { Utils::error() << "Attached render buffer for depth has a wrong size!" << std::endl; return false; } glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _renderBuffer->getContext()); #ifdef OPENGL_ES if( _renderBuffer->getInternalFormat() == GL_DEPTH24_STENCIL8_OES || _renderBuffer->getInternalFormat() == GL_DEPTH_STENCIL_OES) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBuffer->getContext()); #else if( _renderBuffer->getInternalFormat() == GL_DEPTH24_STENCIL8 || _renderBuffer->getInternalFormat() == GL_DEPTH_STENCIL) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBuffer->getContext()); #endif mDepthAttachment.renderBuffer = _renderBuffer; return true; } inline bool setDepthTexture(const SharedTexture& _texture) { if(_texture->getWidth() != mWidth && _texture->getHeight() != mHeight) { Utils::error() << "Attached texture for depth has a wrong size!" << std::endl; return false; } glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, _texture->getTarget(), _texture->getContext(), 0); #ifdef OPENGL_ES if( _texture->getInternalFormat() == GL_DEPTH24_STENCIL8_OES || _texture->getInternalFormat() == GL_DEPTH_STENCIL_OES) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, _texture->getTarget(), _texture->getContext(), 0); #else if( _texture->getInternalFormat() == GL_DEPTH24_STENCIL8 || _texture->getInternalFormat() == GL_DEPTH_STENCIL) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, _texture->getTarget(), _texture->getContext(), 0); #endif mDepthAttachment.texture = _texture; return true; } inline bool isFrameBufferComplete(void) { if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { Utils::error() << "Failed to make complete FrameBuffer object: " << (glCheckFramebufferStatus(GL_FRAMEBUFFER)) << std::endl; return false; } return true; } // ==================================================================================================== \/ // ============================================================================================ METHODS \/ // ==================================================================================================== \/ protected: void clean(void); // =================================================================================================== \/ // ============================================================================================ FIELDS \/ // =================================================================================================== \/ protected: GLuint mContext; GLsizei mWidth; GLsizei mHeight; GLsizei mDrawBuffers; AttachmentVec mColorAttachments; Attachment mDepthAttachment; }; } // Resource } // ACGL #endif // ACGL_RESOURCE_FRAMEBUFFER_HH