Added another texture type for OpenGL, namely the FBODepthRenderbuffer. This is only used internally for now, and also is still WIP as the current design has some bad smell :-(. However, it should allow for depthbuffer reuse for RTTs once the interface is made public.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@1672 dfc29bdd-3216-0410-991c-e03cc46cb475
master
hybrid 2008-11-03 13:13:28 +00:00
parent b8bb90cc30
commit 44b37a7508
4 changed files with 201 additions and 94 deletions

View File

@ -2570,8 +2570,14 @@ ITexture* COpenGLDriver::addRenderTargetTexture(const core::dimension2d<s32>& si
if (queryFeature(EVDF_FRAMEBUFFER_OBJECT))
{
rtt = new COpenGLFBOTexture(size, name, this);
addTexture(rtt);
rtt->drop();
if (rtt)
{
addTexture(rtt);
ITexture* tex = getDepthTexture(rtt);
if (tex)
static_cast<video::COpenGLFBODepthTexture*>(tex)->attach(rtt);
rtt->drop();
}
}
else
#endif
@ -2624,6 +2630,7 @@ bool COpenGLDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuff
if (texture)
{
// we want to set a new target. so do this.
glViewport(0, 0, texture->getSize().Width, texture->getSize().Height);
RenderTargetTexture = static_cast<COpenGLTexture*>(texture);
RenderTargetTexture->bindRTT();
CurrentRendertargetSize = texture->getSize();
@ -2736,6 +2743,46 @@ IImage* COpenGLDriver::createScreenShot()
}
//! get depth texture for the given render target texture
ITexture* COpenGLDriver::getDepthTexture(ITexture* texture, bool shared)
{
if ((texture->getDriverType() != EDT_OPENGL) || (!texture->isRenderTarget()))
return 0;
COpenGLTexture* tex = static_cast<COpenGLTexture*>(texture);
if (!tex->isFrameBufferObject())
return 0;
if (shared)
{
for (u32 i=0; i<DepthTextures.size(); ++i)
{
if (DepthTextures[i]->getSize()==texture->getSize())
{
DepthTextures[i]->grab();
return DepthTextures[i];
}
}
DepthTextures.push_back(new COpenGLFBODepthTexture(texture->getSize(), "depth1", this));
return DepthTextures.getLast();
}
return (new COpenGLFBODepthTexture(texture->getSize(), "depth1", this));
}
void COpenGLDriver::removeDepthTexture(ITexture* texture)
{
for (u32 i=0; i<DepthTextures.size(); ++i)
{
if (texture==DepthTextures[i])
{
DepthTextures.erase(i);
return;
}
}
}
//! Set/unset a clipping plane.
bool COpenGLDriver::setClipPlane(u32 index, const core::plane3df& plane, bool enable)
{

View File

@ -339,7 +339,10 @@ namespace video
virtual void enableClipPlane(u32 index, bool enable);
//! Returns the graphics card vendor name.
virtual core::stringc getVendorInfo() {return vendorName;};
virtual core::stringc getVendorInfo() {return vendorName;}
ITexture* getDepthTexture(ITexture* texture, bool shared=true);
void removeDepthTexture(ITexture* texture);
private:
@ -390,6 +393,7 @@ namespace video
SMaterial Material, LastMaterial;
COpenGLTexture* RenderTargetTexture;
const ITexture* CurrentTexture[MATERIAL_MAX_TEXTURES];
core::array<ITexture*> DepthTextures;
s32 LastSetLight;
core::array<core::plane3df> UserClipPlane;
core::array<bool> UserClipPlaneEnabled;
@ -421,6 +425,3 @@ namespace video
#endif // _IRR_COMPILE_WITH_OPENGL_
#endif

View File

@ -399,12 +399,6 @@ void COpenGLTexture::regenerateMipMapLevels()
}
bool COpenGLTexture::isFrameBufferObject() const
{
return false;
}
bool COpenGLTexture::isRenderTarget() const
{
return IsRenderTarget;
@ -417,10 +411,15 @@ void COpenGLTexture::setIsRenderTarget(bool isTarget)
}
bool COpenGLTexture::isFrameBufferObject() const
{
return false;
}
//! Bind Render Target Texture
void COpenGLTexture::bindRTT()
{
glViewport(0, 0, getSize().Width, getSize().Height);
}
@ -445,11 +444,8 @@ static bool checkFBOStatus(COpenGLDriver* Driver);
//! RTT ColorFrameBuffer constructor
COpenGLFBOTexture::COpenGLFBOTexture(const core::dimension2d<s32>& size,
const char* name,
COpenGLDriver* driver,
bool useStencil)
: COpenGLTexture(name, driver),
ColorFrameBuffer(0), DepthRenderBuffer(0), StencilRenderBuffer(0),
UseStencil(useStencil)
COpenGLDriver* driver)
: COpenGLTexture(name, driver), ColorFrameBuffer(0), DepthTexture(0)
{
#ifdef _DEBUG
setDebugName("COpenGLTexture_FBO");
@ -462,6 +458,89 @@ COpenGLFBOTexture::COpenGLFBOTexture(const core::dimension2d<s32>& size,
HasMipMaps = false;
IsRenderTarget = true;
#ifdef GL_EXT_framebuffer_object
// generate frame buffer
Driver->extGlGenFramebuffers(1, &ColorFrameBuffer);
Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, ColorFrameBuffer);
// generate color texture
glGenTextures(1, &TextureName);
glBindTexture(GL_TEXTURE_2D, TextureName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, ImageSize.Width,
ImageSize.Height, 0, PixelFormat, PixelType, 0);
// attach color texture to frame buffer
Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D,
TextureName,
0);
#endif
unbindRTT();
}
//! destructor
COpenGLFBOTexture::~COpenGLFBOTexture()
{
if (DepthTexture)
if (DepthTexture->drop())
Driver->removeDepthTexture(DepthTexture);
if (ColorFrameBuffer)
Driver->extGlDeleteFramebuffers(1, &ColorFrameBuffer);
}
bool COpenGLFBOTexture::isFrameBufferObject() const
{
return true;
}
//! Bind Render Target Texture
void COpenGLFBOTexture::bindRTT()
{
#ifdef GL_EXT_framebuffer_object
if (ColorFrameBuffer != 0)
Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, ColorFrameBuffer);
#endif
}
//! Unbind Render Target Texture
void COpenGLFBOTexture::unbindRTT()
{
#ifdef GL_EXT_framebuffer_object
if (ColorFrameBuffer != 0)
Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
#endif
}
/* FBO Depth Textures */
//! RTT DepthBuffer constructor
COpenGLFBODepthTexture::COpenGLFBODepthTexture(
const core::dimension2d<s32>& size,
const char* name,
COpenGLDriver* driver,
bool useStencil)
: COpenGLFBOTexture(size, name, driver), DepthRenderBuffer(0),
StencilRenderBuffer(0), UseStencil(useStencil)
{
#ifdef _DEBUG
setDebugName("COpenGLTextureFBO_Depth");
#endif
ImageSize = size;
InternalFormat = GL_RGBA;
PixelFormat = GL_RGBA;
PixelType = GL_UNSIGNED_BYTE;
HasMipMaps = false;
if (useStencil)
{
glGenTextures(1, &DepthRenderBuffer);
@ -509,28 +588,31 @@ COpenGLFBOTexture::COpenGLFBOTexture(const core::dimension2d<s32>& size,
GL_DEPTH_COMPONENT, ImageSize.Width,
ImageSize.Height);
}
#endif
}
// generate frame buffer
Driver->extGlGenFramebuffers(1, &ColorFrameBuffer);
Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, ColorFrameBuffer);
// generate color texture
glGenTextures(1, &TextureName);
glBindTexture(GL_TEXTURE_2D, TextureName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, ImageSize.Width,
ImageSize.Height, 0, PixelFormat, PixelType, 0);
//! destructor
COpenGLFBODepthTexture::~COpenGLFBODepthTexture()
{
if (DepthRenderBuffer && UseStencil)
glDeleteTextures(1, &DepthRenderBuffer);
else
Driver->extGlDeleteRenderbuffers(1, &DepthRenderBuffer);
if (StencilRenderBuffer && StencilRenderBuffer != DepthRenderBuffer)
glDeleteTextures(1, &StencilRenderBuffer);
}
// attach color texture to frame buffer
Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D,
TextureName,
0);
if (useStencil)
//combine depth texture and rtt
void COpenGLFBODepthTexture::attach(ITexture* renderTex)
{
if (!renderTex)
return;
video::COpenGLFBOTexture* rtt = static_cast<video::COpenGLFBOTexture*>(renderTex);
rtt->bindRTT();
#ifdef GL_EXT_framebuffer_object
if (UseStencil)
{
// attach stencil texture to stencil buffer
Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT,
@ -554,72 +636,25 @@ COpenGLFBOTexture::COpenGLFBOTexture(const core::dimension2d<s32>& size,
GL_RENDERBUFFER_EXT,
DepthRenderBuffer);
}
glGetError();
#endif
rtt->DepthTexture=this;
renderTex->grab();
// check the status
if (!checkFBOStatus(Driver))
{
printf("FBO=%u, Color=%u, Depth=%u, Stencil=%u\n",
ColorFrameBuffer, TextureName, DepthRenderBuffer, StencilRenderBuffer);
if (ColorFrameBuffer)
Driver->extGlDeleteFramebuffers(1, &ColorFrameBuffer);
if (DepthRenderBuffer)
{
if (useStencil)
glDeleteTextures(1, &DepthRenderBuffer);
else
Driver->extGlDeleteRenderbuffers(1, &DepthRenderBuffer);
}
if (StencilRenderBuffer && StencilRenderBuffer != DepthRenderBuffer)
glDeleteTextures(1, &StencilRenderBuffer);
ColorFrameBuffer = 0;
DepthRenderBuffer = 0;
StencilRenderBuffer = 0;
}
Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
#endif
}
//! destructor
COpenGLFBOTexture::~COpenGLFBOTexture()
{
if (ColorFrameBuffer)
Driver->extGlDeleteFramebuffers(1, &ColorFrameBuffer);
if (DepthRenderBuffer && UseStencil)
glDeleteTextures(1, &DepthRenderBuffer);
else
Driver->extGlDeleteRenderbuffers(1, &DepthRenderBuffer);
if (StencilRenderBuffer && StencilRenderBuffer != DepthRenderBuffer)
glDeleteTextures(1, &StencilRenderBuffer);
}
bool COpenGLFBOTexture::isFrameBufferObject() const
{
return true;
os::Printer::log("FBO incomplete");
rtt->unbindRTT();
}
//! Bind Render Target Texture
void COpenGLFBOTexture::bindRTT()
void COpenGLFBODepthTexture::bindRTT()
{
glViewport(0, 0, getSize().Width, getSize().Height);
#ifdef GL_EXT_framebuffer_object
if (ColorFrameBuffer != 0)
Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, ColorFrameBuffer);
#endif
}
//! Unbind Render Target Texture
void COpenGLFBOTexture::unbindRTT()
void COpenGLFBODepthTexture::unbindRTT()
{
#ifdef GL_EXT_framebuffer_object
if (ColorFrameBuffer != 0)
Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
#endif
}

