Commit 657fad23 authored by nadro's avatar nadro

- Added ability to set custom depth/stencil texture for render targets (currently OpenGL only).

- Added new color formats: ECF_D16, ECF_D32, ECF_D24S8 (currently OpenGL only).


git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@4984 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 46c24d2c
--------------------------
Changes in 1.9 (not yet released)
- Added ability to set custom depth/stencil texture for render targets.
- Added new color formats: ECF_R8, ECF_R8G8, ECF_D16, ECF_D32, ECF_D24S8.
- Can now enable/disable backround drawing for IGUITable.
- Bugfix: Cloning CBillboardSceneNode now copies colors and sizes.
- EditBox works now with numpad on X11
......
......@@ -125,6 +125,12 @@ public:
case ECF_DXT4:
case ECF_DXT5:
return 32;
case ECF_D16:
return 16;
case ECF_D32:
return 32;
case ECF_D24S8:
return 32;
case ECF_R8:
return 8;
case ECF_R8G8:
......@@ -166,6 +172,20 @@ public:
}
}
//! test if the color format is only viable for depth/stencil textures
static bool isDepthFormat(const ECOLOR_FORMAT format)
{
switch(format)
{
case ECF_D16:
case ECF_D32:
case ECF_D24S8:
return true;
default:
return false;
}
}
//! test if the color format is only viable for RenderTarget textures
/** Since we don't have support for e.g. floating point IImage formats
one should test if the color format can be used for arbitrary usage, or
......
......@@ -552,7 +552,7 @@ namespace video
information is multiplied.*/
virtual void makeNormalMapTexture(video::ITexture* texture, f32 amplitude=1.0f) const =0;
//! Sets a new render target.
//! Sets a new render target. (this prototype will be removed in future)
/** This will only work if the driver supports the
EVDF_RENDER_TO_TARGET feature, which can be queried with
queryFeature(). Usually, rendering to textures is done in this
......@@ -586,7 +586,32 @@ namespace video
\return True if sucessful and false if not. */
virtual bool setRenderTarget(video::ITexture* texture,
bool clearBackBuffer=true, bool clearZBuffer=true,
SColor color=video::SColor(0,0,0,0)) =0;
SColor color=video::SColor(0,0,0,0),
video::ITexture* depthStencil = 0) =0;
//! Sets a new render target.
virtual bool setRenderTarget(video::ITexture* texture,
video::ITexture* depthStencil,
bool clearBackBuffer=true, bool clearZBuffer=true,
SColor color=video::SColor(0,0,0,0))
{
return setRenderTarget(texture, clearBackBuffer, clearZBuffer, color, depthStencil);
}
//! Sets new multiple render targets. (this prototype will be removed in future)
virtual bool setRenderTarget(const core::array<video::IRenderTarget>& texture,
bool clearBackBuffer=true, bool clearZBuffer=true,
SColor color=video::SColor(0,0,0,0),
video::ITexture* depthStencil = 0) =0;
//! Sets new multiple render targets.
virtual bool setRenderTarget(const core::array<video::IRenderTarget>& texture,
video::ITexture* depthStencil,
bool clearBackBuffer=true, bool clearZBuffer=true,
SColor color=video::SColor(0,0,0,0))
{
return setRenderTarget(texture, clearBackBuffer, clearZBuffer, color, depthStencil);
}
//! set or reset special render targets
/** This method enables access to special color buffers such as
......@@ -604,11 +629,6 @@ namespace video
bool clearZBuffer=true,
SColor color=video::SColor(0,0,0,0)) =0;
//! Sets new multiple render targets.
virtual bool setRenderTarget(const core::array<video::IRenderTarget>& texture,
bool clearBackBuffer=true, bool clearZBuffer=true,
SColor color=video::SColor(0,0,0,0)) =0;
//! Sets a new viewport.
/** Every rendering operation is done into this new area.
\param area: Rectangle defining the new area of rendering
......
......@@ -50,6 +50,17 @@ namespace video
/** The following formats may only be used for render target textures. */
/** Depth and stencil formats. */
//! 16 bit format using 16 bits for depth.
ECF_D16,
//! 32 bit format using 32 bits for depth.
ECF_D32,
//! 32 bit format using 24 bits for depth and 8 bits for stencil.
ECF_D24S8,
/** Unsigned normalized integer formats. */
//! 8 bit format using 8 bits for the red channel.
......
......@@ -613,20 +613,9 @@ ITexture* CNullDriver::createDeviceDependentTexture(IImage* surface, const io::p
}
//! set or reset special render targets
bool CNullDriver::setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget,
bool clearZBuffer, SColor color)
{
if (ERT_FRAME_BUFFER==target)
return setRenderTarget(0,clearTarget, clearZBuffer, color);
else
return false;
}
//! sets a render target
bool CNullDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer,
bool clearZBuffer, SColor color)
bool clearZBuffer, SColor color, video::ITexture* depthStencil)
{
return false;
}
......@@ -634,12 +623,23 @@ bool CNullDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer
//! Sets multiple render targets
bool CNullDriver::setRenderTarget(const core::array<video::IRenderTarget>& texture,
bool clearBackBuffer, bool clearZBuffer, SColor color)
bool clearBackBuffer, bool clearZBuffer, SColor color, video::ITexture* depthStencil)
{
return false;
}
//! set or reset special render targets
bool CNullDriver::setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget,
bool clearZBuffer, SColor color)
{
if (ERT_FRAME_BUFFER==target)
return setRenderTarget(0,clearTarget, clearZBuffer, color, 0);
else
return false;
}
//! sets a viewport
void CNullDriver::setViewPort(const core::rect<s32>& area)
{
......
......@@ -102,16 +102,16 @@ namespace video
//! sets a render target
virtual bool setRenderTarget(video::ITexture* texture, bool clearBackBuffer,
bool clearZBuffer, SColor color) _IRR_OVERRIDE_;
bool clearZBuffer, SColor color, video::ITexture* depthStencil) _IRR_OVERRIDE_;
//! Sets multiple render targets
virtual bool setRenderTarget(const core::array<video::IRenderTarget>& texture,
bool clearBackBuffer, bool clearZBuffer, SColor color, video::ITexture* depthStencil) _IRR_OVERRIDE_;
//! set or reset special render targets
virtual bool setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget,
bool clearZBuffer, SColor color) _IRR_OVERRIDE_;
//! Sets multiple render targets
virtual bool setRenderTarget(const core::array<video::IRenderTarget>& texture,
bool clearBackBuffer=true, bool clearZBuffer=true, SColor color=SColor(0,0,0,0)) _IRR_OVERRIDE_;
//! sets a viewport
virtual void setViewPort(const core::rect<s32>& area) _IRR_OVERRIDE_;
......
......@@ -4286,27 +4286,8 @@ ITexture* COpenGLDriver::addRenderTargetTexture(const core::dimension2d<u32>& si
if (queryFeature(EVDF_FRAMEBUFFER_OBJECT))
{
rtt = new COpenGLFBOTexture(size, name, this, format);
if (rtt)
{
bool success = false;
addTexture(rtt);
ITexture* tex = createDepthTexture(rtt);
if (tex)
{
success = static_cast<video::COpenGLFBODepthTexture*>(tex)->attach(rtt);
if ( !success )
{
removeDepthTexture(tex);
}
tex->drop();
}
rtt->drop();
if (!success)
{
removeTexture(rtt);
rtt=0;
}
}
addTexture(rtt);
rtt->drop();
}
else
#endif
......@@ -4338,61 +4319,9 @@ u32 COpenGLDriver::getMaximalPrimitiveCount() const
}
//! set or reset render target
bool COpenGLDriver::setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget,
bool clearZBuffer, SColor color)
{
if (target != CurrentTarget)
setRenderTarget(0, false, false, 0x0);
if (ERT_RENDER_TEXTURE == target)
{
os::Printer::log("For render textures call setRenderTarget with the actual texture as first parameter.", ELL_ERROR);
return false;
}
if (ERT_MULTI_RENDER_TEXTURES == target)
{
os::Printer::log("For multiple render textures call setRenderTarget with the texture array as first parameter.", ELL_ERROR);
return false;
}
if (Params.Stereobuffer && (ERT_STEREO_RIGHT_BUFFER == target))
{
if (Params.Doublebuffer)
glDrawBuffer(GL_BACK_RIGHT);
else
glDrawBuffer(GL_FRONT_RIGHT);
}
else if (Params.Stereobuffer && ERT_STEREO_BOTH_BUFFERS == target)
{
if (Params.Doublebuffer)
glDrawBuffer(GL_BACK);
else
glDrawBuffer(GL_FRONT);
}
else if ((target >= ERT_AUX_BUFFER0) && (target-ERT_AUX_BUFFER0 < MaxAuxBuffers))
{
glDrawBuffer(GL_AUX0+target-ERT_AUX_BUFFER0);
}
else
{
if (Params.Doublebuffer)
glDrawBuffer(GL_BACK_LEFT);
else
glDrawBuffer(GL_FRONT_LEFT);
// exit with false, but also with working color buffer
if (target != ERT_FRAME_BUFFER)
return false;
}
CurrentTarget=target;
clearBuffers(clearTarget, clearZBuffer, false, color);
return true;
}
//! set or reset render target
bool COpenGLDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer,
bool clearZBuffer, SColor color)
bool clearZBuffer, SColor color, video::ITexture* depthStencil)
{
// check for right driver type
......@@ -4434,6 +4363,21 @@ bool COpenGLDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuff
// we want to set a new target. so do this.
BridgeCalls->setViewport(0, 0, texture->getSize().Width, texture->getSize().Height);
RenderTargetTexture = static_cast<COpenGLTexture*>(texture);
if (RenderTargetTexture->isFrameBufferObject())
{
if (depthStencil)
{
static_cast<COpenGLFBOTexture*>(RenderTargetTexture)->setDepthTexture(depthStencil);
}
else
{
ITexture* renderBuffer = createDepthTexture(RenderTargetTexture, true);
static_cast<COpenGLFBOTexture*>(RenderTargetTexture)->setDepthTexture(renderBuffer);
renderBuffer->drop();
}
}
// calls glDrawBuffer as well
RenderTargetTexture->bindRTT();
CurrentRendertargetSize = texture->getSize();
......@@ -4459,14 +4403,14 @@ bool COpenGLDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuff
//! Sets multiple render targets
bool COpenGLDriver::setRenderTarget(const core::array<video::IRenderTarget>& targets,
bool clearBackBuffer, bool clearZBuffer, SColor color)
bool clearBackBuffer, bool clearZBuffer, SColor color, video::ITexture* depthStencil)
{
// if simply disabling the MRT via array call
if (targets.size()==0)
return setRenderTarget(0, clearBackBuffer, clearZBuffer, color);
return setRenderTarget(0, clearBackBuffer, clearZBuffer, color, depthStencil);
// if disabling old MRT, but enabling new one as well
if ((MRTargets.size()!=0) && (targets != MRTargets))
setRenderTarget(0, clearBackBuffer, clearZBuffer, color);
setRenderTarget(0, clearBackBuffer, clearZBuffer, color, depthStencil);
// if no change, simply clear buffers
else if (targets == MRTargets)
{
......@@ -4537,13 +4481,13 @@ bool COpenGLDriver::setRenderTarget(const core::array<video::IRenderTarget>& tar
{
if (targets[i].TargetType==ERT_RENDER_TEXTURE)
{
setRenderTarget(targets[i].RenderTexture, false, false, 0x0);
setRenderTarget(targets[i].RenderTexture, false, false, 0x0, depthStencil);
break; // bind only first RTT
}
}
// init other main buffer, if necessary
if (targets[0].TargetType!=ERT_RENDER_TEXTURE)
setRenderTarget(targets[0].TargetType, false, false, 0x0);
setRenderTarget(targets[0].TargetType, false, false, 0x0, depthStencil);
// attach other textures and store buffers into array
if (maxMultipleRTTs > 1)
......@@ -4652,6 +4596,58 @@ bool COpenGLDriver::setRenderTarget(const core::array<video::IRenderTarget>& tar
}
//! set or reset render target
bool COpenGLDriver::setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget,
bool clearZBuffer, SColor color)
{
if (target != CurrentTarget)
setRenderTarget(0, false, false, 0x0, 0);
if (ERT_RENDER_TEXTURE == target)
{
os::Printer::log("For render textures call setRenderTarget with the actual texture as first parameter.", ELL_ERROR);
return false;
}
if (ERT_MULTI_RENDER_TEXTURES == target)
{
os::Printer::log("For multiple render textures call setRenderTarget with the texture array as first parameter.", ELL_ERROR);
return false;
}
if (Params.Stereobuffer && (ERT_STEREO_RIGHT_BUFFER == target))
{
if (Params.Doublebuffer)
glDrawBuffer(GL_BACK_RIGHT);
else
glDrawBuffer(GL_FRONT_RIGHT);
}
else if (Params.Stereobuffer && ERT_STEREO_BOTH_BUFFERS == target)
{
if (Params.Doublebuffer)
glDrawBuffer(GL_BACK);
else
glDrawBuffer(GL_FRONT);
}
else if ((target >= ERT_AUX_BUFFER0) && (target-ERT_AUX_BUFFER0 < MaxAuxBuffers))
{
glDrawBuffer(GL_AUX0+target-ERT_AUX_BUFFER0);
}
else
{
if (Params.Doublebuffer)
glDrawBuffer(GL_BACK_LEFT);
else
glDrawBuffer(GL_FRONT_LEFT);
// exit with false, but also with working color buffer
if (target != ERT_FRAME_BUFFER)
return false;
}
CurrentTarget=target;
clearBuffers(clearTarget, clearZBuffer, false, color);
return true;
}
// returns the current size of the screen or rendertarget
const core::dimension2d<u32>& COpenGLDriver::getCurrentRenderTargetSize() const
{
......@@ -4807,10 +4803,10 @@ ITexture* COpenGLDriver::createDepthTexture(ITexture* texture, bool shared)
return DepthTextures[i];
}
}
DepthTextures.push_back(new COpenGLFBODepthTexture(texture->getSize(), "depth1", this));
DepthTextures.push_back(new COpenGLRenderBuffer(texture->getSize(), "depth1", this));
return DepthTextures.getLast();
}
return (new COpenGLFBODepthTexture(texture->getSize(), "depth1", this));
return (new COpenGLRenderBuffer(texture->getSize(), "depth1", this));
}
......
......@@ -360,17 +360,17 @@ namespace video
virtual ITexture* addRenderTargetTexture(const core::dimension2d<u32>& size,
const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN) _IRR_OVERRIDE_;
//! set or reset render target
virtual bool setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget,
bool clearZBuffer, SColor color) _IRR_OVERRIDE_;
//! set or reset render target texture
//! sets a render target
virtual bool setRenderTarget(video::ITexture* texture, bool clearBackBuffer,
bool clearZBuffer, SColor color) _IRR_OVERRIDE_;
bool clearZBuffer, SColor color, video::ITexture* depthStencil) _IRR_OVERRIDE_;
//! Sets multiple render targets
virtual bool setRenderTarget(const core::array<video::IRenderTarget>& texture,
bool clearBackBuffer=true, bool clearZBuffer=true, SColor color=SColor(0,0,0,0)) _IRR_OVERRIDE_;
bool clearBackBuffer, bool clearZBuffer, SColor color, video::ITexture* depthStencil) _IRR_OVERRIDE_;
//! set or reset special render targets
virtual bool setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget,
bool clearZBuffer, SColor color) _IRR_OVERRIDE_;
//! Clears the ZBuffer.
virtual void clearZBuffer() _IRR_OVERRIDE_;
......
......@@ -25,7 +25,7 @@ COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, void* mi
TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT),
PixelType(GL_UNSIGNED_BYTE), MipLevelStored(0), MipmapLegacyMode(true),
IsRenderTarget(false), IsCompressed(false), AutomaticMipmapUpdate(false),
ReadOnlyLock(false), KeepImage(true)
ReadOnlyLock(false), KeepImage(true), IsDepthTexture(false), IsRenderBuffer(false)
{
#ifdef _DEBUG
setDebugName("COpenGLTexture");
......@@ -82,7 +82,8 @@ COpenGLTexture::COpenGLTexture(const io::path& name, COpenGLDriver* driver)
TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT),
PixelType(GL_UNSIGNED_BYTE), MipLevelStored(0), HasMipMaps(true),
MipmapLegacyMode(true), IsRenderTarget(false), IsCompressed(false),
AutomaticMipmapUpdate(false), ReadOnlyLock(false), KeepImage(true)
AutomaticMipmapUpdate(false), ReadOnlyLock(false), KeepImage(true),
IsDepthTexture(false), IsRenderBuffer(false)
{
#ifdef _DEBUG
setDebugName("COpenGLTexture");
......@@ -198,96 +199,118 @@ GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT
type = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
internalformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
break;
case ECF_D16:
colorformat = GL_DEPTH_COMPONENT;
type = GL_UNSIGNED_BYTE;
internalformat = GL_DEPTH_COMPONENT16;
break;
case ECF_D32:
colorformat = GL_DEPTH_COMPONENT;
type = GL_UNSIGNED_BYTE;
internalformat = GL_DEPTH_COMPONENT32;
break;
case ECF_D24S8:
#ifdef GL_EXT_packed_depth_stencil
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_EXT_packed_depth_stencil))
{
colorformat = GL_DEPTH_STENCIL_EXT;
type = GL_UNSIGNED_INT_24_8_EXT;
internalformat = GL_DEPTH_STENCIL_EXT;
}
else
#endif
os::Printer::log("ECF_D24S8 color format is not supported", ELL_ERROR);
break;
case ECF_R8:
if (Driver->FeatureAvailable[Driver->IRR_ARB_texture_rg])
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
{
colorformat = GL_RED;
type = GL_UNSIGNED_BYTE;
internalformat = GL_R8;
}
else
os::Printer::log("ECF_R8 color format is unsupported", ELL_ERROR);
os::Printer::log("ECF_R8 color format is not supported", ELL_ERROR);
break;
case ECF_R8G8:
if (Driver->FeatureAvailable[Driver->IRR_ARB_texture_rg])
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
{
colorformat = GL_RG;
type = GL_UNSIGNED_BYTE;
internalformat = GL_RG8;
}
else
os::Printer::log("ECF_R8G8 color format is unsupported", ELL_ERROR);
os::Printer::log("ECF_R8G8 color format is not supported", ELL_ERROR);
break;
case ECF_R16:
if (Driver->FeatureAvailable[Driver->IRR_ARB_texture_rg])
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
{
colorformat = GL_RED;
type = GL_UNSIGNED_SHORT;
internalformat = GL_R16;
}
else
os::Printer::log("ECF_R16 color format is unsupported", ELL_ERROR);
os::Printer::log("ECF_R16 color format is not supported", ELL_ERROR);
break;
case ECF_R16G16:
if (Driver->FeatureAvailable[Driver->IRR_ARB_texture_rg])
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
{
colorformat = GL_RG;
type = GL_UNSIGNED_SHORT;
internalformat = GL_RG16;
}
else
os::Printer::log("ECF_R16G16 color format is unsupported", ELL_ERROR);
os::Printer::log("ECF_R16G16 color format is not supported", ELL_ERROR);
break;
case ECF_R16F:
if (Driver->FeatureAvailable[Driver->IRR_ARB_texture_rg])
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
{
filtering = GL_NEAREST;
colorformat = GL_RED;
internalformat = GL_R16F;
#ifdef GL_ARB_half_float_pixel
if (Driver->FeatureAvailable[Driver->IRR_ARB_half_float_pixel])
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_half_float_pixel))
type = GL_HALF_FLOAT_ARB;
else
#endif
type = GL_FLOAT;
}
else
os::Printer::log("ECF_R16F color format is unsupported", ELL_ERROR);
os::Printer::log("ECF_R16F color format is not supported", ELL_ERROR);
break;
case ECF_G16R16F:
if (Driver->FeatureAvailable[Driver->IRR_ARB_texture_rg])
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
{
filtering = GL_NEAREST;
colorformat = GL_RG;
internalformat = GL_RG16F;
#ifdef GL_ARB_half_float_pixel
if (Driver->FeatureAvailable[Driver->IRR_ARB_half_float_pixel])
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_half_float_pixel))
type = GL_HALF_FLOAT_ARB;
else
#endif
type = GL_FLOAT;
}
else
os::Printer::log("ECF_G16R16F color format is unsupported", ELL_ERROR);
os::Printer::log("ECF_G16R16F color format is not supported", ELL_ERROR);
break;
case ECF_A16B16G16R16F:
if (Driver->FeatureAvailable[Driver->IRR_ARB_texture_float])
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_float))
{
filtering = GL_NEAREST;
colorformat = GL_RGBA;
internalformat = GL_RGBA16F_ARB;
#ifdef GL_ARB_half_float_pixel
if (Driver->FeatureAvailable[Driver->IRR_ARB_half_float_pixel])
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_half_float_pixel))
type = GL_HALF_FLOAT_ARB;
else
#endif
type = GL_FLOAT;
}
else
os::Printer::log("ECF_A16B16G16R16F color format is unsupported", ELL_ERROR);
os::Printer::log("ECF_A16B16G16R16F color format is not supported", ELL_ERROR);
break;
case ECF_R32F:
if (Driver->FeatureAvailable[Driver->IRR_ARB_texture_rg])
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
{
filtering = GL_NEAREST;
colorformat = GL_RED;
......@@ -295,10 +318,10 @@ GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT
type = GL_FLOAT;
}
else
os::Printer::log("ECF_R32F color format is unsupported", ELL_ERROR);
os::Printer::log("ECF_R32F color format is not supported", ELL_ERROR);
break;
case ECF_G32R32F:
if (Driver->FeatureAvailable[Driver->IRR_ARB_texture_rg])
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_rg))
{
filtering = GL_NEAREST;
colorformat = GL_RG;
......@@ -306,10 +329,10 @@ GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT
type = GL_FLOAT;
}
else
os::Printer::log("ECF_G32R32F color format is unsupported", ELL_ERROR);
os::Printer::log("ECF_G32R32F color format is not supported", ELL_ERROR);
break;
case ECF_A32B32G32R32F:
if (Driver->FeatureAvailable[Driver->IRR_ARB_texture_float])
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_texture_float))
{
filtering = GL_NEAREST;
colorformat = GL_RGBA;
......@@ -317,7 +340,7 @@ GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT
type = GL_FLOAT;
}
else
os::Printer::log("ECF_A32B32G32R32F color format is unsupported", ELL_ERROR);
os::Printer::log("ECF_A32B32G32R32F color format is not supported", ELL_ERROR);
break;
default:
os::Printer::log("Unsupported texture format", ELL_ERROR);
......@@ -809,6 +832,18 @@ bool COpenGLTexture::isFrameBufferObject() const
}
bool COpenGLTexture::isDepthTexture() const
{
return IsDepthTexture;
}
bool COpenGLTexture::isRenderBuffer() const
{
return IsRenderBuffer;
}
//! Bind Render Target Texture
void COpenGLTexture::bindRTT()
{
......@@ -838,36 +873,33 @@ COpenGLTexture::SStatesCache& COpenGLTexture::getStatesCache() const
// helper function for render to texture
static bool checkFBOStatus(COpenGLDriver* Driver);
//! RTT ColorFrameBuffer constructor
//! RTT FBO constructor
COpenGLFBOTexture::COpenGLFBOTexture(const core::dimension2d<u32>& size,
const io::path& name, COpenGLDriver* driver,
ECOLOR_FORMAT format)
: COpenGLTexture(name, driver), DepthTexture(0), ColorFrameBuffer(0)
: COpenGLTexture(name, driver), BufferID(0), DepthTexture(0)
{
#ifdef _DEBUG
setDebugName("COpenGLTexture_FBO");
#endif
ImageSize = size;
TextureSize = size;
if (ECF_UNKNOWN == format)
format = getBestColorFormat(driver->getColorFormat());
IsDepthTexture = IImage::isDepthFormat(format);
ImageSize = size;
TextureSize = size;
ColorFormat = format;
GLint FilteringType;
GLint FilteringType = 0;
InternalFormat = getOpenGLFormatAndParametersFromColorFormat(format, FilteringType, PixelFormat, PixelType);
HasMipMaps = false;
IsRenderTarget = true;
#ifdef GL_EXT_framebuffer_object
// generate frame buffer
Driver->extGlGenFramebuffers(1, &ColorFrameBuffer);
bindRTT();
// generate color texture
glGenTextures(1, &TextureName);
Driver->setActiveTexture(0, this);
......@@ -877,7 +909,7 @@ COpenGLFBOTexture::COpenGLFBOTexture(const core::dimension2d<u32>& size,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if(FilteringType == GL_NEAREST)
if (FilteringType == GL_NEAREST)
StatesCache.BilinearFilter = false;
else
StatesCache.BilinearFilter = true;
......@@ -885,24 +917,25 @@ COpenGLFBOTexture::COpenGLFBOTexture(const core::dimension2d<u32>& size,
StatesCache.WrapU = ETC_CLAMP_TO_EDGE;
StatesCache.WrapV = ETC_CLAMP_TO_EDGE;
glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, ImageSize.Width,
ImageSize.Height, 0, PixelFormat, PixelType, 0);
#ifdef _DEBUG
driver->testGLError();
#endif
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);
#ifdef _DEBUG
checkFBOStatus(Driver);
#endif
Driver->setActiveTexture(0, 0);
Driver->getBridgeCalls()->setTexture(0, true);
#ifdef GL_EXT_framebuffer_object
// generate FBO
Driver->extGlGenFramebuffers(1, &BufferID);
if (BufferID != 0 && !IsDepthTexture)
{
Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, BufferID);
Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, TextureName, 0);
Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
}
#endif
unbindRTT();
}
......@@ -910,10 +943,15 @@ COpenGLFBOTexture::COpenGLFBOTexture(const core::dimension2d<u32>& size,
COpenGLFBOTexture::~COpenGLFBOTexture()
{
if (DepthTexture)
if (DepthTexture->drop())
{
bool remove = DepthTexture->isRenderBuffer();
if (DepthTexture->drop() && remove)
Driver->removeDepthTexture(DepthTexture);
if (ColorFrameBuffer)
Driver->extGlDeleteFramebuffers(1, &ColorFrameBuffer);
}
if (BufferID)
Driver->extGlDeleteFramebuffers(1, &BufferID);
}
......@@ -927,8 +965,9 @@ bool COpenGLFBOTexture::isFrameBufferObject() const
void COpenGLFBOTexture::bindRTT()
{
#ifdef GL_EXT_framebuffer_object
if (ColorFrameBuffer != 0)
Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, ColorFrameBuffer);
if (BufferID != 0)
Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, BufferID);
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
#endif
}
......@@ -938,27 +977,103 @@ void COpenGLFBOTexture::bindRTT()
void COpenGLFBOTexture::unbindRTT()
{
#ifdef GL_EXT_framebuffer_object
if (ColorFrameBuffer != 0)
if (BufferID != 0)
Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
#endif
}
/* FBO Depth Textures */
//! Get depth texture.
ITexture* COpenGLFBOTexture::getDepthTexture() const
{
return DepthTexture;
}
//! Set depth texture.
bool COpenGLFBOTexture::setDepthTexture(ITexture* depthTexture)
{
if (DepthTexture == depthTexture || BufferID == 0)
return false;
#ifdef GL_EXT_framebuffer_object
Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, BufferID);
#endif
if (DepthTexture)
{
if (DepthTexture->isRenderBuffer())
{
Driver->extGlFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);
}
else
{
Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);
if (DepthTexture->getColorFormat() == ECF_D24S8)
Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);
}
if (DepthTexture->drop())
Driver->removeDepthTexture(DepthTexture);
}
COpenGLTexture* tex = static_cast<COpenGLTexture*>(depthTexture);
DepthTexture = (tex && tex->isDepthTexture()) ? tex : 0;
if (DepthTexture)
{
DepthTexture->grab();
if (DepthTexture->isRenderBuffer())
{
COpenGLRenderBuffer* renderBuffer = static_cast<COpenGLRenderBuffer*>(DepthTexture);
Driver->extGlFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderBuffer->getBufferID());
}
else
{
COpenGLFBOTexture* fboDepthTexture = static_cast<COpenGLFBOTexture*>(DepthTexture);
Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, fboDepthTexture->getOpenGLTextureName(), 0);
if (DepthTexture->getColorFormat() == ECF_D24S8)
Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, fboDepthTexture->getOpenGLTextureName(), 0);
}
}
#ifdef GL_EXT_framebuffer_object
Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
#endif
if (!checkFBOStatus(Driver))
{
os::Printer::log("FBO incomplete");
return false;
}
return true;
}
/* Render Buffer */
//! RTT DepthBuffer constructor
COpenGLFBODepthTexture::COpenGLFBODepthTexture(
//! constructor
COpenGLRenderBuffer::COpenGLRenderBuffer(
const core::dimension2d<u32>& size,
const io::path& name,
COpenGLDriver* driver,
bool useStencil)
: COpenGLTexture(name, driver), DepthRenderBuffer(0),
StencilRenderBuffer(0), UseStencil(useStencil)
: COpenGLTexture(name, driver), BufferID(0)
{
#ifdef _DEBUG
setDebugName("COpenGLTextureFBO_Depth");
#endif
IsDepthTexture = true;
IsRenderBuffer = true;
ImageSize = size;
TextureSize = size;
InternalFormat = GL_RGBA;
......@@ -966,119 +1081,40 @@ COpenGLFBODepthTexture::COpenGLFBODepthTexture(
PixelType = GL_UNSIGNED_BYTE;
HasMipMaps = false;
if (useStencil)
{
glGenTextures(1, &DepthRenderBuffer);
glBindTexture(GL_TEXTURE_2D, DepthRenderBuffer);
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);
#ifdef GL_EXT_packed_depth_stencil
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_EXT_packed_depth_stencil))
{
// generate packed depth stencil texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL_EXT, ImageSize.Width,
ImageSize.Height, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0);
StencilRenderBuffer = DepthRenderBuffer; // stencil is packed with depth
}
else // generate separate stencil and depth textures
#endif
{
// generate depth texture
glTexImage2D(GL_TEXTURE_2D, 0, Driver->getZBufferBits(), ImageSize.Width,
ImageSize.Height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
// generate stencil texture
glGenTextures(1, &StencilRenderBuffer);
glBindTexture(GL_TEXTURE_2D, StencilRenderBuffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_STENCIL_INDEX, ImageSize.Width,
ImageSize.Height, 0, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, 0);
}
}
#ifdef GL_EXT_framebuffer_object
else
{
// generate depth buffer
Driver->extGlGenRenderbuffers(1, &DepthRenderBuffer);
Driver->extGlBindRenderbuffer(GL_RENDERBUFFER_EXT, DepthRenderBuffer);
Driver->extGlRenderbufferStorage(GL_RENDERBUFFER_EXT,
Driver->getZBufferBits(), ImageSize.Width,
ImageSize.Height);
}
// generate depth buffer
Driver->extGlGenRenderbuffers(1, &BufferID);
Driver->extGlBindRenderbuffer(GL_RENDERBUFFER_EXT, BufferID);
Driver->extGlRenderbufferStorage(GL_RENDERBUFFER_EXT, Driver->getZBufferBits(), ImageSize.Width, ImageSize.Height);
Driver->extGlBindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
#endif
}
//! destructor
COpenGLFBODepthTexture::~COpenGLFBODepthTexture()
COpenGLRenderBuffer::~COpenGLRenderBuffer()
{
if (DepthRenderBuffer && UseStencil)
glDeleteTextures(1, &DepthRenderBuffer);
else
Driver->extGlDeleteRenderbuffers(1, &DepthRenderBuffer);
if (StencilRenderBuffer && StencilRenderBuffer != DepthRenderBuffer)
glDeleteTextures(1, &StencilRenderBuffer);
if (BufferID)
Driver->extGlDeleteRenderbuffers(1, &BufferID);
}
//combine depth texture and rtt
bool COpenGLFBODepthTexture::attach(ITexture* renderTex)
//! Bind Render Target Texture
void COpenGLRenderBuffer::bindRTT()
{
if (!renderTex)
return false;
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,
GL_STENCIL_ATTACHMENT_EXT,
GL_TEXTURE_2D,
StencilRenderBuffer,
0);
// attach depth texture to depth buffer
Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT,
GL_TEXTURE_2D,
DepthRenderBuffer,
0);
}
else
{
// attach depth renderbuffer to depth buffer
Driver->extGlFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT,
DepthRenderBuffer);
}
#endif
// check the status
if (!checkFBOStatus(Driver))
{
os::Printer::log("FBO incomplete");
return false;
}
rtt->DepthTexture=this;
grab(); // grab the depth buffer, not the RTT
rtt->unbindRTT();
return true;
}
//! Bind Render Target Texture
void COpenGLFBODepthTexture::bindRTT()
//! Unbind Render Target Texture
void COpenGLRenderBuffer::unbindRTT()
{
}
//! Unbind Render Target Texture
void COpenGLFBODepthTexture::unbindRTT()
bool COpenGLRenderBuffer::getBufferID() const
{
return BufferID;
}
......
......@@ -116,6 +116,12 @@ public:
//! Is it a FrameBufferObject?
virtual bool isFrameBufferObject() const;
//! Is it a depth texture?
bool isDepthTexture() const _IRR_OVERRIDE_;
//! Is it a renderbuffer?
bool isRenderBuffer() const _IRR_OVERRIDE_;
//! Bind RenderTargetTexture
virtual void bindRTT();
......@@ -170,6 +176,9 @@ protected:
bool ReadOnlyLock;
bool KeepImage;
bool IsDepthTexture;
bool IsRenderBuffer;
mutable SStatesCache StatesCache;
};
......@@ -194,21 +203,28 @@ public:
//! Unbind RenderTargetTexture
virtual void unbindRTT() _IRR_OVERRIDE_;
ITexture* DepthTexture;
//! Return depth texture.
ITexture* getDepthTexture() const;
//! Set depth texture.
bool setDepthTexture(ITexture* depthTexture);
protected:
GLuint ColorFrameBuffer;
GLuint BufferID;
COpenGLTexture* DepthTexture;
};
//! OpenGL FBO depth texture.
class COpenGLFBODepthTexture : public COpenGLTexture
//! OpenGL Render Buffer.
class COpenGLRenderBuffer : public COpenGLTexture
{
public:
//! FrameBufferObject depth constructor
COpenGLFBODepthTexture(const core::dimension2d<u32>& size, const io::path& name, COpenGLDriver* driver=0, bool useStencil=false);
COpenGLRenderBuffer(const core::dimension2d<u32>& size, const io::path& name, COpenGLDriver* driver=0, bool useStencil=false);
//! destructor
virtual ~COpenGLFBODepthTexture();
virtual ~COpenGLRenderBuffer();
//! Bind RenderTargetTexture
virtual void bindRTT() _IRR_OVERRIDE_;
......@@ -216,12 +232,10 @@ public:
//! Unbind RenderTargetTexture
virtual void unbindRTT() _IRR_OVERRIDE_;
bool attach(ITexture*);
bool getBufferID() const;
protected:
GLuint DepthRenderBuffer;
GLuint StencilRenderBuffer;
bool UseStencil;
GLuint BufferID;
};
......
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