291 lines
13 KiB
C++
291 lines
13 KiB
C++
|
/***********************************************************************
|
||
|
* Copyright 2011-2012 Computer Graphics Group RWTH Aachen University. *
|
||
|
* All rights reserved. *
|
||
|
* Distributed under the terms of the MIT License (see LICENSE.TXT). *
|
||
|
**********************************************************************/
|
||
|
|
||
|
#ifndef ACGL_OPENGL_OBJECTS_FRAMEBUFFEROBJECT_HH
|
||
|
#define ACGL_OPENGL_OBJECTS_FRAMEBUFFEROBJECT_HH
|
||
|
|
||
|
/**
|
||
|
* This FrameBufferObject class encapsulates an OpenGL frame buffer object (FBO).
|
||
|
* A FrameBufferObject is a target for rendering and thus consists of different "layers":
|
||
|
*
|
||
|
* one or no depthbuffer
|
||
|
* one or no stencilbuffer
|
||
|
* one (OpenGL ES) to many (hardware dependent limit) colorbuffers
|
||
|
*
|
||
|
* These buffers get attached to the FrameBufferObject.
|
||
|
*
|
||
|
* There exists one system-provided frame buffer object for rendering to the screen
|
||
|
* and optionaly multiple user defined frame buffer objects for offscreen rendering.
|
||
|
*
|
||
|
* This class does not encapsulate the system-provided FBO.
|
||
|
*/
|
||
|
|
||
|
#include <ACGL/ACGL.hh>
|
||
|
|
||
|
#include <ACGL/Base/Macros.hh>
|
||
|
#include <ACGL/Utils/StringHelpers.hh>
|
||
|
#include <ACGL/OpenGL/GL.hh>
|
||
|
#include <ACGL/OpenGL/Tools.hh>
|
||
|
#include <ACGL/OpenGL/Objects/RenderBuffer.hh>
|
||
|
#include <ACGL/OpenGL/Objects/Texture.hh>
|
||
|
#include <ACGL/OpenGL/Data/LocationMappings.hh>
|
||
|
|
||
|
#include <vector>
|
||
|
#include <map>
|
||
|
|
||
|
namespace ACGL{
|
||
|
namespace OpenGL{
|
||
|
|
||
|
class FrameBufferObject
|
||
|
{
|
||
|
ACGL_NOT_COPYABLE(FrameBufferObject)
|
||
|
|
||
|
// ==================================================================================================== \/
|
||
|
// ============================================================================================ STRUCTS \/
|
||
|
// ==================================================================================================== \/
|
||
|
public:
|
||
|
//! defines a clear color per color buffer
|
||
|
struct ClearColor {
|
||
|
ClearColor() {
|
||
|
mType = Float;
|
||
|
mColor.floatColor[0] = mColor.floatColor[1] = mColor.floatColor[2] = mColor.floatColor[3] = 0.0f;
|
||
|
}
|
||
|
|
||
|
enum Type { Integer, UnsignedInteger, Float };
|
||
|
union Data {
|
||
|
GLint intColor[4];
|
||
|
GLuint uintColor[4];
|
||
|
GLfloat floatColor[4];
|
||
|
} mColor;
|
||
|
Type mType; // defines which of the data types of the union to use
|
||
|
};
|
||
|
|
||
|
//! An attachment can be a texture or a render buffer
|
||
|
struct Attachment
|
||
|
{
|
||
|
std::string name; // user defined name that matches the fragment shader out
|
||
|
ConstSharedTextureBase texture; // attached color texture, or:
|
||
|
ConstSharedRenderBuffer renderBuffer; // attached renderbuffer - only this or the texture should be set!
|
||
|
GLuint location; // the frag data location that maps to this attachment
|
||
|
Image image; // in case of a texture the image will define which part of the texture to use
|
||
|
ClearColor clearColor; // clear color of the attachement
|
||
|
};
|
||
|
|
||
|
// ===================================================================================================== \/
|
||
|
// ============================================================================================ TYPEDEFS \/
|
||
|
// ===================================================================================================== \/
|
||
|
public:
|
||
|
typedef std::vector< Attachment > AttachmentVec;
|
||
|
|
||
|
// ========================================================================================================= \/
|
||
|
// ============================================================================================ CONSTRUCTORS \/
|
||
|
// ========================================================================================================= \/
|
||
|
public:
|
||
|
FrameBufferObject(void)
|
||
|
: mObjectName(0),
|
||
|
mColorAttachments(),
|
||
|
mDepthAttachment()
|
||
|
{
|
||
|
mObjectName = 0;
|
||
|
glGenFramebuffers(1, &mObjectName);
|
||
|
mDepthAttachment.texture = ConstSharedTextureBase();
|
||
|
mDepthAttachment.renderBuffer = ConstSharedRenderBuffer();
|
||
|
mDepthAttachment.name = ""; // not useful here
|
||
|
mDepthAttachment.location = 0; // not useful here
|
||
|
}
|
||
|
|
||
|
virtual ~FrameBufferObject(void)
|
||
|
{
|
||
|
// buffer 0 will get ignored by OpenGL
|
||
|
glDeleteFramebuffers(1, &mObjectName);
|
||
|
}
|
||
|
|
||
|
// ==================================================================================================== \/
|
||
|
// ============================================================================================ GETTERS \/
|
||
|
// ==================================================================================================== \/
|
||
|
public:
|
||
|
inline GLuint getObjectName (void) const { return mObjectName; }
|
||
|
inline const AttachmentVec& getColorAttachments (void) const { return mColorAttachments; }
|
||
|
inline const Attachment& getDepthAttachment (void) const { return mDepthAttachment; }
|
||
|
|
||
|
// ===================================================================================================== \/
|
||
|
// ============================================================================================ WRAPPERS \/
|
||
|
// ===================================================================================================== \/
|
||
|
public:
|
||
|
int_t getColorAttachmentIndexByName(const std::string& _name) const;
|
||
|
|
||
|
void validate (void) const;
|
||
|
|
||
|
/**
|
||
|
* Per default a FrameBufferObject gets used for read/write operations, but we can
|
||
|
* bind two different FrameBufferObjects for these operations!
|
||
|
*/
|
||
|
inline void bind(GLenum _type = GL_FRAMEBUFFER) const
|
||
|
{
|
||
|
glBindFramebuffer(_type, mObjectName);
|
||
|
}
|
||
|
|
||
|
//! let OpenGL validate the completeness
|
||
|
bool isFrameBufferObjectComplete() const;
|
||
|
|
||
|
/*
|
||
|
* Attach another RenderBuffer as a render target. If the name already exists the old target will get replaced.
|
||
|
*/
|
||
|
inline bool attachColorRenderBuffer(const std::string &_name, const ConstSharedRenderBuffer& _renderBuffer)
|
||
|
{
|
||
|
Attachment a = {_name, SharedTextureBase(), _renderBuffer, 0xFFFFFFFF, Image(), ClearColor()};
|
||
|
return attachColorAttachment( a );
|
||
|
}
|
||
|
|
||
|
inline bool attachColorTexture(const std::string &_name, const ConstSharedTextureBase& _texture, const Image _image = Image() )
|
||
|
{
|
||
|
Attachment a = {_name, _texture, SharedRenderBuffer(), 0xFFFFFFFF, _image, ClearColor()};
|
||
|
return attachColorAttachment( a );
|
||
|
}
|
||
|
|
||
|
inline bool attachColorRenderBuffer(const std::string &_name, const ConstSharedRenderBuffer& _renderBuffer, GLuint _location )
|
||
|
{
|
||
|
Attachment a = {_name, SharedTextureBase(), _renderBuffer, _location, Image(), ClearColor()};
|
||
|
return attachColorAttachment( a );
|
||
|
}
|
||
|
|
||
|
inline bool attachColorTexture(const std::string &_name, const ConstSharedTextureBase& _texture, GLuint _location, const Image _image = Image() )
|
||
|
{
|
||
|
Attachment a = {_name, _texture, SharedRenderBuffer(), _location, _image, ClearColor()};
|
||
|
return attachColorAttachment( a );
|
||
|
}
|
||
|
|
||
|
// if the location within the attachment is larger than the possible number of attachments,
|
||
|
// attachColorAttachment will try to find a non-colliding attachment point.
|
||
|
// this can be used to say "i don't care about the actual attachment number used"
|
||
|
bool attachColorAttachment( const Attachment &_attachment );
|
||
|
|
||
|
void remapAttachments();
|
||
|
|
||
|
inline bool setDepthRenderBuffer(const ConstSharedRenderBuffer& _renderBuffer)
|
||
|
{
|
||
|
bind();
|
||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _renderBuffer->getObjectName() );
|
||
|
#ifdef ACGL_OPENGL_ES
|
||
|
if( _renderBuffer->getInternalFormat() == GL_DEPTH24_STENCIL8_OES ||
|
||
|
_renderBuffer->getInternalFormat() == GL_DEPTH_STENCIL_OES)
|
||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBuffer->getObjectName() );
|
||
|
#else
|
||
|
if( _renderBuffer->getInternalFormat() == GL_DEPTH24_STENCIL8 ||
|
||
|
_renderBuffer->getInternalFormat() == GL_DEPTH_STENCIL)
|
||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBuffer->getObjectName() );
|
||
|
#endif
|
||
|
mDepthAttachment.renderBuffer = _renderBuffer;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//! todo: support mipmap levels
|
||
|
inline bool setDepthTexture(const ConstSharedTextureBase& _texture)
|
||
|
{
|
||
|
bind();
|
||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, _texture->getTarget(), _texture->getObjectName(), 0);
|
||
|
#ifdef ACGL_OPENGL_ES
|
||
|
if( _texture->getInternalFormat() == GL_DEPTH24_STENCIL8_OES ||
|
||
|
_texture->getInternalFormat() == GL_DEPTH_STENCIL_OES)
|
||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, _texture->getTarget(), _texture->getObjectName(), 0);
|
||
|
#else
|
||
|
if( _texture->getInternalFormat() == GL_DEPTH24_STENCIL8 ||
|
||
|
_texture->getInternalFormat() == GL_DEPTH_STENCIL)
|
||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, _texture->getTarget(), _texture->getObjectName(), 0);
|
||
|
#endif
|
||
|
mDepthAttachment.texture = _texture;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//! x,y coordinate is the FBO size in pixels, z coordinate the number of color attachments. x,y are both 0 if the FBO has no useful size
|
||
|
//! todo: support mipmap levels
|
||
|
glm::uvec3 getSize() const
|
||
|
{
|
||
|
glm::uvec3 size;
|
||
|
|
||
|
if (mDepthAttachment.texture) {
|
||
|
// use the size of the depth texture
|
||
|
size = mDepthAttachment.texture->getSize();
|
||
|
} else if (mDepthAttachment.renderBuffer) {
|
||
|
// use the size of the depth render buffer
|
||
|
size = glm::uvec3( mDepthAttachment.renderBuffer->getSize(), 0 );
|
||
|
} else if ( mColorAttachments.size() > 0 ) {
|
||
|
if (mColorAttachments[0].texture) {
|
||
|
// use the size of the first texture:
|
||
|
size = mColorAttachments[0].texture->getSize();
|
||
|
} else if (mColorAttachments[0].renderBuffer) {
|
||
|
// use the size of the first renderBuffer:
|
||
|
size = glm::uvec3( mColorAttachments[0].renderBuffer->getSize(), 0 );
|
||
|
}
|
||
|
} else {
|
||
|
size = glm::uvec3(0);
|
||
|
}
|
||
|
|
||
|
size.z = mColorAttachments.size();
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
// =================================================================================================== \/
|
||
|
// =========================================================================================== METHODS \/
|
||
|
// =================================================================================================== \/
|
||
|
public:
|
||
|
//! sets the attachment locations of this FBO where they match the names specified in _locationMappings
|
||
|
void setAttachmentLocations(ConstSharedLocationMappings _locationMappings);
|
||
|
|
||
|
//! get a list of attachment locations and names that can be used to set up a ShaderProgram
|
||
|
SharedLocationMappings getAttachmentLocations() const;
|
||
|
|
||
|
//! returns the current contents of the default FrameBuffer
|
||
|
//! the format of the returned TextureData will be GL_RGB, the type will be GL_UNSIGNED_INT
|
||
|
//! _readBuffer = GL_INVALID_ENUM will read out the default read buffer
|
||
|
static SharedTextureData getImageData(GLsizei _width, GLsizei _height, GLint _x = 0, GLint _y = 0, GLenum _readBuffer = GL_INVALID_ENUM);
|
||
|
|
||
|
//! get the part of the framebuffer thats part of the current viewport
|
||
|
static SharedTextureData getImageData();
|
||
|
|
||
|
//
|
||
|
// clear buffer functions:
|
||
|
//
|
||
|
|
||
|
//! clear only the depth buffer:
|
||
|
void clearDepthBuffer();
|
||
|
|
||
|
//! clear one specific color buffer:
|
||
|
void clearBuffer( const std::string &_name );
|
||
|
|
||
|
//! clear all buffers, color and depth:
|
||
|
void clearBuffers();
|
||
|
|
||
|
//! sets the clear color for one buffer:
|
||
|
void setClearColor( const std::string &_name, const glm::vec4 &_color );
|
||
|
//! sets the clear color for one buffer:
|
||
|
void setClearColor( const std::string &_name, const glm::ivec4 &_color );
|
||
|
//! sets the clear color for one buffer:
|
||
|
void setClearColor( const std::string &_name, const glm::uvec4 &_color );
|
||
|
|
||
|
//! sets the clear color for all color buffers:
|
||
|
void setClearColor( const glm::vec4 &_color );
|
||
|
//! sets the clear color for all color buffers:
|
||
|
void setClearColor( const glm::ivec4 &_color );
|
||
|
//! sets the clear color for all color buffers:
|
||
|
void setClearColor( const glm::uvec4 &_color );
|
||
|
|
||
|
// =================================================================================================== \/
|
||
|
// ============================================================================================ FIELDS \/
|
||
|
// =================================================================================================== \/
|
||
|
protected:
|
||
|
GLuint mObjectName;
|
||
|
AttachmentVec mColorAttachments;
|
||
|
Attachment mDepthAttachment; // depth and stencil are combined
|
||
|
};
|
||
|
|
||
|
ACGL_SMARTPOINTER_TYPEDEFS(FrameBufferObject)
|
||
|
|
||
|
} // OpenGL
|
||
|
} // ACGL
|
||
|
|
||
|
#endif // ACGL_OPENGL_OBJECTS_FRAMEBUFFEROBJECT_HH
|