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
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.
/** This interface is one of the most important interfaces of
the Irrlicht Engine: All rendering and texture manipulation is done with
......@@ -352,7 +375,22 @@ 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)) =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.
/** Every rendering operation is done into this new area.
......
......@@ -27,7 +27,9 @@ namespace irr
Vsync(false),
AntiAlias(0),
WithAlphaChannel(false),
Doublebuffer(true),
IgnoreInput(false),
Stereobuffer(false),
HighPrecisionFPU(false),
EventReceiver(0),
WindowId(0),
......@@ -50,7 +52,9 @@ namespace irr
Vsync = other.Vsync;
AntiAlias = other.AntiAlias;
WithAlphaChannel = other.WithAlphaChannel;
Doublebuffer = other.Doublebuffer;
IgnoreInput = other.IgnoreInput;
Stereobuffer = other.Stereobuffer;
HighPrecisionFPU = other.HighPrecisionFPU;
EventReceiver = other.EventReceiver;
WindowId = other.WindowId;
......@@ -120,13 +124,29 @@ namespace irr
Default value: false */
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
/** This is only relevant when using external I/O handlers.
External windows need to take care of this themselves.
Currently only supported under X11.
Currently only supported by X11.
Default value: false */
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
/** This is only relevant for DirectX Devices, which switch to
low FPU precision by default for performance reasons. However,
......
......@@ -310,10 +310,11 @@ bool CIrrDeviceLinux::createWindow()
GLX_BLUE_SIZE, 4,
GLX_ALPHA_SIZE, CreationParams.WithAlphaChannel?1:0,
GLX_DEPTH_SIZE, CreationParams.ZBufferBits,
GLX_DOUBLEBUFFER, GL_TRUE,
GLX_DOUBLEBUFFER, CreationParams.Doublebuffer?GL_TRUE:GL_FALSE,
GLX_STENCIL_SIZE, 1,
GLX_SAMPLE_BUFFERS_ARB, 1,
GLX_SAMPLES_ARB, CreationParams.AntiAlias,
GLX_STEREO, CreationParams.Stereobuffer?GL_TRUE:GL_FALSE,
None
};
......@@ -389,10 +390,11 @@ bool CIrrDeviceLinux::createWindow()
}
}
// Next try without double buffer
if (!configList)
if (!configList && CreationParams.Doublebuffer)
{
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);
if (!configList && CreationParams.AntiAlias)
{
......@@ -439,8 +441,9 @@ bool CIrrDeviceLinux::createWindow()
GLX_BLUE_SIZE, 4,
GLX_ALPHA_SIZE, CreationParams.WithAlphaChannel?1:0,
GLX_DEPTH_SIZE, CreationParams.ZBufferBits,
GLX_DOUBLEBUFFER, GL_TRUE,
GLX_DOUBLEBUFFER, CreationParams.Doublebuffer?GL_TRUE:GL_FALSE,
GLX_STENCIL_SIZE, 1,
GLX_STEREO, CreationParams.Stereobuffer?GL_TRUE:GL_FALSE,
None
};
......@@ -456,10 +459,11 @@ bool CIrrDeviceLinux::createWindow()
visualAttrBuffer[15]=0;
visual=glXChooseVisual(display, screennr, visualAttrBuffer);
if (!visual)
if (!visual && CreationParams.Doublebuffer)
{
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);
}
}
......@@ -475,6 +479,7 @@ bool CIrrDeviceLinux::createWindow()
// create visual with standard X methods
{
os::Printer::log("Using plain X visual");
XVisualInfo visTempl; //Template to hold requested values
int visNumber; // Return value of available visuals
......
......@@ -89,7 +89,7 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param)
SDL_Flags |= SDL_FULLSCREEN;
if (CreationParams.DriverType == video::EDT_OPENGL)
SDL_Flags |= SDL_OPENGL;
else
else if (CreationParams.Doublebuffer)
SDL_Flags |= SDL_DOUBLEBUF;
// create window
if (CreationParams.DriverType != video::EDT_NULL)
......@@ -147,7 +147,10 @@ bool CIrrDeviceSDL::createWindow()
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_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)
{
SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 1 );
......@@ -176,6 +179,12 @@ bool CIrrDeviceSDL::createWindow()
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 )
{
os::Printer::log( "Could not initialize display!" );
......
......@@ -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
bool CNullDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer,
......@@ -507,14 +517,12 @@ bool CNullDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer
}
//! sets a viewport
void CNullDriver::setViewPort(const core::rect<s32>& area)
{
}
//! gets the area of the current viewport
const core::rect<s32>& CNullDriver::getViewPort() const
{
......@@ -522,7 +530,6 @@ const core::rect<s32>& CNullDriver::getViewPort() const
}
//! 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)
{
......@@ -530,7 +537,6 @@ void CNullDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount,
}
//! draws an indexed triangle list
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
}
//! draws an indexed triangle list
inline void CNullDriver::drawIndexedTriangleList(const S3DVertex2TCoords* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount)
{
......
......@@ -89,6 +89,10 @@ namespace video
virtual bool setRenderTarget(video::ITexture* texture, bool clearBackBuffer,
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
virtual void setViewPort(const core::rect<s32>& area);
......
......@@ -36,7 +36,9 @@ COpenGLDriver::COpenGLDriver(const irr::SIrrlichtCreationParameters& params,
: CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(),
CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true),
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)
{
#ifdef _DEBUG
......@@ -47,13 +49,14 @@ COpenGLDriver::COpenGLDriver(const irr::SIrrlichtCreationParameters& params,
//! inits the open gl driver
bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params)
{
// Set up ixel format descriptor with desired parameters
// Set up pixel format descriptor with desired parameters
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
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
params.Bits, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
......@@ -150,6 +153,15 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params)
}
else
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);
ReleaseDC(temporary_wnd, HDc);
......@@ -190,8 +202,8 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params)
// improvement over 4, but 4 shows a big improvement
// over 2.
if(AntiAlias > 16)
AntiAlias = 16;
if(AntiAlias > 32)
AntiAlias = 32;
f32 fAttributes[] = {0.0, 0.0};
s32 iAttributes[] =
......@@ -203,7 +215,8 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params)
WGL_ALPHA_BITS_ARB,(params.Bits==32) ? 8 : 1,
WGL_DEPTH_BITS_ARB,params.ZBufferBits,
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_SAMPLES_ARB,AntiAlias,
0,0
......@@ -353,7 +366,10 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params,
: CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(),
CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true),
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
setDebugName("COpenGLDriver");
......@@ -373,7 +389,9 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params,
: CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(),
CurrentRenderMode(ERM_NONE), ResetRenderStates(true),
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
setDebugName("COpenGLDriver");
......@@ -410,7 +428,9 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params,
: CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(),
CurrentRenderMode(ERM_NONE), ResetRenderStates(true),
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
setDebugName("COpenGLDriver");
......@@ -624,14 +644,10 @@ bool COpenGLDriver::endScene()
}
//! clears the zbuffer
bool COpenGLDriver::beginScene(bool backBuffer, bool zBuffer, SColor color,
void* windowId, core::rect<s32>* sourceRect)
//! clears the zbuffer and color buffer
void COpenGLDriver::clearBuffers(bool backBuffer, bool zBuffer, bool stencilBuffer, SColor color)
{
CNullDriver::beginScene(backBuffer, zBuffer, color, windowId, sourceRect);
GLbitfield mask = 0;
if (backBuffer)
{
const f32 inv = 1.0f / 255.0f;
......@@ -648,7 +664,20 @@ bool COpenGLDriver::beginScene(bool backBuffer, bool zBuffer, SColor color,
mask |= GL_DEPTH_BUFFER_BIT;
}
if (stencilBuffer)
mask |= GL_STENCIL_BUFFER_BIT;
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;
}
......@@ -2622,8 +2651,7 @@ void COpenGLDriver::drawStencilShadow(bool clearStencilBuffer, video::SColor lef
glEnd();
if (clearStencilBuffer)
glClear(GL_STENCIL_BUFFER_BIT);
clearBuffers(false, false, clearStencilBuffer, 0x0);
// restore settings
glPopMatrix();
......@@ -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
bool COpenGLDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer,
bool clearZBuffer, SColor color)
......@@ -2881,32 +2956,17 @@ bool COpenGLDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuff
RenderTargetTexture = static_cast<COpenGLTexture*>(texture);
RenderTargetTexture->bindRTT();
CurrentRendertargetSize = texture->getSize();
CurrentTarget=ERT_RENDER_TEXTURE;
}
else
{
glViewport(0,0,ScreenSize.Width,ScreenSize.Height);
RenderTargetTexture = 0;
CurrentRendertargetSize = core::dimension2d<u32>(0,0);
CurrentTarget=ERT_FRAME_BUFFER;
}
GLbitfield mask = 0;
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);
clearBuffers(clearBackBuffer, clearZBuffer, false, color);
return true;
}
......@@ -2924,13 +2984,7 @@ const core::dimension2d<u32>& COpenGLDriver::getCurrentRenderTargetSize() const
//! Clears the ZBuffer.
void COpenGLDriver::clearZBuffer()
{
GLboolean enabled = GL_TRUE;
glGetBooleanv(GL_DEPTH_WRITEMASK, &enabled);
glDepthMask(GL_TRUE);
glClear(GL_DEPTH_BUFFER_BIT);
glDepthMask(enabled);
clearBuffers(false, true, false, 0x0);
}
......
......@@ -312,6 +312,11 @@ namespace video
virtual ITexture* addRenderTargetTexture(const core::dimension2d<u32>& size,
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,
bool clearZBuffer, SColor color);
......@@ -346,6 +351,9 @@ namespace video
private:
//! clears the zbuffer and color buffer
void clearBuffers(bool backBuffer, bool zBuffer, bool stencilBuffer, SColor color);
bool updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer);
bool updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer);
......@@ -414,6 +422,12 @@ namespace video
//! Color buffer format
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
//! number of them will be used at once.
struct RequestedLight
......
......@@ -729,3 +729,4 @@ bool checkFBOStatus(COpenGLDriver* Driver)
} // end namespace irr
#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