Moved FBO support from osgfbo example into core osg.
This commit is contained in:
parent
77a4cef9d6
commit
d702fed0ef
@ -89,22 +89,6 @@ LINK32=link.exe
|
||||
|
||||
SOURCE=..\..\..\examples\osgfbo\osgfbo.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\examples\osgfbo\FBOExtensions.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\examples\osgfbo\FramebufferAttachment.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\examples\osgfbo\FramebufferObject.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\examples\osgfbo\Renderbuffer.cpp
|
||||
# End Source File
|
||||
# End Target
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
|
@ -236,6 +236,10 @@ SOURCE=..\..\src\osg\FragmentProgram.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\osg\FrameBufferObject.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\src\osg\FrameStamp.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@ -680,6 +684,10 @@ SOURCE=..\..\include\osg\FragmentProgram
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\osg\FrameBufferObject
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\osg\FrameStamp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -1,38 +0,0 @@
|
||||
#include "FBOExtensions.h"
|
||||
#include <osg/GLExtensions>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
#define LOAD_FBO_EXT(name) name = (T##name *)getGLExtensionFuncPtr(#name);
|
||||
|
||||
FBOExtensions::FBOExtensions(unsigned int contextID)
|
||||
: _supported(false)
|
||||
{
|
||||
if (!isGLExtensionSupported(contextID, "GL_EXT_framebuffer_object"))
|
||||
return;
|
||||
|
||||
LOAD_FBO_EXT(glBindRenderbufferEXT);
|
||||
LOAD_FBO_EXT(glGenRenderbuffersEXT);
|
||||
LOAD_FBO_EXT(glRenderbufferStorageEXT);
|
||||
LOAD_FBO_EXT(glBindFramebufferEXT);
|
||||
LOAD_FBO_EXT(glGenFramebuffersEXT);
|
||||
LOAD_FBO_EXT(glCheckFramebufferStatusEXT);
|
||||
LOAD_FBO_EXT(glFramebufferTexture1DEXT);
|
||||
LOAD_FBO_EXT(glFramebufferTexture2DEXT);
|
||||
LOAD_FBO_EXT(glFramebufferTexture3DEXT);
|
||||
LOAD_FBO_EXT(glFramebufferRenderbufferEXT);
|
||||
LOAD_FBO_EXT(glGenerateMipmapEXT);
|
||||
|
||||
_supported =
|
||||
glBindRenderbufferEXT != 0 &&
|
||||
glGenRenderbuffersEXT != 0 &&
|
||||
glRenderbufferStorageEXT != 0 &&
|
||||
glBindFramebufferEXT != 0 &&
|
||||
glGenFramebuffersEXT != 0 &&
|
||||
glCheckFramebufferStatusEXT != 0 &&
|
||||
glFramebufferTexture1DEXT != 0 &&
|
||||
glFramebufferTexture2DEXT != 0 &&
|
||||
glFramebufferTexture3DEXT != 0 &&
|
||||
glFramebufferRenderbufferEXT != 0 &&
|
||||
glGenerateMipmapEXT != 0;
|
||||
}
|
@ -1,118 +0,0 @@
|
||||
#ifndef OSG_FBOEXTENSIONS
|
||||
#define OSG_FBOEXTENSIONS 1
|
||||
|
||||
#include <osg/GL>
|
||||
#include <osg/buffered_value>
|
||||
|
||||
#ifndef GL_EXT_framebuffer_object
|
||||
#define GL_EXT_framebuffer_object 1
|
||||
#define GL_FRAMEBUFFER_EXT 0x8D40
|
||||
#define GL_RENDERBUFFER_EXT 0x8D41
|
||||
#define GL_STENCIL_INDEX_EXT 0x8D45
|
||||
#define GL_STENCIL_INDEX1_EXT 0x8D46
|
||||
#define GL_STENCIL_INDEX4_EXT 0x8D47
|
||||
#define GL_STENCIL_INDEX8_EXT 0x8D48
|
||||
#define GL_STENCIL_INDEX16_EXT 0x8D49
|
||||
#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
|
||||
#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
|
||||
#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
|
||||
#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
|
||||
#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
|
||||
#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
|
||||
#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
|
||||
#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
|
||||
#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
|
||||
#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
|
||||
#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
|
||||
#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
|
||||
#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
|
||||
#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
|
||||
#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
|
||||
#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
|
||||
#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
|
||||
#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
|
||||
#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
|
||||
#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
|
||||
#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
|
||||
#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
|
||||
#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
|
||||
#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
|
||||
#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
|
||||
#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
|
||||
#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
|
||||
#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
|
||||
#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
|
||||
#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
|
||||
#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7
|
||||
#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
|
||||
#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
|
||||
#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
|
||||
#endif
|
||||
|
||||
namespace osg
|
||||
{
|
||||
|
||||
class FBOExtensions
|
||||
{
|
||||
public:
|
||||
typedef void APIENTRY TglBindRenderbufferEXT(GLenum, GLuint);
|
||||
typedef void APIENTRY TglGenRenderbuffersEXT(GLsizei, GLuint *);
|
||||
typedef void APIENTRY TglRenderbufferStorageEXT(GLenum, GLenum, GLsizei, GLsizei);
|
||||
typedef void APIENTRY TglBindFramebufferEXT(GLenum, GLuint);
|
||||
typedef void APIENTRY TglGenFramebuffersEXT(GLsizei, GLuint *);
|
||||
typedef GLenum APIENTRY TglCheckFramebufferStatusEXT(GLenum);
|
||||
typedef void APIENTRY TglFramebufferTexture1DEXT(GLenum, GLenum, GLenum, GLuint, GLint);
|
||||
typedef void APIENTRY TglFramebufferTexture2DEXT(GLenum, GLenum, GLenum, GLuint, GLint);
|
||||
typedef void APIENTRY TglFramebufferTexture3DEXT(GLenum, GLenum, GLenum, GLuint, GLint, GLint);
|
||||
typedef void APIENTRY TglFramebufferRenderbufferEXT(GLenum, GLenum, GLenum, GLuint);
|
||||
typedef void APIENTRY TglGenerateMipmapEXT(GLenum);
|
||||
|
||||
TglBindRenderbufferEXT *glBindRenderbufferEXT;
|
||||
TglGenRenderbuffersEXT *glGenRenderbuffersEXT;
|
||||
TglRenderbufferStorageEXT *glRenderbufferStorageEXT;
|
||||
TglBindFramebufferEXT *glBindFramebufferEXT;
|
||||
TglGenFramebuffersEXT *glGenFramebuffersEXT;
|
||||
TglCheckFramebufferStatusEXT *glCheckFramebufferStatusEXT;
|
||||
TglFramebufferTexture1DEXT *glFramebufferTexture1DEXT;
|
||||
TglFramebufferTexture2DEXT *glFramebufferTexture2DEXT;
|
||||
TglFramebufferTexture3DEXT *glFramebufferTexture3DEXT;
|
||||
TglFramebufferRenderbufferEXT *glFramebufferRenderbufferEXT;
|
||||
TglGenerateMipmapEXT *glGenerateMipmapEXT;
|
||||
|
||||
static FBOExtensions *instance(unsigned contextID)
|
||||
{
|
||||
static buffered_object<FBOExtensions *> _instances;
|
||||
FBOExtensions *ext = _instances[contextID];
|
||||
if (!ext)
|
||||
{
|
||||
ext = new FBOExtensions(contextID);
|
||||
_instances[contextID] = ext;
|
||||
}
|
||||
return ext;
|
||||
}
|
||||
|
||||
bool isSupported() const { return _supported; }
|
||||
|
||||
protected:
|
||||
FBOExtensions(unsigned int contextID);
|
||||
|
||||
private:
|
||||
bool _supported;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,173 +0,0 @@
|
||||
#include "FramebufferAttachment.h"
|
||||
#include "Renderbuffer.h"
|
||||
#include "FBOExtensions.h"
|
||||
#include <osg/Texture1D>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Texture3D>
|
||||
#include <osg/TextureCubeMap>
|
||||
#include <osg/TextureRectangle>
|
||||
#include <osg/State>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
#ifndef GL_TEXTURE_CUBE_MAP_POSITIVE_X
|
||||
#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
|
||||
#endif
|
||||
|
||||
struct FramebufferAttachment::Pimpl
|
||||
{
|
||||
enum TargetType
|
||||
{
|
||||
RENDERBUFFER,
|
||||
TEXTURE1D,
|
||||
TEXTURE2D,
|
||||
TEXTURE3D,
|
||||
TEXTURECUBE,
|
||||
TEXTURERECT
|
||||
};
|
||||
|
||||
TargetType targetType;
|
||||
ref_ptr<Renderbuffer> renderbufferTarget;
|
||||
ref_ptr<Texture> textureTarget;
|
||||
int cubeMapFace;
|
||||
int level;
|
||||
int zoffset;
|
||||
|
||||
explicit Pimpl(TargetType ttype = RENDERBUFFER, int lev = 0)
|
||||
: targetType(ttype),
|
||||
cubeMapFace(0),
|
||||
level(lev),
|
||||
zoffset(0)
|
||||
{
|
||||
}
|
||||
|
||||
Pimpl(const Pimpl ©)
|
||||
: targetType(copy.targetType),
|
||||
renderbufferTarget(copy.renderbufferTarget),
|
||||
textureTarget(copy.textureTarget),
|
||||
cubeMapFace(copy.cubeMapFace),
|
||||
level(copy.level),
|
||||
zoffset(copy.zoffset)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
FramebufferAttachment::FramebufferAttachment()
|
||||
{
|
||||
_ximpl = new Pimpl;
|
||||
}
|
||||
|
||||
FramebufferAttachment::FramebufferAttachment(const FramebufferAttachment ©)
|
||||
{
|
||||
_ximpl = new Pimpl(*copy._ximpl);
|
||||
}
|
||||
|
||||
FramebufferAttachment::FramebufferAttachment(Renderbuffer* target)
|
||||
{
|
||||
_ximpl = new Pimpl(Pimpl::RENDERBUFFER);
|
||||
_ximpl->renderbufferTarget = target;
|
||||
}
|
||||
|
||||
FramebufferAttachment::FramebufferAttachment(Texture1D* target, int level)
|
||||
{
|
||||
_ximpl = new Pimpl(Pimpl::TEXTURE1D, level);
|
||||
_ximpl->textureTarget = target;
|
||||
}
|
||||
|
||||
FramebufferAttachment::FramebufferAttachment(Texture2D* target, int level)
|
||||
{
|
||||
_ximpl = new Pimpl(Pimpl::TEXTURE2D, level);
|
||||
_ximpl->textureTarget = target;
|
||||
}
|
||||
|
||||
FramebufferAttachment::FramebufferAttachment(Texture3D* target, int level, int zoffset)
|
||||
{
|
||||
_ximpl = new Pimpl(Pimpl::TEXTURE3D, level);
|
||||
_ximpl->textureTarget = target;
|
||||
_ximpl->zoffset = zoffset;
|
||||
}
|
||||
|
||||
FramebufferAttachment::FramebufferAttachment(TextureCubeMap* target, int face, int level)
|
||||
{
|
||||
_ximpl = new Pimpl(Pimpl::TEXTURECUBE, level);
|
||||
_ximpl->textureTarget = target;
|
||||
_ximpl->cubeMapFace = face;
|
||||
}
|
||||
|
||||
FramebufferAttachment::FramebufferAttachment(TextureRectangle* target)
|
||||
{
|
||||
_ximpl = new Pimpl(Pimpl::TEXTURERECT);
|
||||
_ximpl->textureTarget = target;
|
||||
}
|
||||
|
||||
FramebufferAttachment::~FramebufferAttachment()
|
||||
{
|
||||
delete _ximpl;
|
||||
}
|
||||
|
||||
FramebufferAttachment &FramebufferAttachment::operator = (const FramebufferAttachment ©)
|
||||
{
|
||||
delete _ximpl;
|
||||
_ximpl = new Pimpl(*copy._ximpl);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void FramebufferAttachment::attach(State &state, GLenum attachment_point, const FBOExtensions* ext) const
|
||||
{
|
||||
unsigned int contextID = state.getContextID();
|
||||
|
||||
// force compile texture if necessary
|
||||
Texture::TextureObject *tobj = 0;
|
||||
if (_ximpl->textureTarget.valid())
|
||||
{
|
||||
tobj = _ximpl->textureTarget->getTextureObject(contextID);
|
||||
if (!tobj || tobj->_id == 0)
|
||||
{
|
||||
_ximpl->textureTarget->compileGLObjects(state);
|
||||
tobj = _ximpl->textureTarget->getTextureObject(contextID);
|
||||
}
|
||||
if (!tobj || tobj->_id == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_ximpl->targetType)
|
||||
{
|
||||
default:
|
||||
case Pimpl::RENDERBUFFER:
|
||||
ext->glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment_point, GL_RENDERBUFFER_EXT, _ximpl->renderbufferTarget->getObjectID(contextID, ext));
|
||||
break;
|
||||
case Pimpl::TEXTURE1D:
|
||||
ext->glFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, attachment_point, GL_TEXTURE_1D, tobj->_id, _ximpl->level);
|
||||
break;
|
||||
case Pimpl::TEXTURE2D:
|
||||
ext->glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment_point, GL_TEXTURE_2D, tobj->_id, _ximpl->level);
|
||||
break;
|
||||
case Pimpl::TEXTURE3D:
|
||||
ext->glFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, attachment_point, GL_TEXTURE_3D, tobj->_id, _ximpl->level, _ximpl->zoffset);
|
||||
break;
|
||||
case Pimpl::TEXTURERECT:
|
||||
ext->glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment_point, GL_TEXTURE_RECTANGLE, tobj->_id, 0);
|
||||
break;
|
||||
case Pimpl::TEXTURECUBE:
|
||||
ext->glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment_point, GL_TEXTURE_CUBE_MAP_POSITIVE_X + _ximpl->cubeMapFace, tobj->_id, _ximpl->level);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int FramebufferAttachment::compare(const FramebufferAttachment &fa) const
|
||||
{
|
||||
if (&fa == this) return 0;
|
||||
if (_ximpl->targetType < fa._ximpl->targetType) return -1;
|
||||
if (_ximpl->targetType > fa._ximpl->targetType) return 1;
|
||||
if (_ximpl->renderbufferTarget.get() < fa._ximpl->renderbufferTarget.get()) return -1;
|
||||
if (_ximpl->renderbufferTarget.get() > fa._ximpl->renderbufferTarget.get()) return 1;
|
||||
if (_ximpl->textureTarget.get() < fa._ximpl->textureTarget.get()) return -1;
|
||||
if (_ximpl->textureTarget.get() > fa._ximpl->textureTarget.get()) return 1;
|
||||
if (_ximpl->cubeMapFace < fa._ximpl->cubeMapFace) return -1;
|
||||
if (_ximpl->cubeMapFace > fa._ximpl->cubeMapFace) return 1;
|
||||
if (_ximpl->level < fa._ximpl->level) return -1;
|
||||
if (_ximpl->level > fa._ximpl->level) return 1;
|
||||
if (_ximpl->zoffset < fa._ximpl->zoffset) return -1;
|
||||
if (_ximpl->zoffset > fa._ximpl->zoffset) return 1;
|
||||
return 0;
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
#ifndef OSG_FRAMEBUFFERATTACHMENT
|
||||
#define OSG_FRAMEBUFFERATTACHMENT 1
|
||||
|
||||
#include <osg/Object>
|
||||
#include <osg/GL>
|
||||
|
||||
namespace osg
|
||||
{
|
||||
|
||||
class FBOExtensions;
|
||||
|
||||
class Renderbuffer;
|
||||
class Texture1D;
|
||||
class Texture2D;
|
||||
class Texture3D;
|
||||
class TextureCubeMap;
|
||||
class TextureRectangle;
|
||||
|
||||
class FramebufferAttachment
|
||||
{
|
||||
public:
|
||||
FramebufferAttachment();
|
||||
FramebufferAttachment(const FramebufferAttachment ©);
|
||||
|
||||
explicit FramebufferAttachment(Renderbuffer* target);
|
||||
explicit FramebufferAttachment(Texture1D* target, int level = 0);
|
||||
explicit FramebufferAttachment(Texture2D* target, int level = 0);
|
||||
explicit FramebufferAttachment(Texture3D* target, int zoffset, int level = 0);
|
||||
explicit FramebufferAttachment(TextureCubeMap* target, int face, int level = 0);
|
||||
explicit FramebufferAttachment(TextureRectangle* target);
|
||||
|
||||
~FramebufferAttachment();
|
||||
|
||||
FramebufferAttachment &operator = (const FramebufferAttachment ©);
|
||||
|
||||
void attach(State &state, GLenum attachment_point, const FBOExtensions* ext) const;
|
||||
int compare(const FramebufferAttachment &fa) const;
|
||||
|
||||
private:
|
||||
// use the Pimpl idiom to avoid dependency from
|
||||
// all Texture* headers
|
||||
struct Pimpl;
|
||||
Pimpl* _ximpl;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,79 +0,0 @@
|
||||
#include "FramebufferObject.h"
|
||||
#include "FBOExtensions.h"
|
||||
#include <osg/State>
|
||||
#include <osg/Notify>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
FramebufferObject::FramebufferObject()
|
||||
: StateAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
FramebufferObject::FramebufferObject(const FramebufferObject ©, const CopyOp ©op)
|
||||
: StateAttribute(copy, copyop),
|
||||
_attachments(copy._attachments)
|
||||
{
|
||||
}
|
||||
|
||||
void FramebufferObject::apply(State &state) const
|
||||
{
|
||||
unsigned int contextID = state.getContextID();
|
||||
|
||||
if (_unsupported[contextID])
|
||||
return;
|
||||
|
||||
FBOExtensions* ext = FBOExtensions::instance(contextID);
|
||||
if (!ext->isSupported())
|
||||
{
|
||||
_unsupported[contextID] = 1;
|
||||
notify(WARN) << "Warning: EXT_framebuffer_object is not supported" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_attachments.empty())
|
||||
{
|
||||
ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
int &dirtyAttachmentList = _dirtyAttachmentList[contextID];
|
||||
|
||||
GLuint &fboID = _fboID[contextID];
|
||||
if (fboID == 0)
|
||||
{
|
||||
ext->glGenFramebuffersEXT(1, &fboID);
|
||||
if (fboID == 0)
|
||||
{
|
||||
notify(WARN) << "Warning: FramebufferObject: could not create the FBO" << std::endl;
|
||||
return;
|
||||
}
|
||||
dirtyAttachmentList = 1;
|
||||
}
|
||||
|
||||
ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
|
||||
|
||||
if (dirtyAttachmentList)
|
||||
{
|
||||
for (AttachmentMap::const_iterator i=_attachments.begin(); i!=_attachments.end(); ++i)
|
||||
{
|
||||
const FramebufferAttachment &fa = i->second;
|
||||
fa.attach(state, i->first, ext);
|
||||
}
|
||||
dirtyAttachmentList = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int FramebufferObject::compare(const StateAttribute &sa) const
|
||||
{
|
||||
COMPARE_StateAttribute_Types(FramebufferObject, sa);
|
||||
COMPARE_StateAttribute_Parameter(_attachments.size());
|
||||
AttachmentMap::const_iterator i = _attachments.begin();
|
||||
AttachmentMap::const_iterator j = rhs._attachments.begin();
|
||||
for (; i!=_attachments.end(); ++i, ++j)
|
||||
{
|
||||
int cmp = i->second.compare(j->second);
|
||||
if (cmp != 0) return cmp;
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
#ifndef OSG_FRAMEBUFFEROBJECT
|
||||
#define OSG_FRAMEBUFFEROBJECT 1
|
||||
|
||||
#include <osg/Texture>
|
||||
#include <osg/buffered_value>
|
||||
|
||||
#include "FramebufferAttachment.h"
|
||||
|
||||
namespace osg
|
||||
{
|
||||
|
||||
class FramebufferObject: public StateAttribute
|
||||
{
|
||||
public:
|
||||
typedef std::map<GLenum, FramebufferAttachment> AttachmentMap;
|
||||
|
||||
FramebufferObject();
|
||||
FramebufferObject(const FramebufferObject ©, const CopyOp ©op = CopyOp::SHALLOW_COPY);
|
||||
|
||||
META_StateAttribute(osg, FramebufferObject, (StateAttribute::Type)0x101010/*FRAMEBUFFEROBJECT*/);
|
||||
|
||||
inline const AttachmentMap &getAttachmentMap() const;
|
||||
inline bool hasAttachment(GLenum attachment_point) const;
|
||||
inline const FramebufferAttachment& getAttachment(GLenum attachment_point) const;
|
||||
inline void setAttachment(GLenum attachment_point, const FramebufferAttachment &attachment);
|
||||
|
||||
int compare(const StateAttribute &sa) const;
|
||||
void apply(State &state) const;
|
||||
|
||||
protected:
|
||||
virtual ~FramebufferObject() {}
|
||||
FramebufferObject &operator=(const FramebufferObject &) { return *this; }
|
||||
|
||||
inline void dirtyAll();
|
||||
|
||||
private:
|
||||
AttachmentMap _attachments;
|
||||
mutable buffered_value<int> _dirtyAttachmentList;
|
||||
mutable buffered_value<int> _unsupported;
|
||||
mutable buffered_value<GLuint> _fboID;
|
||||
};
|
||||
|
||||
// INLINE METHODS
|
||||
|
||||
inline const FramebufferObject::AttachmentMap &FramebufferObject::getAttachmentMap() const
|
||||
{
|
||||
return _attachments;
|
||||
}
|
||||
|
||||
inline bool FramebufferObject::hasAttachment(GLenum attachment_point) const
|
||||
{
|
||||
return _attachments.find(attachment_point) != _attachments.end();
|
||||
}
|
||||
|
||||
inline const FramebufferAttachment &FramebufferObject::getAttachment(GLenum attachment_point) const
|
||||
{
|
||||
return _attachments.find(attachment_point)->second;
|
||||
}
|
||||
|
||||
inline void FramebufferObject::setAttachment(GLenum attachment_point, const FramebufferAttachment &attachment)
|
||||
{
|
||||
_attachments[attachment_point] = attachment;
|
||||
dirtyAll();
|
||||
}
|
||||
|
||||
inline void FramebufferObject::dirtyAll()
|
||||
{
|
||||
_dirtyAttachmentList.setAllElementsTo(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -2,10 +2,6 @@ TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
FBOExtensions.cpp\
|
||||
FramebufferObject.cpp\
|
||||
Renderbuffer.cpp\
|
||||
FramebufferAttachment.cpp\
|
||||
osgfbo.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgText -losgGA -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
@ -1,53 +0,0 @@
|
||||
#include "Renderbuffer.h"
|
||||
#include "FBOExtensions.h"
|
||||
|
||||
using namespace osg;
|
||||
|
||||
Renderbuffer::Renderbuffer()
|
||||
: Object(),
|
||||
_width(512),
|
||||
_height(512),
|
||||
_internalFormat(GL_DEPTH_COMPONENT24)
|
||||
{
|
||||
}
|
||||
|
||||
Renderbuffer::Renderbuffer(int width, int height, GLenum internalFormat)
|
||||
: Object(),
|
||||
_width(width),
|
||||
_height(height),
|
||||
_internalFormat(internalFormat)
|
||||
{
|
||||
}
|
||||
|
||||
Renderbuffer::Renderbuffer(const Renderbuffer ©, const CopyOp ©op)
|
||||
: Object(copy, copyop),
|
||||
_width(copy._width),
|
||||
_height(copy._height),
|
||||
_internalFormat(copy._internalFormat)
|
||||
{
|
||||
}
|
||||
|
||||
GLuint Renderbuffer::getObjectID(unsigned int contextID, const FBOExtensions *ext) const
|
||||
{
|
||||
GLuint &objectID = _objectID[contextID];
|
||||
|
||||
int &dirty = _dirty[contextID];
|
||||
|
||||
if (objectID == 0)
|
||||
{
|
||||
ext->glGenRenderbuffersEXT(1, &objectID);
|
||||
if (objectID == 0)
|
||||
return 0;
|
||||
dirty = 1;
|
||||
}
|
||||
|
||||
if (dirty)
|
||||
{
|
||||
// bind and configure
|
||||
ext->glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, objectID);
|
||||
ext->glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, _internalFormat, _width, _height);
|
||||
dirty = 0;
|
||||
}
|
||||
|
||||
return objectID;
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
#ifndef OSG_RENDERBUFFER
|
||||
#define OSG_RENDERBUFFER 1
|
||||
|
||||
#include <osg/Object>
|
||||
#include <osg/buffered_value>
|
||||
#include <osg/GL>
|
||||
|
||||
#ifndef GL_VERSION_1_4
|
||||
#define GL_DEPTH_COMPONENT16 0x81A5
|
||||
#define GL_DEPTH_COMPONENT24 0x81A6
|
||||
#define GL_DEPTH_COMPONENT32 0x81A7
|
||||
#endif
|
||||
|
||||
namespace osg
|
||||
{
|
||||
|
||||
class FBOExtensions;
|
||||
|
||||
class Renderbuffer: public Object
|
||||
{
|
||||
public:
|
||||
Renderbuffer();
|
||||
Renderbuffer(int width, int height, GLenum internalFormat);
|
||||
Renderbuffer(const Renderbuffer ©, const CopyOp ©op = CopyOp::SHALLOW_COPY);
|
||||
|
||||
META_Object(osg, Renderbuffer);
|
||||
|
||||
inline int getWidth() const;
|
||||
inline int getHeight() const;
|
||||
inline void setWidth(int w);
|
||||
inline void setHeight(int h);
|
||||
inline void setSize(int w, int h);
|
||||
inline GLenum getInternalFormat() const;
|
||||
inline void setInternalFormat(GLenum format);
|
||||
|
||||
GLuint getObjectID(unsigned int contextID, const FBOExtensions *ext) const;
|
||||
inline int compare(const Renderbuffer &rb) const;
|
||||
|
||||
protected:
|
||||
virtual ~Renderbuffer() {}
|
||||
Renderbuffer &operator=(const Renderbuffer &) { return *this; }
|
||||
|
||||
inline void dirtyAll() const;
|
||||
|
||||
private:
|
||||
mutable buffered_value<GLuint> _objectID;
|
||||
mutable buffered_value<int> _dirty;
|
||||
GLenum _internalFormat;
|
||||
int _width;
|
||||
int _height;
|
||||
};
|
||||
|
||||
// INLINE METHODS
|
||||
|
||||
inline int Renderbuffer::getWidth() const
|
||||
{
|
||||
return _width;
|
||||
}
|
||||
|
||||
inline int Renderbuffer::getHeight() const
|
||||
{
|
||||
return _height;
|
||||
}
|
||||
|
||||
inline void Renderbuffer::setWidth(int w)
|
||||
{
|
||||
_width = w;
|
||||
dirtyAll();
|
||||
}
|
||||
|
||||
inline void Renderbuffer::setHeight(int h)
|
||||
{
|
||||
_height = h;
|
||||
dirtyAll();
|
||||
}
|
||||
|
||||
inline void Renderbuffer::setSize(int w, int h)
|
||||
{
|
||||
_width = w;
|
||||
_height = h;
|
||||
dirtyAll();
|
||||
}
|
||||
|
||||
inline GLenum Renderbuffer::getInternalFormat() const
|
||||
{
|
||||
return _internalFormat;
|
||||
}
|
||||
|
||||
inline void Renderbuffer::setInternalFormat(GLenum format)
|
||||
{
|
||||
_internalFormat = format;
|
||||
dirtyAll();
|
||||
}
|
||||
|
||||
inline void Renderbuffer::dirtyAll() const
|
||||
{
|
||||
_dirty.setAllElementsTo(1);
|
||||
}
|
||||
|
||||
inline int Renderbuffer::compare(const Renderbuffer &rb) const
|
||||
{
|
||||
if (&rb == this) return 0;
|
||||
if (_internalFormat < rb._internalFormat) return -1;
|
||||
if (_internalFormat > rb._internalFormat) return 1;
|
||||
if (_width < rb._width) return -1;
|
||||
if (_width > rb._width) return 1;
|
||||
if (_height < rb._height) return -1;
|
||||
if (_height > rb._height) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -10,10 +10,7 @@
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include "FramebufferObject.h"
|
||||
#include "FramebufferAttachment.h"
|
||||
#include "Renderbuffer.h"
|
||||
#include "FBOExtensions.h"
|
||||
#include <osg/FrameBufferObject>
|
||||
|
||||
// This drawable class provides the means for clearing
|
||||
// the color and depth buffer and it is used in this
|
||||
@ -81,11 +78,11 @@ void build_world(osg::Group *root)
|
||||
|
||||
// create and configure a framebuffer object.
|
||||
// We attach the texture to the first color buffer,
|
||||
// and we attach a simple offscreen image (Renderbuffer)
|
||||
// and we attach a simple offscreen image (RenderBuffer)
|
||||
// to the depth buffer in order to allow depth operations
|
||||
osg::ref_ptr<osg::FramebufferObject> fbo = new osg::FramebufferObject();
|
||||
fbo->setAttachment(GL_COLOR_ATTACHMENT0_EXT, osg::FramebufferAttachment(tex.get()));
|
||||
fbo->setAttachment(GL_DEPTH_ATTACHMENT_EXT, osg::FramebufferAttachment(new osg::Renderbuffer(width, height, GL_DEPTH_COMPONENT24)));
|
||||
osg::ref_ptr<osg::FrameBufferObject> fbo = new osg::FrameBufferObject();
|
||||
fbo->setAttachment(GL_COLOR_ATTACHMENT0_EXT, osg::FrameBufferAttachment(tex.get()));
|
||||
fbo->setAttachment(GL_DEPTH_ATTACHMENT_EXT, osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, GL_DEPTH_COMPONENT24)));
|
||||
|
||||
#if 0
|
||||
|
||||
|
@ -245,9 +245,22 @@ class OSG_EXPORT CameraNode : public Transform, public CullSettings
|
||||
|
||||
typedef std::map< BufferComponent, Attachment> BufferAttachmentMap;
|
||||
|
||||
/** Get the BufferAttachmentMap, used to configure frame buffer objects, pbuffers and texture reads.*/
|
||||
BufferAttachmentMap& getBufferAttachmentMap() { return _bufferAttachmentMap; }
|
||||
const BufferAttachmentMap& getBufferAttachmentMap() const { return _bufferAttachmentMap; }
|
||||
|
||||
/** Get the const BufferAttachmentMap, used to configure frame buffer objects, pbuffers and texture reads.*/
|
||||
const BufferAttachmentMap& getBufferAttachmentMap() const { return _bufferAttachmentMap; }
|
||||
|
||||
|
||||
/** Set the Rendering object that is used to implement rendering of the subgraph.*/
|
||||
void setRenderingCache(osg::Object* rc) { _renderingCache = rc; }
|
||||
|
||||
/** Get the Rendering object that is used to implement rendering of the subgraph.*/
|
||||
osg::Object* getRenderingCache() { return _renderingCache.get(); }
|
||||
|
||||
/** Get the const Rendering object that is used to implement rendering of the subgraph.*/
|
||||
const osg::Object* getRenderingCache() const { return _renderingCache.get(); }
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@ -277,6 +290,7 @@ class OSG_EXPORT CameraNode : public Transform, public CullSettings
|
||||
RenderTargetImplementation _renderTargetImplementation;
|
||||
BufferAttachmentMap _bufferAttachmentMap;
|
||||
|
||||
ref_ptr<Object> _renderingCache;
|
||||
};
|
||||
|
||||
}
|
||||
|
325
include/osg/FrameBufferObject
Normal file
325
include/osg/FrameBufferObject
Normal file
@ -0,0 +1,325 @@
|
||||
#ifndef OSG_FRAMEBUFFEROBJECT
|
||||
#define OSG_FRAMEBUFFEROBJECT 1
|
||||
|
||||
#include <osg/GL>
|
||||
#include <osg/Texture>
|
||||
#include <osg/buffered_value>
|
||||
|
||||
#ifndef GL_EXT_framebuffer_object
|
||||
#define GL_EXT_framebuffer_object 1
|
||||
#define GL_FRAMEBUFFER_EXT 0x8D40
|
||||
#define GL_RENDERBUFFER_EXT 0x8D41
|
||||
#define GL_STENCIL_INDEX_EXT 0x8D45
|
||||
#define GL_STENCIL_INDEX1_EXT 0x8D46
|
||||
#define GL_STENCIL_INDEX4_EXT 0x8D47
|
||||
#define GL_STENCIL_INDEX8_EXT 0x8D48
|
||||
#define GL_STENCIL_INDEX16_EXT 0x8D49
|
||||
#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
|
||||
#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
|
||||
#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
|
||||
#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
|
||||
#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
|
||||
#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
|
||||
#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
|
||||
#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
|
||||
#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
|
||||
#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
|
||||
#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
|
||||
#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
|
||||
#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
|
||||
#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
|
||||
#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
|
||||
#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
|
||||
#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
|
||||
#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
|
||||
#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
|
||||
#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
|
||||
#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
|
||||
#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
|
||||
#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
|
||||
#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
|
||||
#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
|
||||
#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
|
||||
#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
|
||||
#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
|
||||
#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
|
||||
#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
|
||||
#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7
|
||||
#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
|
||||
#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
|
||||
#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
|
||||
#endif
|
||||
|
||||
#ifndef GL_VERSION_1_4
|
||||
#define GL_DEPTH_COMPONENT16 0x81A5
|
||||
#define GL_DEPTH_COMPONENT24 0x81A6
|
||||
#define GL_DEPTH_COMPONENT32 0x81A7
|
||||
#endif
|
||||
|
||||
namespace osg
|
||||
{
|
||||
|
||||
/**************************************************************************
|
||||
* FBOExtensions
|
||||
**************************************************************************/
|
||||
|
||||
class FBOExtensions
|
||||
{
|
||||
public:
|
||||
typedef void APIENTRY TglBindRenderbufferEXT(GLenum, GLuint);
|
||||
typedef void APIENTRY TglGenRenderbuffersEXT(GLsizei, GLuint *);
|
||||
typedef void APIENTRY TglRenderbufferStorageEXT(GLenum, GLenum, GLsizei, GLsizei);
|
||||
typedef void APIENTRY TglBindFramebufferEXT(GLenum, GLuint);
|
||||
typedef void APIENTRY TglGenFramebuffersEXT(GLsizei, GLuint *);
|
||||
typedef GLenum APIENTRY TglCheckFramebufferStatusEXT(GLenum);
|
||||
typedef void APIENTRY TglFramebufferTexture1DEXT(GLenum, GLenum, GLenum, GLuint, GLint);
|
||||
typedef void APIENTRY TglFramebufferTexture2DEXT(GLenum, GLenum, GLenum, GLuint, GLint);
|
||||
typedef void APIENTRY TglFramebufferTexture3DEXT(GLenum, GLenum, GLenum, GLuint, GLint, GLint);
|
||||
typedef void APIENTRY TglFramebufferRenderbufferEXT(GLenum, GLenum, GLenum, GLuint);
|
||||
typedef void APIENTRY TglGenerateMipmapEXT(GLenum);
|
||||
|
||||
TglBindRenderbufferEXT *glBindRenderbufferEXT;
|
||||
TglGenRenderbuffersEXT *glGenRenderbuffersEXT;
|
||||
TglRenderbufferStorageEXT *glRenderbufferStorageEXT;
|
||||
TglBindFramebufferEXT *glBindFramebufferEXT;
|
||||
TglGenFramebuffersEXT *glGenFramebuffersEXT;
|
||||
TglCheckFramebufferStatusEXT *glCheckFramebufferStatusEXT;
|
||||
TglFramebufferTexture1DEXT *glFramebufferTexture1DEXT;
|
||||
TglFramebufferTexture2DEXT *glFramebufferTexture2DEXT;
|
||||
TglFramebufferTexture3DEXT *glFramebufferTexture3DEXT;
|
||||
TglFramebufferRenderbufferEXT *glFramebufferRenderbufferEXT;
|
||||
TglGenerateMipmapEXT *glGenerateMipmapEXT;
|
||||
|
||||
static FBOExtensions *instance(unsigned contextID)
|
||||
{
|
||||
static buffered_object<FBOExtensions *> _instances;
|
||||
FBOExtensions *ext = _instances[contextID];
|
||||
if (!ext)
|
||||
{
|
||||
ext = new FBOExtensions(contextID);
|
||||
_instances[contextID] = ext;
|
||||
}
|
||||
return ext;
|
||||
}
|
||||
|
||||
bool isSupported() const { return _supported; }
|
||||
|
||||
protected:
|
||||
FBOExtensions(unsigned int contextID);
|
||||
|
||||
private:
|
||||
bool _supported;
|
||||
};
|
||||
|
||||
/**************************************************************************
|
||||
* RenderBuffer
|
||||
**************************************************************************/
|
||||
|
||||
class RenderBuffer: public Object
|
||||
{
|
||||
public:
|
||||
RenderBuffer();
|
||||
RenderBuffer(int width, int height, GLenum internalFormat);
|
||||
RenderBuffer(const RenderBuffer ©, const CopyOp ©op = CopyOp::SHALLOW_COPY);
|
||||
|
||||
META_Object(osg, RenderBuffer);
|
||||
|
||||
inline int getWidth() const;
|
||||
inline int getHeight() const;
|
||||
inline void setWidth(int w);
|
||||
inline void setHeight(int h);
|
||||
inline void setSize(int w, int h);
|
||||
inline GLenum getInternalFormat() const;
|
||||
inline void setInternalFormat(GLenum format);
|
||||
|
||||
GLuint getObjectID(unsigned int contextID, const FBOExtensions *ext) const;
|
||||
inline int compare(const RenderBuffer &rb) const;
|
||||
|
||||
protected:
|
||||
virtual ~RenderBuffer() {}
|
||||
RenderBuffer &operator=(const RenderBuffer &) { return *this; }
|
||||
|
||||
inline void dirtyAll() const;
|
||||
|
||||
private:
|
||||
mutable buffered_value<GLuint> _objectID;
|
||||
mutable buffered_value<int> _dirty;
|
||||
GLenum _internalFormat;
|
||||
int _width;
|
||||
int _height;
|
||||
};
|
||||
|
||||
// INLINE METHODS
|
||||
|
||||
inline int RenderBuffer::getWidth() const
|
||||
{
|
||||
return _width;
|
||||
}
|
||||
|
||||
inline int RenderBuffer::getHeight() const
|
||||
{
|
||||
return _height;
|
||||
}
|
||||
|
||||
inline void RenderBuffer::setWidth(int w)
|
||||
{
|
||||
_width = w;
|
||||
dirtyAll();
|
||||
}
|
||||
|
||||
inline void RenderBuffer::setHeight(int h)
|
||||
{
|
||||
_height = h;
|
||||
dirtyAll();
|
||||
}
|
||||
|
||||
inline void RenderBuffer::setSize(int w, int h)
|
||||
{
|
||||
_width = w;
|
||||
_height = h;
|
||||
dirtyAll();
|
||||
}
|
||||
|
||||
inline GLenum RenderBuffer::getInternalFormat() const
|
||||
{
|
||||
return _internalFormat;
|
||||
}
|
||||
|
||||
inline void RenderBuffer::setInternalFormat(GLenum format)
|
||||
{
|
||||
_internalFormat = format;
|
||||
dirtyAll();
|
||||
}
|
||||
|
||||
inline void RenderBuffer::dirtyAll() const
|
||||
{
|
||||
_dirty.setAllElementsTo(1);
|
||||
}
|
||||
|
||||
inline int RenderBuffer::compare(const RenderBuffer &rb) const
|
||||
{
|
||||
if (&rb == this) return 0;
|
||||
if (_internalFormat < rb._internalFormat) return -1;
|
||||
if (_internalFormat > rb._internalFormat) return 1;
|
||||
if (_width < rb._width) return -1;
|
||||
if (_width > rb._width) return 1;
|
||||
if (_height < rb._height) return -1;
|
||||
if (_height > rb._height) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* FrameBufferAttachement
|
||||
**************************************************************************/
|
||||
class Texture1D;
|
||||
class Texture2D;
|
||||
class Texture3D;
|
||||
class TextureCubeMap;
|
||||
class TextureRectangle;
|
||||
|
||||
class FrameBufferAttachment
|
||||
{
|
||||
public:
|
||||
FrameBufferAttachment();
|
||||
FrameBufferAttachment(const FrameBufferAttachment ©);
|
||||
|
||||
explicit FrameBufferAttachment(RenderBuffer* target);
|
||||
explicit FrameBufferAttachment(Texture1D* target, int level = 0);
|
||||
explicit FrameBufferAttachment(Texture2D* target, int level = 0);
|
||||
explicit FrameBufferAttachment(Texture3D* target, int zoffset, int level = 0);
|
||||
explicit FrameBufferAttachment(TextureCubeMap* target, int face, int level = 0);
|
||||
explicit FrameBufferAttachment(TextureRectangle* target);
|
||||
|
||||
~FrameBufferAttachment();
|
||||
|
||||
FrameBufferAttachment &operator = (const FrameBufferAttachment ©);
|
||||
|
||||
void attach(State &state, GLenum attachment_point, const FBOExtensions* ext) const;
|
||||
int compare(const FrameBufferAttachment &fa) const;
|
||||
|
||||
private:
|
||||
// use the Pimpl idiom to avoid dependency from
|
||||
// all Texture* headers
|
||||
struct Pimpl;
|
||||
Pimpl* _ximpl;
|
||||
};
|
||||
|
||||
/**************************************************************************
|
||||
* FrameBufferObject
|
||||
**************************************************************************/
|
||||
class FrameBufferObject: public StateAttribute
|
||||
{
|
||||
public:
|
||||
typedef std::map<GLenum, FrameBufferAttachment> AttachmentMap;
|
||||
|
||||
FrameBufferObject();
|
||||
FrameBufferObject(const FrameBufferObject ©, const CopyOp ©op = CopyOp::SHALLOW_COPY);
|
||||
|
||||
META_StateAttribute(osg, FrameBufferObject, (StateAttribute::Type)0x101010/*FrameBufferObject*/);
|
||||
|
||||
inline const AttachmentMap &getAttachmentMap() const;
|
||||
inline bool hasAttachment(GLenum attachment_point) const;
|
||||
inline const FrameBufferAttachment& getAttachment(GLenum attachment_point) const;
|
||||
inline void setAttachment(GLenum attachment_point, const FrameBufferAttachment &attachment);
|
||||
|
||||
int compare(const StateAttribute &sa) const;
|
||||
void apply(State &state) const;
|
||||
|
||||
protected:
|
||||
virtual ~FrameBufferObject() {}
|
||||
FrameBufferObject &operator=(const FrameBufferObject &) { return *this; }
|
||||
|
||||
inline void dirtyAll();
|
||||
|
||||
private:
|
||||
AttachmentMap _attachments;
|
||||
mutable buffered_value<int> _dirtyAttachmentList;
|
||||
mutable buffered_value<int> _unsupported;
|
||||
mutable buffered_value<GLuint> _fboID;
|
||||
};
|
||||
|
||||
// INLINE METHODS
|
||||
|
||||
inline const FrameBufferObject::AttachmentMap &FrameBufferObject::getAttachmentMap() const
|
||||
{
|
||||
return _attachments;
|
||||
}
|
||||
|
||||
inline bool FrameBufferObject::hasAttachment(GLenum attachment_point) const
|
||||
{
|
||||
return _attachments.find(attachment_point) != _attachments.end();
|
||||
}
|
||||
|
||||
inline const FrameBufferAttachment &FrameBufferObject::getAttachment(GLenum attachment_point) const
|
||||
{
|
||||
return _attachments.find(attachment_point)->second;
|
||||
}
|
||||
|
||||
inline void FrameBufferObject::setAttachment(GLenum attachment_point, const FrameBufferAttachment &attachment)
|
||||
{
|
||||
_attachments[attachment_point] = attachment;
|
||||
dirtyAll();
|
||||
}
|
||||
|
||||
inline void FrameBufferObject::dirtyAll()
|
||||
{
|
||||
_dirtyAttachmentList.setAllElementsTo(1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
346
src/osg/FrameBufferObject.cpp
Normal file
346
src/osg/FrameBufferObject.cpp
Normal file
@ -0,0 +1,346 @@
|
||||
#include <osg/FrameBufferObject>
|
||||
#include <osg/State>
|
||||
#include <osg/GLExtensions>
|
||||
#include <osg/Texture1D>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Texture3D>
|
||||
#include <osg/TextureCubeMap>
|
||||
#include <osg/TextureRectangle>
|
||||
#include <osg/Notify>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* FBOExtensions
|
||||
**************************************************************************/
|
||||
#define LOAD_FBO_EXT(name) name = (T##name *)getGLExtensionFuncPtr(#name);
|
||||
|
||||
FBOExtensions::FBOExtensions(unsigned int contextID)
|
||||
: _supported(false)
|
||||
{
|
||||
if (!isGLExtensionSupported(contextID, "GL_EXT_framebuffer_object"))
|
||||
return;
|
||||
|
||||
LOAD_FBO_EXT(glBindRenderbufferEXT);
|
||||
LOAD_FBO_EXT(glGenRenderbuffersEXT);
|
||||
LOAD_FBO_EXT(glRenderbufferStorageEXT);
|
||||
LOAD_FBO_EXT(glBindFramebufferEXT);
|
||||
LOAD_FBO_EXT(glGenFramebuffersEXT);
|
||||
LOAD_FBO_EXT(glCheckFramebufferStatusEXT);
|
||||
LOAD_FBO_EXT(glFramebufferTexture1DEXT);
|
||||
LOAD_FBO_EXT(glFramebufferTexture2DEXT);
|
||||
LOAD_FBO_EXT(glFramebufferTexture3DEXT);
|
||||
LOAD_FBO_EXT(glFramebufferRenderbufferEXT);
|
||||
LOAD_FBO_EXT(glGenerateMipmapEXT);
|
||||
|
||||
_supported =
|
||||
glBindRenderbufferEXT != 0 &&
|
||||
glGenRenderbuffersEXT != 0 &&
|
||||
glRenderbufferStorageEXT != 0 &&
|
||||
glBindFramebufferEXT != 0 &&
|
||||
glGenFramebuffersEXT != 0 &&
|
||||
glCheckFramebufferStatusEXT != 0 &&
|
||||
glFramebufferTexture1DEXT != 0 &&
|
||||
glFramebufferTexture2DEXT != 0 &&
|
||||
glFramebufferTexture3DEXT != 0 &&
|
||||
glFramebufferRenderbufferEXT != 0 &&
|
||||
glGenerateMipmapEXT != 0;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* RenderBuffer
|
||||
**************************************************************************/
|
||||
|
||||
RenderBuffer::RenderBuffer()
|
||||
: Object(),
|
||||
_internalFormat(GL_DEPTH_COMPONENT24),
|
||||
_width(512),
|
||||
_height(512)
|
||||
{
|
||||
}
|
||||
|
||||
RenderBuffer::RenderBuffer(int width, int height, GLenum internalFormat)
|
||||
: Object(),
|
||||
_internalFormat(internalFormat),
|
||||
_width(width),
|
||||
_height(height)
|
||||
{
|
||||
}
|
||||
|
||||
RenderBuffer::RenderBuffer(const RenderBuffer ©, const CopyOp ©op)
|
||||
: Object(copy, copyop),
|
||||
_internalFormat(copy._internalFormat),
|
||||
_width(copy._width),
|
||||
_height(copy._height)
|
||||
{
|
||||
}
|
||||
|
||||
GLuint RenderBuffer::getObjectID(unsigned int contextID, const FBOExtensions *ext) const
|
||||
{
|
||||
GLuint &objectID = _objectID[contextID];
|
||||
|
||||
int &dirty = _dirty[contextID];
|
||||
|
||||
if (objectID == 0)
|
||||
{
|
||||
ext->glGenRenderbuffersEXT(1, &objectID);
|
||||
if (objectID == 0)
|
||||
return 0;
|
||||
dirty = 1;
|
||||
}
|
||||
|
||||
if (dirty)
|
||||
{
|
||||
// bind and configure
|
||||
ext->glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, objectID);
|
||||
ext->glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, _internalFormat, _width, _height);
|
||||
dirty = 0;
|
||||
}
|
||||
|
||||
return objectID;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* FrameBufferAttachement
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef GL_TEXTURE_CUBE_MAP_POSITIVE_X
|
||||
#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
|
||||
#endif
|
||||
|
||||
struct FrameBufferAttachment::Pimpl
|
||||
{
|
||||
enum TargetType
|
||||
{
|
||||
RENDERBUFFER,
|
||||
TEXTURE1D,
|
||||
TEXTURE2D,
|
||||
TEXTURE3D,
|
||||
TEXTURECUBE,
|
||||
TEXTURERECT
|
||||
};
|
||||
|
||||
TargetType targetType;
|
||||
ref_ptr<RenderBuffer> renderbufferTarget;
|
||||
ref_ptr<Texture> textureTarget;
|
||||
int cubeMapFace;
|
||||
int level;
|
||||
int zoffset;
|
||||
|
||||
explicit Pimpl(TargetType ttype = RENDERBUFFER, int lev = 0)
|
||||
: targetType(ttype),
|
||||
cubeMapFace(0),
|
||||
level(lev),
|
||||
zoffset(0)
|
||||
{
|
||||
}
|
||||
|
||||
Pimpl(const Pimpl ©)
|
||||
: targetType(copy.targetType),
|
||||
renderbufferTarget(copy.renderbufferTarget),
|
||||
textureTarget(copy.textureTarget),
|
||||
cubeMapFace(copy.cubeMapFace),
|
||||
level(copy.level),
|
||||
zoffset(copy.zoffset)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
FrameBufferAttachment::FrameBufferAttachment()
|
||||
{
|
||||
_ximpl = new Pimpl;
|
||||
}
|
||||
|
||||
FrameBufferAttachment::FrameBufferAttachment(const FrameBufferAttachment ©)
|
||||
{
|
||||
_ximpl = new Pimpl(*copy._ximpl);
|
||||
}
|
||||
|
||||
FrameBufferAttachment::FrameBufferAttachment(RenderBuffer* target)
|
||||
{
|
||||
_ximpl = new Pimpl(Pimpl::RENDERBUFFER);
|
||||
_ximpl->renderbufferTarget = target;
|
||||
}
|
||||
|
||||
FrameBufferAttachment::FrameBufferAttachment(Texture1D* target, int level)
|
||||
{
|
||||
_ximpl = new Pimpl(Pimpl::TEXTURE1D, level);
|
||||
_ximpl->textureTarget = target;
|
||||
}
|
||||
|
||||
FrameBufferAttachment::FrameBufferAttachment(Texture2D* target, int level)
|
||||
{
|
||||
_ximpl = new Pimpl(Pimpl::TEXTURE2D, level);
|
||||
_ximpl->textureTarget = target;
|
||||
}
|
||||
|
||||
FrameBufferAttachment::FrameBufferAttachment(Texture3D* target, int level, int zoffset)
|
||||
{
|
||||
_ximpl = new Pimpl(Pimpl::TEXTURE3D, level);
|
||||
_ximpl->textureTarget = target;
|
||||
_ximpl->zoffset = zoffset;
|
||||
}
|
||||
|
||||
FrameBufferAttachment::FrameBufferAttachment(TextureCubeMap* target, int face, int level)
|
||||
{
|
||||
_ximpl = new Pimpl(Pimpl::TEXTURECUBE, level);
|
||||
_ximpl->textureTarget = target;
|
||||
_ximpl->cubeMapFace = face;
|
||||
}
|
||||
|
||||
FrameBufferAttachment::FrameBufferAttachment(TextureRectangle* target)
|
||||
{
|
||||
_ximpl = new Pimpl(Pimpl::TEXTURERECT);
|
||||
_ximpl->textureTarget = target;
|
||||
}
|
||||
|
||||
FrameBufferAttachment::~FrameBufferAttachment()
|
||||
{
|
||||
delete _ximpl;
|
||||
}
|
||||
|
||||
FrameBufferAttachment &FrameBufferAttachment::operator = (const FrameBufferAttachment ©)
|
||||
{
|
||||
delete _ximpl;
|
||||
_ximpl = new Pimpl(*copy._ximpl);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void FrameBufferAttachment::attach(State &state, GLenum attachment_point, const FBOExtensions* ext) const
|
||||
{
|
||||
unsigned int contextID = state.getContextID();
|
||||
|
||||
// force compile texture if necessary
|
||||
Texture::TextureObject *tobj = 0;
|
||||
if (_ximpl->textureTarget.valid())
|
||||
{
|
||||
tobj = _ximpl->textureTarget->getTextureObject(contextID);
|
||||
if (!tobj || tobj->_id == 0)
|
||||
{
|
||||
_ximpl->textureTarget->compileGLObjects(state);
|
||||
tobj = _ximpl->textureTarget->getTextureObject(contextID);
|
||||
}
|
||||
if (!tobj || tobj->_id == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_ximpl->targetType)
|
||||
{
|
||||
default:
|
||||
case Pimpl::RENDERBUFFER:
|
||||
ext->glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment_point, GL_RENDERBUFFER_EXT, _ximpl->renderbufferTarget->getObjectID(contextID, ext));
|
||||
break;
|
||||
case Pimpl::TEXTURE1D:
|
||||
ext->glFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, attachment_point, GL_TEXTURE_1D, tobj->_id, _ximpl->level);
|
||||
break;
|
||||
case Pimpl::TEXTURE2D:
|
||||
ext->glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment_point, GL_TEXTURE_2D, tobj->_id, _ximpl->level);
|
||||
break;
|
||||
case Pimpl::TEXTURE3D:
|
||||
ext->glFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, attachment_point, GL_TEXTURE_3D, tobj->_id, _ximpl->level, _ximpl->zoffset);
|
||||
break;
|
||||
case Pimpl::TEXTURERECT:
|
||||
ext->glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment_point, GL_TEXTURE_RECTANGLE, tobj->_id, 0);
|
||||
break;
|
||||
case Pimpl::TEXTURECUBE:
|
||||
ext->glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment_point, GL_TEXTURE_CUBE_MAP_POSITIVE_X + _ximpl->cubeMapFace, tobj->_id, _ximpl->level);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int FrameBufferAttachment::compare(const FrameBufferAttachment &fa) const
|
||||
{
|
||||
if (&fa == this) return 0;
|
||||
if (_ximpl->targetType < fa._ximpl->targetType) return -1;
|
||||
if (_ximpl->targetType > fa._ximpl->targetType) return 1;
|
||||
if (_ximpl->renderbufferTarget.get() < fa._ximpl->renderbufferTarget.get()) return -1;
|
||||
if (_ximpl->renderbufferTarget.get() > fa._ximpl->renderbufferTarget.get()) return 1;
|
||||
if (_ximpl->textureTarget.get() < fa._ximpl->textureTarget.get()) return -1;
|
||||
if (_ximpl->textureTarget.get() > fa._ximpl->textureTarget.get()) return 1;
|
||||
if (_ximpl->cubeMapFace < fa._ximpl->cubeMapFace) return -1;
|
||||
if (_ximpl->cubeMapFace > fa._ximpl->cubeMapFace) return 1;
|
||||
if (_ximpl->level < fa._ximpl->level) return -1;
|
||||
if (_ximpl->level > fa._ximpl->level) return 1;
|
||||
if (_ximpl->zoffset < fa._ximpl->zoffset) return -1;
|
||||
if (_ximpl->zoffset > fa._ximpl->zoffset) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* FrameBufferObject
|
||||
**************************************************************************/
|
||||
|
||||
FrameBufferObject::FrameBufferObject()
|
||||
: StateAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
FrameBufferObject::FrameBufferObject(const FrameBufferObject ©, const CopyOp ©op)
|
||||
: StateAttribute(copy, copyop),
|
||||
_attachments(copy._attachments)
|
||||
{
|
||||
}
|
||||
|
||||
void FrameBufferObject::apply(State &state) const
|
||||
{
|
||||
unsigned int contextID = state.getContextID();
|
||||
|
||||
if (_unsupported[contextID])
|
||||
return;
|
||||
|
||||
FBOExtensions* ext = FBOExtensions::instance(contextID);
|
||||
if (!ext->isSupported())
|
||||
{
|
||||
_unsupported[contextID] = 1;
|
||||
notify(WARN) << "Warning: EXT_framebuffer_object is not supported" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_attachments.empty())
|
||||
{
|
||||
ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
int &dirtyAttachmentList = _dirtyAttachmentList[contextID];
|
||||
|
||||
GLuint &fboID = _fboID[contextID];
|
||||
if (fboID == 0)
|
||||
{
|
||||
ext->glGenFramebuffersEXT(1, &fboID);
|
||||
if (fboID == 0)
|
||||
{
|
||||
notify(WARN) << "Warning: FrameBufferObject: could not create the FBO" << std::endl;
|
||||
return;
|
||||
}
|
||||
dirtyAttachmentList = 1;
|
||||
}
|
||||
|
||||
ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
|
||||
|
||||
if (dirtyAttachmentList)
|
||||
{
|
||||
for (AttachmentMap::const_iterator i=_attachments.begin(); i!=_attachments.end(); ++i)
|
||||
{
|
||||
const FrameBufferAttachment &fa = i->second;
|
||||
fa.attach(state, i->first, ext);
|
||||
}
|
||||
dirtyAttachmentList = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int FrameBufferObject::compare(const StateAttribute &sa) const
|
||||
{
|
||||
COMPARE_StateAttribute_Types(FrameBufferObject, sa);
|
||||
COMPARE_StateAttribute_Parameter(_attachments.size());
|
||||
AttachmentMap::const_iterator i = _attachments.begin();
|
||||
AttachmentMap::const_iterator j = rhs._attachments.begin();
|
||||
for (; i!=_attachments.end(); ++i, ++j)
|
||||
{
|
||||
int cmp = i->second.compare(j->second);
|
||||
if (cmp != 0) return cmp;
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -39,6 +39,7 @@ CXXFILES =\
|
||||
Fog.cpp\
|
||||
FragmentProgram.cpp\
|
||||
FrameStamp.cpp\
|
||||
FrameBufferObject.cpp\
|
||||
FrontFace.cpp\
|
||||
Geode.cpp\
|
||||
Geometry.cpp\
|
||||
|
Loading…
Reference in New Issue
Block a user