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-e03cc46cb475master
parent
b8bb90cc30
commit
44b37a7508
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue