From Farshid Lashkari & Robert Osfield: Added support for VERTICAL_INTERLACE and HORIZONTAL_INTERLACE
stereo modes use the stencil buffer.
This commit is contained in:
@@ -90,7 +90,9 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced
|
||||
HORIZONTAL_SPLIT,
|
||||
VERTICAL_SPLIT,
|
||||
LEFT_EYE,
|
||||
RIGHT_EYE
|
||||
RIGHT_EYE,
|
||||
HORIZONTAL_INTERLACE,
|
||||
VERTICAL_INTERLACE
|
||||
};
|
||||
|
||||
void setStereoMode(StereoMode mode) { _stereoMode = mode; }
|
||||
|
||||
@@ -113,6 +113,13 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced, public osg::CullSetting
|
||||
void setClearColor(const osg::Vec4& color) { _clearColor=color; }
|
||||
/** Get the color used in glClearColor.*/
|
||||
const osg::Vec4& getClearColor() const { return _clearColor; }
|
||||
|
||||
|
||||
/** Mannually set the redraw interlaced stereo stencil mask request flag to control whether to redraw the stencil buffer on the next frame.*/
|
||||
void setRedrawInterlacedStereoStencilMask(bool flag) { _redrawInterlacedStereoStencilMask = flag; }
|
||||
|
||||
/** Get the redraw interlaced stereo stencil mask request flag.*/
|
||||
bool getRedrawInterlacedStereoStencilMask() const { return _redrawInterlacedStereoStencilMask; }
|
||||
|
||||
|
||||
void setGlobalStateSet(osg::StateSet* state) { _globalStateSet = state; }
|
||||
@@ -504,6 +511,11 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced, public osg::CullSetting
|
||||
int _activeUniforms;
|
||||
double _previousFrameTime;
|
||||
|
||||
bool _redrawInterlacedStereoStencilMask;
|
||||
int _interlacedStereoStencilWidth;
|
||||
int _interlacedStereoStencilHeight;
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ void DisplaySettings::setDefaults()
|
||||
}
|
||||
|
||||
static ApplicationUsageProxy DisplaySetting_e0(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_DISPLAY_TYPE <type>","MONITOR | POWERWALL | REALITY_CENTER | HEAD_MOUNTED_DISPLAY");
|
||||
static ApplicationUsageProxy DisplaySetting_e1(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_STEREO_MODE <mode>","QUAD_BUFFER | ANAGLYPHIC | HORIZONTAL_SPLIT | VERTICAL_SPLIT | LEFT_EYE | RIGHT_EYE");
|
||||
static ApplicationUsageProxy DisplaySetting_e1(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_STEREO_MODE <mode>","QUAD_BUFFER | ANAGLYPHIC | HORIZONTAL_SPLIT | VERTICAL_SPLIT | LEFT_EYE | RIGHT_EYE | VERTICAL_INTERLACE | HORIZONTAL_INTERLACE");
|
||||
static ApplicationUsageProxy DisplaySetting_e2(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_STEREO <mode>","OFF | ON");
|
||||
static ApplicationUsageProxy DisplaySetting_e3(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_EYE_SEPARATION <float>","physical distance between eyes");
|
||||
static ApplicationUsageProxy DisplaySetting_e4(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN_DISTANCE <float>","physical distance between eyes and screen");
|
||||
@@ -159,31 +159,34 @@ void DisplaySettings::readEnvironmentalVariables()
|
||||
{
|
||||
_stereoMode = QUAD_BUFFER;
|
||||
}
|
||||
else
|
||||
if (strcmp(ptr,"ANAGLYPHIC")==0)
|
||||
else if (strcmp(ptr,"ANAGLYPHIC")==0)
|
||||
{
|
||||
_stereoMode = ANAGLYPHIC;
|
||||
}
|
||||
else
|
||||
if (strcmp(ptr,"HORIZONTAL_SPLIT")==0)
|
||||
else if (strcmp(ptr,"HORIZONTAL_SPLIT")==0)
|
||||
{
|
||||
_stereoMode = HORIZONTAL_SPLIT;
|
||||
}
|
||||
else
|
||||
if (strcmp(ptr,"VERTICAL_SPLIT")==0)
|
||||
else if (strcmp(ptr,"VERTICAL_SPLIT")==0)
|
||||
{
|
||||
_stereoMode = VERTICAL_SPLIT;
|
||||
}
|
||||
else
|
||||
if (strcmp(ptr,"LEFT_EYE")==0)
|
||||
else if (strcmp(ptr,"LEFT_EYE")==0)
|
||||
{
|
||||
_stereoMode = LEFT_EYE;
|
||||
}
|
||||
else
|
||||
if (strcmp(ptr,"RIGHT_EYE")==0)
|
||||
else if (strcmp(ptr,"RIGHT_EYE")==0)
|
||||
{
|
||||
_stereoMode = RIGHT_EYE;
|
||||
}
|
||||
else if (strcmp(ptr,"HORIZONTAL_INTERLACE")==0)
|
||||
{
|
||||
_stereoMode = HORIZONTAL_INTERLACE;
|
||||
}
|
||||
else if (strcmp(ptr,"VERTICAL_INTERLACE")==0)
|
||||
{
|
||||
_stereoMode = VERTICAL_INTERLACE;
|
||||
}
|
||||
}
|
||||
|
||||
if( (ptr = getenv("OSG_STEREO")) != 0)
|
||||
|
||||
@@ -502,8 +502,31 @@ bool OsgCameraGroup::realize()
|
||||
rs_vc->setSimpleConfiguration();
|
||||
rs->setVisualChooser(rs_vc);
|
||||
}
|
||||
if (_ds->getStereo() && _ds->getStereoMode()==osg::DisplaySettings::QUAD_BUFFER) rs_vc->useStereo();
|
||||
if (_ds->getStencilBuffer()) rs_vc->setStencilSize(_ds->getMinimumNumStencilBits());
|
||||
|
||||
unsigned int numStencilBits = 0;
|
||||
if (_ds->getStereo())
|
||||
{
|
||||
switch(_ds->getStereoMode())
|
||||
{
|
||||
case(osg::DisplaySettings::QUAD_BUFFER):
|
||||
rs_vc->useStereo();
|
||||
break;
|
||||
case(osg::DisplaySettings::HORIZONTAL_INTERLACE):
|
||||
case(osg::DisplaySettings::VERTICAL_INTERLACE):
|
||||
numStencilBits = 8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// set up stencil buffer if required.
|
||||
numStencilBits = osg::maximum(numStencilBits,_ds->getMinimumNumStencilBits());
|
||||
if (numStencilBits > 0)
|
||||
{
|
||||
rs_vc->setStencilSize(numStencilBits);
|
||||
}
|
||||
|
||||
if (_ds->getAlphaBuffer()) rs_vc->setAlphaSize(_ds->getMinimumNumAlphaBits());
|
||||
|
||||
rs_vc->setDepthSize(24);
|
||||
|
||||
@@ -31,6 +31,60 @@
|
||||
using namespace osg;
|
||||
using namespace osgUtil;
|
||||
|
||||
static const GLubyte patternVertEven[] = {
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
|
||||
|
||||
static const GLubyte patternVertOdd[] = {
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
|
||||
|
||||
static const GLubyte patternHorzEven[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
SceneView::SceneView(DisplaySettings* ds)
|
||||
{
|
||||
_displaySettings = ds;
|
||||
@@ -57,6 +111,10 @@ SceneView::SceneView(DisplaySettings* ds)
|
||||
_activeUniforms = DEFAULT_UNIFORMS;
|
||||
|
||||
_previousFrameTime = 0;
|
||||
|
||||
_redrawInterlacedStereoStencilMask = true;
|
||||
_interlacedStereoStencilWidth = 0;
|
||||
_interlacedStereoStencilHeight = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -950,6 +1008,136 @@ void SceneView::draw()
|
||||
_renderStage->draw(*_state,previous);
|
||||
}
|
||||
break;
|
||||
case(osg::DisplaySettings::VERTICAL_INTERLACE):
|
||||
{
|
||||
_localStateSet->setAttribute(_viewport.get());
|
||||
|
||||
// ensure that all color planes are active.
|
||||
osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
|
||||
if (cmask)
|
||||
{
|
||||
cmask->setMask(true,true,true,true);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmask = new osg::ColorMask(true,true,true,true);
|
||||
_localStateSet->setAttribute(cmask);
|
||||
}
|
||||
_renderStageLeft->setColorMask(cmask);
|
||||
_renderStageRight->setColorMask(cmask);
|
||||
|
||||
_renderStageLeft->drawPreRenderStages(*_state,previous);
|
||||
_renderStageRight->drawPreRenderStages(*_state,previous);
|
||||
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
|
||||
if(_redrawInterlacedStereoStencilMask ||
|
||||
_interlacedStereoStencilWidth != _viewport->width() ||
|
||||
_interlacedStereoStencilHeight != _viewport->height() )
|
||||
{
|
||||
_viewport->apply(*_state);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(_viewport->x(), _viewport->width(), _viewport->y(), _viewport->height(), -1.0, 1.0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glStencilMask(~0);
|
||||
glClear(GL_STENCIL_BUFFER_BIT);
|
||||
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||
glStencilFunc(GL_ALWAYS, 1, ~0);
|
||||
glPolygonStipple(patternVertEven);
|
||||
glEnable(GL_POLYGON_STIPPLE);
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
glRecti(_viewport->x(), _viewport->y(), _viewport->width(), _viewport->height());
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glDisable(GL_POLYGON_STIPPLE);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
_redrawInterlacedStereoStencilMask = false;
|
||||
_interlacedStereoStencilWidth = _viewport->width();
|
||||
_interlacedStereoStencilHeight = _viewport->height();
|
||||
}
|
||||
|
||||
_renderStageLeft->setClearMask(_renderStageLeft->getClearMask() & ~(GL_STENCIL_BUFFER_BIT));
|
||||
_renderStageRight->setClearMask(_renderStageRight->getClearMask() & ~(GL_STENCIL_BUFFER_BIT|GL_COLOR_BUFFER_BIT));
|
||||
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
glStencilFunc(GL_EQUAL, 0, ~0);
|
||||
_renderStageLeft->draw(*_state,previous);
|
||||
|
||||
glStencilFunc(GL_NOTEQUAL, 0, ~0);
|
||||
_renderStageRight->draw(*_state,previous);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
}
|
||||
break;
|
||||
case(osg::DisplaySettings::HORIZONTAL_INTERLACE):
|
||||
{
|
||||
_localStateSet->setAttribute(_viewport.get());
|
||||
|
||||
// ensure that all color planes are active.
|
||||
osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
|
||||
if (cmask)
|
||||
{
|
||||
cmask->setMask(true,true,true,true);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmask = new osg::ColorMask(true,true,true,true);
|
||||
_localStateSet->setAttribute(cmask);
|
||||
}
|
||||
_renderStageLeft->setColorMask(cmask);
|
||||
_renderStageRight->setColorMask(cmask);
|
||||
|
||||
_renderStageLeft->drawPreRenderStages(*_state,previous);
|
||||
_renderStageRight->drawPreRenderStages(*_state,previous);
|
||||
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
|
||||
if(_redrawInterlacedStereoStencilMask ||
|
||||
_interlacedStereoStencilWidth != _viewport->width() ||
|
||||
_interlacedStereoStencilHeight != _viewport->height() )
|
||||
{
|
||||
_viewport->apply(*_state);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(_viewport->x(), _viewport->width(), _viewport->y(), _viewport->height(), -1.0, 1.0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glStencilMask(~0);
|
||||
glClear(GL_STENCIL_BUFFER_BIT);
|
||||
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||
glStencilFunc(GL_ALWAYS, 1, ~0);
|
||||
glPolygonStipple(patternHorzEven);
|
||||
glEnable(GL_POLYGON_STIPPLE);
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
glRecti(_viewport->x(), _viewport->y(), _viewport->width(), _viewport->height());
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glDisable(GL_POLYGON_STIPPLE);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
_redrawInterlacedStereoStencilMask = false;
|
||||
_interlacedStereoStencilWidth = _viewport->width();
|
||||
_interlacedStereoStencilHeight = _viewport->height();
|
||||
}
|
||||
|
||||
_renderStageLeft->setClearMask(_renderStageLeft->getClearMask() & ~(GL_STENCIL_BUFFER_BIT));
|
||||
_renderStageRight->setClearMask(_renderStageRight->getClearMask() & ~(GL_STENCIL_BUFFER_BIT|GL_COLOR_BUFFER_BIT));
|
||||
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
glStencilFunc(GL_EQUAL, 0, ~0);
|
||||
_renderStageLeft->draw(*_state,previous);
|
||||
|
||||
glStencilFunc(GL_NOTEQUAL, 0, ~0);
|
||||
_renderStageRight->draw(*_state,previous);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Warning: stereo mode not implemented yet."<< std::endl;
|
||||
|
||||
Reference in New Issue
Block a user