Commit 8ca89ee6 authored by hybrid's avatar hybrid

Added support for Stereo framebuffers and AUX buffers (which are currently...

Added support for Stereo framebuffers and AUX buffers (which are currently only accessible via direct OpenGL calls or shaders).
Added a creation parameter for doublebuffering.
Cleaned up the framebuffer clean methods in OpenGL.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2102 dfc29bdd-3216-0410-991c-e03cc46cb475
parent fed4bd31
...@@ -78,6 +78,29 @@ namespace video ...@@ -78,6 +78,29 @@ namespace video
ELR_HW_BUFFERS = 8 ELR_HW_BUFFERS = 8
}; };
enum E_RENDER_TARGET
{
//! Render target is the main color frame buffer
ERT_FRAME_BUFFER=0,
ERT_STEREO_LEFT_BUFFER=0,
//! Render target is a render texture
ERT_RENDER_TEXTURE,
//! Render target is the right color buffer (left is the main buffer)
ERT_STEREO_RIGHT_BUFFER,
//! Render to both stereo buffers at once
ERT_STEREO_BOTH_BUFFERS,
//! Auxiliary buffer 0
ERT_AUX_BUFFER0,
//! Auxiliary buffer 1
ERT_AUX_BUFFER1,
//! Auxiliary buffer 2
ERT_AUX_BUFFER2,
//! Auxiliary buffer 3
ERT_AUX_BUFFER3,
//! Auxiliary buffer 4
ERT_AUX_BUFFER4
};
//! Interface to driver which is able to perform 2d and 3d graphics functions. //! Interface to driver which is able to perform 2d and 3d graphics functions.
/** This interface is one of the most important interfaces of /** This interface is one of the most important interfaces of
the Irrlicht Engine: All rendering and texture manipulation is done with the Irrlicht Engine: All rendering and texture manipulation is done with
...@@ -352,7 +375,22 @@ namespace video ...@@ -352,7 +375,22 @@ namespace video
\return True if sucessful and false if not. */ \return True if sucessful and false if not. */
virtual bool setRenderTarget(video::ITexture* texture, virtual bool setRenderTarget(video::ITexture* texture,
bool clearBackBuffer=true, bool clearZBuffer=true, bool clearBackBuffer=true, bool clearZBuffer=true,
SColor color=video::SColor(0,0,0,0)) = 0; SColor color=video::SColor(0,0,0,0)) =0;
//! set or reset special render targets
/** This method enables access to special color buffers such as
stereoscopic buffers or auxiliary buffers.
\param target Enum value for the render target
\param clearTarget Clears the target buffer with the color
parameter
\param clearZBuffer Clears the zBuffer of the rendertarget.
Note that because the main frame buffer may share the zbuffer with
the rendertarget, its zbuffer might be partially cleared too
by this.
\param color The background color for the render target.
\return True if sucessful and false if not. */
virtual bool setRenderTarget(E_RENDER_TARGET target, bool clearTarget,
bool clearZBuffer, SColor color) =0;
//! Sets a new viewport. //! Sets a new viewport.
/** Every rendering operation is done into this new area. /** Every rendering operation is done into this new area.
......
...@@ -27,7 +27,9 @@ namespace irr ...@@ -27,7 +27,9 @@ namespace irr
Vsync(false), Vsync(false),
AntiAlias(0), AntiAlias(0),
WithAlphaChannel(false), WithAlphaChannel(false),
Doublebuffer(true),
IgnoreInput(false), IgnoreInput(false),
Stereobuffer(false),
HighPrecisionFPU(false), HighPrecisionFPU(false),
EventReceiver(0), EventReceiver(0),
WindowId(0), WindowId(0),
...@@ -50,7 +52,9 @@ namespace irr ...@@ -50,7 +52,9 @@ namespace irr
Vsync = other.Vsync; Vsync = other.Vsync;
AntiAlias = other.AntiAlias; AntiAlias = other.AntiAlias;
WithAlphaChannel = other.WithAlphaChannel; WithAlphaChannel = other.WithAlphaChannel;
Doublebuffer = other.Doublebuffer;
IgnoreInput = other.IgnoreInput; IgnoreInput = other.IgnoreInput;
Stereobuffer = other.Stereobuffer;
HighPrecisionFPU = other.HighPrecisionFPU; HighPrecisionFPU = other.HighPrecisionFPU;
EventReceiver = other.EventReceiver; EventReceiver = other.EventReceiver;
WindowId = other.WindowId; WindowId = other.WindowId;
...@@ -120,13 +124,29 @@ namespace irr ...@@ -120,13 +124,29 @@ namespace irr
Default value: false */ Default value: false */
bool WithAlphaChannel; bool WithAlphaChannel;
//! Whether the main framebuffer uses doublebuffering.
/** This should be usually enabled, in order to avoid render
artifacts on the visible framebuffer. However, it might be
useful to use only one buffer on very small devices. If no
doublebuffering is available, the drivers will fall back to
single buffers. Default value: true */
bool Doublebuffer;
//! Specifies if the device should ignore input events //! Specifies if the device should ignore input events
/** This is only relevant when using external I/O handlers. /** This is only relevant when using external I/O handlers.
External windows need to take care of this themselves. External windows need to take care of this themselves.
Currently only supported under X11. Currently only supported by X11.
Default value: false */ Default value: false */
bool IgnoreInput; bool IgnoreInput;
//! Specifies if the device should use stereo buffers
/** Some high-end gfx cards support two framebuffers for direct
support of stereoscopic output devices. If this flag is set the
device tries to create a stereo context.
Currently only supported by OpenGL.
Default value: false */
bool Stereobuffer;
//! Specifies if the device should use high precision FPU setting //! Specifies if the device should use high precision FPU setting
/** This is only relevant for DirectX Devices, which switch to /** This is only relevant for DirectX Devices, which switch to
low FPU precision by default for performance reasons. However, low FPU precision by default for performance reasons. However,
......
...@@ -310,10 +310,11 @@ bool CIrrDeviceLinux::createWindow() ...@@ -310,10 +310,11 @@ bool CIrrDeviceLinux::createWindow()
GLX_BLUE_SIZE, 4, GLX_BLUE_SIZE, 4,
GLX_ALPHA_SIZE, CreationParams.WithAlphaChannel?1:0, GLX_ALPHA_SIZE, CreationParams.WithAlphaChannel?1:0,
GLX_DEPTH_SIZE, CreationParams.ZBufferBits, GLX_DEPTH_SIZE, CreationParams.ZBufferBits,
GLX_DOUBLEBUFFER, GL_TRUE, GLX_DOUBLEBUFFER, CreationParams.Doublebuffer?GL_TRUE:GL_FALSE,
GLX_STENCIL_SIZE, 1, GLX_STENCIL_SIZE, 1,
GLX_SAMPLE_BUFFERS_ARB, 1, GLX_SAMPLE_BUFFERS_ARB, 1,
GLX_SAMPLES_ARB, CreationParams.AntiAlias, GLX_SAMPLES_ARB, CreationParams.AntiAlias,
GLX_STEREO, CreationParams.Stereobuffer?GL_TRUE:GL_FALSE,
None None
}; };
...@@ -389,10 +390,11 @@ bool CIrrDeviceLinux::createWindow() ...@@ -389,10 +390,11 @@ bool CIrrDeviceLinux::createWindow()
} }
} }
// Next try without double buffer // Next try without double buffer
if (!configList) if (!configList && CreationParams.Doublebuffer)
{ {
os::Printer::log("No doublebuffering available.", ELL_WARNING); os::Printer::log("No doublebuffering available.", ELL_WARNING);
visualAttrBuffer[13] = GL_FALSE; CreationParams.Doublebuffer=false;
visualAttrBuffer[13] = GLX_DONT_CARE;
configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);
if (!configList && CreationParams.AntiAlias) if (!configList && CreationParams.AntiAlias)
{ {
...@@ -439,8 +441,9 @@ bool CIrrDeviceLinux::createWindow() ...@@ -439,8 +441,9 @@ bool CIrrDeviceLinux::createWindow()
GLX_BLUE_SIZE, 4, GLX_BLUE_SIZE, 4,
GLX_ALPHA_SIZE, CreationParams.WithAlphaChannel?1:0, GLX_ALPHA_SIZE, CreationParams.WithAlphaChannel?1:0,
GLX_DEPTH_SIZE, CreationParams.ZBufferBits, GLX_DEPTH_SIZE, CreationParams.ZBufferBits,
GLX_DOUBLEBUFFER, GL_TRUE, GLX_DOUBLEBUFFER, CreationParams.Doublebuffer?GL_TRUE:GL_FALSE,
GLX_STENCIL_SIZE, 1, GLX_STENCIL_SIZE, 1,
GLX_STEREO, CreationParams.Stereobuffer?GL_TRUE:GL_FALSE,
None None
}; };
...@@ -456,10 +459,11 @@ bool CIrrDeviceLinux::createWindow() ...@@ -456,10 +459,11 @@ bool CIrrDeviceLinux::createWindow()
visualAttrBuffer[15]=0; visualAttrBuffer[15]=0;
visual=glXChooseVisual(display, screennr, visualAttrBuffer); visual=glXChooseVisual(display, screennr, visualAttrBuffer);
if (!visual) if (!visual && CreationParams.Doublebuffer)
{ {
os::Printer::log("No doublebuffering available.", ELL_WARNING); os::Printer::log("No doublebuffering available.", ELL_WARNING);
visualAttrBuffer[13] = GL_FALSE; CreationParams.Doublebuffer=false;
visualAttrBuffer[13] = GLX_DONT_CARE;
visual=glXChooseVisual(display, screennr, visualAttrBuffer); visual=glXChooseVisual(display, screennr, visualAttrBuffer);
} }
} }
...@@ -475,6 +479,7 @@ bool CIrrDeviceLinux::createWindow() ...@@ -475,6 +479,7 @@ bool CIrrDeviceLinux::createWindow()
// create visual with standard X methods // create visual with standard X methods
{ {
os::Printer::log("Using plain X visual");
XVisualInfo visTempl; //Template to hold requested values XVisualInfo visTempl; //Template to hold requested values
int visNumber; // Return value of available visuals int visNumber; // Return value of available visuals
......
...@@ -89,7 +89,7 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param) ...@@ -89,7 +89,7 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param)
SDL_Flags |= SDL_FULLSCREEN; SDL_Flags |= SDL_FULLSCREEN;
if (CreationParams.DriverType == video::EDT_OPENGL) if (CreationParams.DriverType == video::EDT_OPENGL)
SDL_Flags |= SDL_OPENGL; SDL_Flags |= SDL_OPENGL;
else else if (CreationParams.Doublebuffer)
SDL_Flags |= SDL_DOUBLEBUF; SDL_Flags |= SDL_DOUBLEBUF;
// create window // create window
if (CreationParams.DriverType != video::EDT_NULL) if (CreationParams.DriverType != video::EDT_NULL)
...@@ -147,7 +147,10 @@ bool CIrrDeviceSDL::createWindow() ...@@ -147,7 +147,10 @@ bool CIrrDeviceSDL::createWindow()
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, CreationParams.WithAlphaChannel?8:0 ); SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, CreationParams.WithAlphaChannel?8:0 );
} }
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, CreationParams.ZBufferBits); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, CreationParams.ZBufferBits);
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); if (CreationParams.Doublebuffer)
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
if (CreationParams.Stereobuffer)
SDL_GL_SetAttribute( SDL_GL_STEREO, 1 );
if (CreationParams.AntiAlias>1) if (CreationParams.AntiAlias>1)
{ {
SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 1 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 1 );
...@@ -176,6 +179,12 @@ bool CIrrDeviceSDL::createWindow() ...@@ -176,6 +179,12 @@ bool CIrrDeviceSDL::createWindow()
os::Printer::log("AntiAliasing disabled due to lack of support!" ); os::Printer::log("AntiAliasing disabled due to lack of support!" );
} }
} }
if ( !Screen && CreationParams.Doublebuffer)
{
// Try single buffer
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
Screen = SDL_SetVideoMode( Width, Height, CreationParams.Bits, SDL_Flags );
}
if ( !Screen ) if ( !Screen )
{ {
os::Printer::log( "Could not initialize display!" ); os::Printer::log( "Could not initialize display!" );
......
...@@ -498,6 +498,16 @@ ITexture* CNullDriver::createDeviceDependentTexture(IImage* surface, const char* ...@@ -498,6 +498,16 @@ ITexture* CNullDriver::createDeviceDependentTexture(IImage* surface, const char*
} }
//! 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 //! sets a render target
bool CNullDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer, bool CNullDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer,
...@@ -507,14 +517,12 @@ bool CNullDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer ...@@ -507,14 +517,12 @@ bool CNullDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer
} }
//! sets a viewport //! sets a viewport
void CNullDriver::setViewPort(const core::rect<s32>& area) void CNullDriver::setViewPort(const core::rect<s32>& area)
{ {
} }
//! gets the area of the current viewport //! gets the area of the current viewport
const core::rect<s32>& CNullDriver::getViewPort() const const core::rect<s32>& CNullDriver::getViewPort() const
{ {
...@@ -522,7 +530,6 @@ const core::rect<s32>& CNullDriver::getViewPort() const ...@@ -522,7 +530,6 @@ const core::rect<s32>& CNullDriver::getViewPort() const
} }
//! draws a vertex primitive list //! draws a vertex primitive list
void CNullDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) void CNullDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType)
{ {
...@@ -530,7 +537,6 @@ void CNullDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount, ...@@ -530,7 +537,6 @@ void CNullDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount,
} }
//! draws an indexed triangle list //! draws an indexed triangle list
inline void CNullDriver::drawIndexedTriangleList(const S3DVertex* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) inline void CNullDriver::drawIndexedTriangleList(const S3DVertex* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount)
{ {
...@@ -538,7 +544,6 @@ inline void CNullDriver::drawIndexedTriangleList(const S3DVertex* vertices, u32 ...@@ -538,7 +544,6 @@ inline void CNullDriver::drawIndexedTriangleList(const S3DVertex* vertices, u32
} }
//! draws an indexed triangle list //! draws an indexed triangle list
inline void CNullDriver::drawIndexedTriangleList(const S3DVertex2TCoords* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) inline void CNullDriver::drawIndexedTriangleList(const S3DVertex2TCoords* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount)
{ {
......
...@@ -89,6 +89,10 @@ namespace video ...@@ -89,6 +89,10 @@ namespace video
virtual bool setRenderTarget(video::ITexture* texture, bool clearBackBuffer, virtual bool setRenderTarget(video::ITexture* texture, bool clearBackBuffer,
bool clearZBuffer, SColor color); bool clearZBuffer, SColor color);
//! set or reset special render targets
virtual bool setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget,
bool clearZBuffer, SColor color);
//! sets a viewport //! sets a viewport
virtual void setViewPort(const core::rect<s32>& area); virtual void setViewPort(const core::rect<s32>& area);
......
...@@ -36,7 +36,9 @@ COpenGLDriver::COpenGLDriver(const irr::SIrrlichtCreationParameters& params, ...@@ -36,7 +36,9 @@ COpenGLDriver::COpenGLDriver(const irr::SIrrlichtCreationParameters& params,
: CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(),
CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true),
AntiAlias(params.AntiAlias), RenderTargetTexture(0), LastSetLight(-1), AntiAlias(params.AntiAlias), RenderTargetTexture(0), LastSetLight(-1),
CurrentRendertargetSize(0,0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8),
CurrentTarget(ERT_FRAME_BUFFER),
Doublebuffer(params.Doublebuffer), Stereo(params.Stereobuffer),
HDc(0), Window(static_cast<HWND>(params.WindowId)), HRc(0) HDc(0), Window(static_cast<HWND>(params.WindowId)), HRc(0)
{ {
#ifdef _DEBUG #ifdef _DEBUG
...@@ -47,13 +49,14 @@ COpenGLDriver::COpenGLDriver(const irr::SIrrlichtCreationParameters& params, ...@@ -47,13 +49,14 @@ COpenGLDriver::COpenGLDriver(const irr::SIrrlichtCreationParameters& params,
//! inits the open gl driver //! inits the open gl driver
bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params) bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params)
{ {
// Set up ixel format descriptor with desired parameters // Set up pixel format descriptor with desired parameters
PIXELFORMATDESCRIPTOR pfd = { PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number 1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering params.Doublebuffer?PFD_DOUBLEBUFFER:0 | // Must Support Double Buffering
params.Stereobuffer?PFD_STEREO:0 | // Must Support Stereo Buffer
PFD_TYPE_RGBA, // Request An RGBA Format PFD_TYPE_RGBA, // Request An RGBA Format
params.Bits, // Select Our Color Depth params.Bits, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored 0, 0, 0, 0, 0, 0, // Color Bits Ignored
...@@ -150,6 +153,15 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params) ...@@ -150,6 +153,15 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params)
} }
else else
if (i == 4) if (i == 4)
{
// try single buffer
if (params.Doublebuffer)
pfd.dwFlags &= ~PFD_DOUBLEBUFFER;
else
continue;
}
else
if (i == 5)
{ {
os::Printer::log("Cannot create a GL device context", "No suitable format for temporary window.", ELL_ERROR); os::Printer::log("Cannot create a GL device context", "No suitable format for temporary window.", ELL_ERROR);
ReleaseDC(temporary_wnd, HDc); ReleaseDC(temporary_wnd, HDc);
...@@ -190,8 +202,8 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params) ...@@ -190,8 +202,8 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params)
// improvement over 4, but 4 shows a big improvement // improvement over 4, but 4 shows a big improvement
// over 2. // over 2.
if(AntiAlias > 16) if(AntiAlias > 32)
AntiAlias = 16; AntiAlias = 32;
f32 fAttributes[] = {0.0, 0.0}; f32 fAttributes[] = {0.0, 0.0};
s32 iAttributes[] = s32 iAttributes[] =
...@@ -203,7 +215,8 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params) ...@@ -203,7 +215,8 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params)
WGL_ALPHA_BITS_ARB,(params.Bits==32) ? 8 : 1, WGL_ALPHA_BITS_ARB,(params.Bits==32) ? 8 : 1,
WGL_DEPTH_BITS_ARB,params.ZBufferBits, WGL_DEPTH_BITS_ARB,params.ZBufferBits,
WGL_STENCIL_BITS_ARB,(params.Stencilbuffer) ? 1 : 0, WGL_STENCIL_BITS_ARB,(params.Stencilbuffer) ? 1 : 0,
WGL_DOUBLE_BUFFER_ARB,GL_TRUE, WGL_DOUBLE_BUFFER_ARB,(params.Doublebuffer) ? GL_TRUE : GL_FALSE,
WGL_STEREO_ARB,(params.Stereobuffer) ? GL_TRUE : GL_FALSE,
WGL_SAMPLE_BUFFERS_ARB, 1, WGL_SAMPLE_BUFFERS_ARB, 1,
WGL_SAMPLES_ARB,AntiAlias, WGL_SAMPLES_ARB,AntiAlias,
0,0 0,0
...@@ -353,7 +366,10 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, ...@@ -353,7 +366,10 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params,
: CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(),
CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true),
AntiAlias(params.AntiAlias), RenderTargetTexture(0), AntiAlias(params.AntiAlias), RenderTargetTexture(0),
CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), _device(device) CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8),
CurrentTarget(ERT_FRAME_BUFFER),
Doublebuffer(params.Doublebuffer), Stereo(params.Stereobuffer),
_device(device)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("COpenGLDriver"); setDebugName("COpenGLDriver");
...@@ -373,7 +389,9 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, ...@@ -373,7 +389,9 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params,
: CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(),
CurrentRenderMode(ERM_NONE), ResetRenderStates(true), CurrentRenderMode(ERM_NONE), ResetRenderStates(true),
Transformation3DChanged(true), AntiAlias(params.AntiAlias), Transformation3DChanged(true), AntiAlias(params.AntiAlias),
RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8) RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8),
CurrentTarget(ERT_FRAME_BUFFER),
Doublebuffer(params.Doublebuffer), Stereo(params.Stereobuffer)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("COpenGLDriver"); setDebugName("COpenGLDriver");
...@@ -410,7 +428,9 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, ...@@ -410,7 +428,9 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params,
: CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(),
CurrentRenderMode(ERM_NONE), ResetRenderStates(true), CurrentRenderMode(ERM_NONE), ResetRenderStates(true),
Transformation3DChanged(true), AntiAlias(params.AntiAlias), Transformation3DChanged(true), AntiAlias(params.AntiAlias),
RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8) RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8),
CurrentTarget(ERT_FRAME_BUFFER),
Doublebuffer(params.Doublebuffer), Stereo(params.Stereobuffer)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("COpenGLDriver"); setDebugName("COpenGLDriver");
...@@ -624,14 +644,10 @@ bool COpenGLDriver::endScene() ...@@ -624,14 +644,10 @@ bool COpenGLDriver::endScene()
} }
//! clears the zbuffer //! clears the zbuffer and color buffer
bool COpenGLDriver::beginScene(bool backBuffer, bool zBuffer, SColor color, void COpenGLDriver::clearBuffers(bool backBuffer, bool zBuffer, bool stencilBuffer, SColor color)
void* windowId, core::rect<s32>* sourceRect)
{ {
CNullDriver::beginScene(backBuffer, zBuffer, color, windowId, sourceRect);
GLbitfield mask = 0; GLbitfield mask = 0;
if (backBuffer) if (backBuffer)
{ {
const f32 inv = 1.0f / 255.0f; const f32 inv = 1.0f / 255.0f;
...@@ -648,7 +664,20 @@ bool COpenGLDriver::beginScene(bool backBuffer, bool zBuffer, SColor color, ...@@ -648,7 +664,20 @@ bool COpenGLDriver::beginScene(bool backBuffer, bool zBuffer, SColor color,
mask |= GL_DEPTH_BUFFER_BIT; mask |= GL_DEPTH_BUFFER_BIT;
} }
if (stencilBuffer)
mask |= GL_STENCIL_BUFFER_BIT;
glClear(mask); glClear(mask);
}
//! init call for rendering start
bool COpenGLDriver::beginScene(bool backBuffer, bool zBuffer, SColor color,
void* windowId, core::rect<s32>* sourceRect)
{
CNullDriver::beginScene(backBuffer, zBuffer, color, windowId, sourceRect);
clearBuffers(backBuffer, zBuffer, false, color);
return true; return true;
} }
...@@ -2622,8 +2651,7 @@ void COpenGLDriver::drawStencilShadow(bool clearStencilBuffer, video::SColor lef ...@@ -2622,8 +2651,7 @@ void COpenGLDriver::drawStencilShadow(bool clearStencilBuffer, video::SColor lef
glEnd(); glEnd();
if (clearStencilBuffer) clearBuffers(false, false, clearStencilBuffer, 0x0);
glClear(GL_STENCIL_BUFFER_BIT);
// restore settings // restore settings
glPopMatrix(); glPopMatrix();
...@@ -2853,6 +2881,53 @@ u32 COpenGLDriver::getMaximalPrimitiveCount() const ...@@ -2853,6 +2881,53 @@ 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("Fatal Error: For render textures call setRenderTarget with the actual texture as first parameter.", ELL_ERROR);
return false;
}
if (Stereo && (ERT_STEREO_RIGHT_BUFFER == target))
{
if (Doublebuffer)
glDrawBuffer(GL_BACK_RIGHT);
else
glDrawBuffer(GL_FRONT_RIGHT);
}
else if (Stereo && ERT_STEREO_BOTH_BUFFERS == target)
{
if (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 (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 //! set or reset render target
bool COpenGLDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer, bool COpenGLDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer,
bool clearZBuffer, SColor color) bool clearZBuffer, SColor color)
...@@ -2881,32 +2956,17 @@ bool COpenGLDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuff ...@@ -2881,32 +2956,17 @@ bool COpenGLDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuff
RenderTargetTexture = static_cast<COpenGLTexture*>(texture); RenderTargetTexture = static_cast<COpenGLTexture*>(texture);
RenderTargetTexture->bindRTT(); RenderTargetTexture->bindRTT();
CurrentRendertargetSize = texture->getSize(); CurrentRendertargetSize = texture->getSize();
CurrentTarget=ERT_RENDER_TEXTURE;
} }
else else
{ {
glViewport(0,0,ScreenSize.Width,ScreenSize.Height); glViewport(0,0,ScreenSize.Width,ScreenSize.Height);
RenderTargetTexture = 0; RenderTargetTexture = 0;
CurrentRendertargetSize = core::dimension2d<u32>(0,0); CurrentRendertargetSize = core::dimension2d<u32>(0,0);
CurrentTarget=ERT_FRAME_BUFFER;
} }
GLbitfield mask = 0; clearBuffers(clearBackBuffer, clearZBuffer, false, color);
if (clearBackBuffer)
{
const f32 inv = 1.0f / 255.0f;
glClearColor(color.getRed() * inv, color.getGreen() * inv,
color.getBlue() * inv, color.getAlpha() * inv);
mask |= GL_COLOR_BUFFER_BIT;
}
if (clearZBuffer)
{
glDepthMask(GL_TRUE);
LastMaterial.ZWriteEnable=true;
mask |= GL_DEPTH_BUFFER_BIT;
}
glClear(mask);
return true; return true;
} }
...@@ -2924,13 +2984,7 @@ const core::dimension2d<u32>& COpenGLDriver::getCurrentRenderTargetSize() const ...@@ -2924,13 +2984,7 @@ const core::dimension2d<u32>& COpenGLDriver::getCurrentRenderTargetSize() const
//! Clears the ZBuffer. //! Clears the ZBuffer.
void COpenGLDriver::clearZBuffer() void COpenGLDriver::clearZBuffer()
{ {
GLboolean enabled = GL_TRUE; clearBuffers(false, true, false, 0x0);
glGetBooleanv(GL_DEPTH_WRITEMASK, &enabled);
glDepthMask(GL_TRUE);
glClear(GL_DEPTH_BUFFER_BIT);
glDepthMask(enabled);
} }
......
...@@ -312,6 +312,11 @@ namespace video ...@@ -312,6 +312,11 @@ namespace video
virtual ITexture* addRenderTargetTexture(const core::dimension2d<u32>& size, virtual ITexture* addRenderTargetTexture(const core::dimension2d<u32>& size,
const c8* name); const c8* name);
//! set or reset render target
virtual bool setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget,
bool clearZBuffer, SColor color);
//! set or reset render target texture
virtual bool setRenderTarget(video::ITexture* texture, bool clearBackBuffer, virtual bool setRenderTarget(video::ITexture* texture, bool clearBackBuffer,
bool clearZBuffer, SColor color); bool clearZBuffer, SColor color);
...@@ -346,6 +351,9 @@ namespace video ...@@ -346,6 +351,9 @@ namespace video
private: private:
//! clears the zbuffer and color buffer
void clearBuffers(bool backBuffer, bool zBuffer, bool stencilBuffer, SColor color);
bool updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer); bool updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer);
bool updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer); bool updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer);
...@@ -414,6 +422,12 @@ namespace video ...@@ -414,6 +422,12 @@ namespace video
//! Color buffer format //! Color buffer format
ECOLOR_FORMAT ColorFormat; ECOLOR_FORMAT ColorFormat;
//! Render target type for render operations
E_RENDER_TARGET CurrentTarget;
bool Doublebuffer;
bool Stereo;
//! All the lights that have been requested; a hardware limited //! All the lights that have been requested; a hardware limited
//! number of them will be used at once. //! number of them will be used at once.
struct RequestedLight struct RequestedLight
......
...@@ -729,3 +729,4 @@ bool checkFBOStatus(COpenGLDriver* Driver) ...@@ -729,3 +729,4 @@ bool checkFBOStatus(COpenGLDriver* Driver)
} // end namespace irr } // end namespace irr
#endif // _IRR_COMPILE_WITH_OPENGL_ #endif // _IRR_COMPILE_WITH_OPENGL_
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