View File

@ -138,7 +138,7 @@ class COpenGLFBOTexture : public COpenGLTexture
public:
//! FrameBufferObject constructor
COpenGLFBOTexture(const core::dimension2d<s32>& size, const char* name, COpenGLDriver* driver=0, bool useStencil=false);
COpenGLFBOTexture(const core::dimension2d<s32>& size, const char* name, COpenGLDriver* driver=0);
//! destructor
virtual ~COpenGLFBOTexture();
@ -152,9 +152,33 @@ public:
//! Unbind RenderTargetTexture
virtual void unbindRTT();
GLuint ColorFrameBuffer; // for FBO path
GLuint DepthRenderBuffer; // for FBO path
GLuint StencilRenderBuffer; // for FBO path
ITexture* DepthTexture;
protected:
GLuint ColorFrameBuffer;
};
//! OpenGL FBO depth texture.
class COpenGLFBODepthTexture : public COpenGLFBOTexture
{
public:
//! FrameBufferObject depth constructor
COpenGLFBODepthTexture(const core::dimension2d<s32>& size, const char* name, COpenGLDriver* driver=0, bool useStencil=false);
//! destructor
virtual ~COpenGLFBODepthTexture();
//! Bind RenderTargetTexture
virtual void bindRTT();
//! Unbind RenderTargetTexture
virtual void unbindRTT();
void attach(ITexture*);
protected:
GLuint DepthRenderBuffer;
GLuint StencilRenderBuffer;
bool UseStencil;
};