From Farshid Lashkari & Robert Osfield: Added support for VERTICAL_INTERLACE and HORIZONTAL_INTERLACE

stereo modes use the stencil buffer.
This commit is contained in:
Robert Osfield
2005-10-25 15:43:04 +00:00
parent e14262df85
commit f46044084a
5 changed files with 242 additions and 14 deletions

View File

@@ -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; }

View File

@@ -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;
};
}

View File

@@ -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)

View File

@@ -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);

View File

@@ -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;