diff --git a/include/osg/DisplaySettings b/include/osg/DisplaySettings index 8db376836..d7cedaa54 100644 --- a/include/osg/DisplaySettings +++ b/include/osg/DisplaySettings @@ -94,7 +94,8 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced LEFT_EYE, RIGHT_EYE, HORIZONTAL_INTERLACE, - VERTICAL_INTERLACE + VERTICAL_INTERLACE, + CHECKERBOARD }; void setStereoMode(StereoMode mode) { _stereoMode = mode; } diff --git a/src/osg/DisplaySettings.cpp b/src/osg/DisplaySettings.cpp index 95e460f2e..2bc9466fd 100644 --- a/src/osg/DisplaySettings.cpp +++ b/src/osg/DisplaySettings.cpp @@ -230,6 +230,10 @@ void DisplaySettings::readEnvironmentalVariables() { _stereoMode = VERTICAL_INTERLACE; } + else if (strcmp(ptr,"CHECKERBOARD")==0) + { + _stereoMode = CHECKERBOARD; + } } if( (ptr = getenv("OSG_STEREO")) != 0) @@ -357,7 +361,7 @@ void DisplaySettings::readCommandLine(ArgumentParser& arguments) { arguments.getApplicationUsage()->addCommandLineOption("--display ","MONITOR | POWERWALL | REALITY_CENTER | HEAD_MOUNTED_DISPLAY"); arguments.getApplicationUsage()->addCommandLineOption("--stereo","Use default stereo mode which is ANAGLYPHIC if not overriden by environmental variable"); - arguments.getApplicationUsage()->addCommandLineOption("--stereo ","ANAGLYPHIC | QUAD_BUFFER | HORIZONTAL_SPLIT | VERTICAL_SPLIT | LEFT_EYE | RIGHT_EYE | ON | OFF "); + arguments.getApplicationUsage()->addCommandLineOption("--stereo ","ANAGLYPHIC | QUAD_BUFFER | HORIZONTAL_SPLIT | VERTICAL_SPLIT | LEFT_EYE | RIGHT_EYE | HORIZONTAL_INTERLACE | VERTICAL_INTERLACE | CHECKERBOARD | ON | OFF "); arguments.getApplicationUsage()->addCommandLineOption("--rgba","Request a RGBA color buffer visual"); arguments.getApplicationUsage()->addCommandLineOption("--stencil","Request a stencil buffer visual"); arguments.getApplicationUsage()->addCommandLineOption("--accum-rgb","Request a rgb accumulator buffer visual"); @@ -385,6 +389,7 @@ void DisplaySettings::readCommandLine(ArgumentParser& arguments) else if (arguments.match(pos+1,"VERTICAL_SPLIT")) { arguments.remove(pos,2); _stereo = true;_stereoMode = VERTICAL_SPLIT; } else if (arguments.match(pos+1,"HORIZONTAL_INTERLACE")) { arguments.remove(pos,2); _stereo = true;_stereoMode = HORIZONTAL_INTERLACE; } else if (arguments.match(pos+1,"VERTICAL_INTERLACE")) { arguments.remove(pos,2); _stereo = true;_stereoMode = VERTICAL_INTERLACE; } + else if (arguments.match(pos+1,"CHECKERBOARD")) { arguments.remove(pos,2); _stereo = true;_stereoMode = CHECKERBOARD; } else if (arguments.match(pos+1,"LEFT_EYE")) { arguments.remove(pos,2); _stereo = true;_stereoMode = LEFT_EYE; } else if (arguments.match(pos+1,"RIGHT_EYE")) { arguments.remove(pos,2); _stereo = true;_stereoMode = RIGHT_EYE; } else if (arguments.match(pos+1,"ON")) { arguments.remove(pos,2); _stereo = true; } diff --git a/src/osgUtil/SceneView.cpp b/src/osgUtil/SceneView.cpp index 3240bda95..2de213038 100644 --- a/src/osgUtil/SceneView.cpp +++ b/src/osgUtil/SceneView.cpp @@ -84,8 +84,44 @@ static const GLubyte patternHorzEven[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}; -SceneView::SceneView(DisplaySettings* ds): - osg::Object(true) +// 32 x 32 bit array every row is a horizontal line of pixels +// and the (bitwise) columns a vertical line +// The following is a checkerboard pattern +static const GLubyte patternCheckerboard[] = { + 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, + 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, + 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, + 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, + 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, + 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, + 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, + 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, + 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, + 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, + 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, + 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, + 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, + 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, + 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, + 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA}; + +SceneView::SceneView(DisplaySettings* ds) { _displaySettings = ds; @@ -132,16 +168,8 @@ SceneView::SceneView(const SceneView& rhs, const osg::CopyOp& copyop): _prioritizeTextures = rhs._prioritizeTextures; - if (rhs._camera.valid()) - { - setCamera(new osg::Camera(*rhs._camera,copyop), rhs._camera.get()==rhs._cameraWithOwnership.get()); - } - else - { - setCamera(new Camera); - _camera->setViewport(new Viewport); - _camera->setClearColor(osg::Vec4(0.2f, 0.2f, 0.4f, 1.0f)); - } + _camera = rhs._camera; + _cameraWithOwnership = rhs._cameraWithOwnership; _initCalled = false; @@ -1308,6 +1336,83 @@ void SceneView::draw() glDisable(GL_STENCIL_TEST); } break; + case(osg::DisplaySettings::CHECKERBOARD): + { + if( getDrawBufferValue() != GL_NONE) + { + _renderStageLeft->setDrawBuffer(getDrawBufferValue()); + _renderStageLeft->setReadBuffer(getDrawBufferValue()); + _renderStageRight->setDrawBuffer(getDrawBufferValue()); + _renderStageRight->setReadBuffer(getDrawBufferValue()); + } + _localStateSet->setAttribute(getViewport()); + + // ensure that all color planes are active. + osg::ColorMask* cmask = static_cast(_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(_renderInfo,previous); + _renderStageRight->drawPreRenderStages(_renderInfo,previous); + + glEnable(GL_STENCIL_TEST); + + if(_redrawInterlacedStereoStencilMask || + _interlacedStereoStencilWidth != getViewport()->width() || + _interlacedStereoStencilHeight != getViewport()->height() ) + { + getViewport()->apply(*state); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(getViewport()->x(), getViewport()->width(), getViewport()->y(), getViewport()->height(), -1.0, 1.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + glStencilMask(~0u); + glClear(GL_STENCIL_BUFFER_BIT); + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + glStencilFunc(GL_ALWAYS, 1, ~0u); + glPolygonStipple(patternCheckerboard); + glEnable(GL_POLYGON_STIPPLE); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + glRecti(static_cast(getViewport()->x()), + static_cast(getViewport()->y()), + static_cast(getViewport()->width()), + static_cast(getViewport()->height()) ); + + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDisable(GL_POLYGON_STIPPLE); + glEnable(GL_LIGHTING); + glEnable(GL_DEPTH_TEST); + + _redrawInterlacedStereoStencilMask = false; + _interlacedStereoStencilWidth = static_cast(getViewport()->width()); + _interlacedStereoStencilHeight = static_cast(getViewport()->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, ~0u); + _renderStageLeft->draw(_renderInfo,previous); + + glStencilFunc(GL_NOTEQUAL, 0, ~0u); + _renderStageRight->draw(_renderInfo,previous); + glDisable(GL_STENCIL_TEST); + } + break; default: { osg::notify(osg::NOTICE)<<"Warning: stereo mode not implemented yet."<< std::endl; diff --git a/src/osgViewer/View.cpp b/src/osgViewer/View.cpp index 13ccfe9ec..a7914f8a3 100644 --- a/src/osgViewer/View.cpp +++ b/src/osgViewer/View.cpp @@ -370,6 +370,7 @@ void View::setUpViewAcrossAllScreens() { case(osg::DisplaySettings::QUAD_BUFFER): traits->quadBufferStereo = true; break; case(osg::DisplaySettings::VERTICAL_INTERLACE): + case(osg::DisplaySettings::CHECKERBOARD): case(osg::DisplaySettings::HORIZONTAL_INTERLACE): traits->stencil = 8; break; default: break; } @@ -450,6 +451,7 @@ void View::setUpViewAcrossAllScreens() { case(osg::DisplaySettings::QUAD_BUFFER): traits->quadBufferStereo = true; break; case(osg::DisplaySettings::VERTICAL_INTERLACE): + case(osg::DisplaySettings::CHECKERBOARD): case(osg::DisplaySettings::HORIZONTAL_INTERLACE): traits->stencil = 8; break; default: break; } @@ -529,6 +531,7 @@ void View::setUpViewInWindow(int x, int y, int width, int height, unsigned int s { case(osg::DisplaySettings::QUAD_BUFFER): traits->quadBufferStereo = true; break; case(osg::DisplaySettings::VERTICAL_INTERLACE): + case(osg::DisplaySettings::CHECKERBOARD): case(osg::DisplaySettings::HORIZONTAL_INTERLACE): traits->stencil = 8; break; default: break; } @@ -610,6 +613,7 @@ void View::setUpViewOnSingleScreen(unsigned int screenNum) { case(osg::DisplaySettings::QUAD_BUFFER): traits->quadBufferStereo = true; break; case(osg::DisplaySettings::VERTICAL_INTERLACE): + case(osg::DisplaySettings::CHECKERBOARD): case(osg::DisplaySettings::HORIZONTAL_INTERLACE): traits->stencil = 8; break; default: break; } diff --git a/src/osgWrappers/osg/DisplaySettings.cpp b/src/osgWrappers/osg/DisplaySettings.cpp index 2aa3d1554..e89257a92 100644 --- a/src/osgWrappers/osg/DisplaySettings.cpp +++ b/src/osgWrappers/osg/DisplaySettings.cpp @@ -39,6 +39,7 @@ BEGIN_ENUM_REFLECTOR(osg::DisplaySettings::StereoMode) I_EnumLabel(osg::DisplaySettings::RIGHT_EYE); I_EnumLabel(osg::DisplaySettings::HORIZONTAL_INTERLACE); I_EnumLabel(osg::DisplaySettings::VERTICAL_INTERLACE); + I_EnumLabel(osg::DisplaySettings::CHECKERBOARD); END_REFLECTOR BEGIN_ENUM_REFLECTOR(osg::DisplaySettings::SplitStereoHorizontalEyeMapping)