Commit 44b37a75 authored by hybrid's avatar hybrid

Added another texture type for OpenGL, namely the FBODepthRenderbuffer. This...

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
parent b8bb90cc
......@@ -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)
{
......
......@@ -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
......@@ -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
}
......
......@@ -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;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment