Stereo now initializes before anything is drawn. Added option to add initial/pre/post draw callbacks to stereo.

pull/615/head
Mads Buvik Sandvei 4 years ago
parent 1bebe51c29
commit 76fc1a8f84

@ -721,13 +721,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
// Create sound system
mEnvironment.setSoundManager (new MWSound::SoundManager(mVFS.get(), mUseSound));
if (!mSkipMenu)
{
const std::string& logo = Fallback::Map::getString("Movies_Company_Logo");
if (!logo.empty())
window->playVideo(logo, true);
}
// VR mode will override this setting by setting mStereoOverride.
mStereoEnabled = mStereoOverride || Settings::Manager::getBool("stereo enabled", "Stereo");
@ -736,6 +729,18 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
if (mStereoEnabled)
{
mResourceSystem->getSceneManager()->getShaderManager().setStereoGeometryShaderEnabled(Misc::getStereoTechnique() == Misc::StereoView::Technique::GeometryShader_IndexedViewports);
// Mask in everything that does not currently use shaders.
// Remove that altogether when the sky finally uses them.
auto noShaderMask = MWRender::VisMask::Mask_Sky | MWRender::VisMask::Mask_Sun | MWRender::VisMask::Mask_WeatherParticles;
auto geometryShaderMask = mViewer->getCamera()->getCullMask() & ~noShaderMask;
mStereoView = new Misc::StereoView(mViewer, Misc::getStereoTechnique(), geometryShaderMask, noShaderMask | MWRender::VisMask::Mask_Scene);
}
if (!mSkipMenu)
{
const std::string& logo = Fallback::Map::getString("Movies_Company_Logo");
if (!logo.empty())
window->playVideo(logo, true);
}
// Create the world
@ -747,11 +752,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
// Set up stereo
if (mStereoEnabled)
{
// Mask in everything that does not currently use shaders.
// Remove that altogether when the sky finally uses them.
auto noShaderMask = MWRender::VisMask::Mask_Sky | MWRender::VisMask::Mask_Sun | MWRender::VisMask::Mask_WeatherParticles;
auto geometryShaderMask = mViewer->getCamera()->getCullMask() & ~noShaderMask;
mStereoView = new Misc::StereoView(mViewer, Misc::getStereoTechnique(), geometryShaderMask, noShaderMask | MWRender::VisMask::Mask_Scene);
mStereoView->initializeScene();
}
window->setStore(mEnvironment.getWorld()->getStore());

@ -9,6 +9,8 @@
#include <osgViewer/Viewer>
#include <iostream>
#include <map>
#include <string>
#include <components/debug/debuglog.hpp>
@ -225,11 +227,18 @@ namespace Misc
StereoView* stereoView;
};
StereoView* sInstance = nullptr;
StereoView& StereoView::instance()
{
return *sInstance;
}
StereoView::StereoView(osgViewer::Viewer* viewer, Technique technique, osg::Node::NodeMask geometryShaderMask, osg::Node::NodeMask noShaderMask)
: osg::Group()
, mViewer(viewer)
, mMainCamera(mViewer->getCamera())
, mRoot(viewer->getSceneData()->asGroup())
, mRoot(mViewer->getSceneData()->asGroup())
, mTechnique(technique)
, mGeometryShaderMask(geometryShaderMask)
, mNoShaderMask(noShaderMask)
@ -241,19 +250,14 @@ namespace Misc
// Do nothing
return;
mRoot->setDataVariance(osg::Object::STATIC);
mMasterConfig->_id = "STEREO";
mMasterConfig->_master = true;
mSlaveConfig->_id = "STEREO";
mSlaveConfig->_master = false;
SceneUtil::FindByNameVisitor findScene("Scene Root");
mRoot->accept(findScene);
mScene = findScene.mFoundNode;
if (!mScene)
throw std::logic_error("Couldn't find scene root");
setName("Stereo Root");
mRoot->setDataVariance(osg::Object::STATIC);
setDataVariance(osg::Object::STATIC);
mLeftCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
mLeftCamera->setProjectionResizePolicy(osg::Camera::FIXED);
@ -287,6 +291,10 @@ namespace Misc
{
setupBruteForceTechnique();
}
if (sInstance)
throw std::logic_error("Double instance og StereoView");
sInstance = this;
}
void StereoView::setupBruteForceTechnique()
@ -313,8 +321,8 @@ namespace Misc
mRightCamera->setViewport(width / 2, 0, width / 2, height);
mViewer->stopThreading();
mViewer->addSlave(mLeftCamera, true);
mViewer->addSlave(mRightCamera, true);
mViewer->addSlave(mLeftCamera, true);
mRightCamera->setGraphicsContext(mViewer->getCamera()->getGraphicsContext());
mLeftCamera->setGraphicsContext(mViewer->getCamera()->getGraphicsContext());
mViewer->getCamera()->setGraphicsContext(nullptr);
@ -332,16 +340,14 @@ namespace Misc
mMainCamera->setCullMask(mGeometryShaderMask);
addChild(mStereoGeometryShaderRoot);
mStereoGeometryShaderRoot->addChild(mRoot);
addChild(mStereoBruteForceRoot);
mStereoBruteForceRoot->addChild(mLeftCamera);
mLeftCamera->addChild(mScene); // Use scene directly to avoid redundant shadow computation.
mStereoBruteForceRoot->addChild(mRightCamera);
mRightCamera->addChild(mScene);
addCullCallback(new StereoStatesetUpdateCallback(this));
// Inject self as the root of the scene graph
mStereoGeometryShaderRoot->addChild(mRoot);
mViewer->setSceneData(this);
}
@ -494,6 +500,21 @@ namespace Misc
cb = cb_;
}
void StereoView::initializeScene()
{
SceneUtil::FindByNameVisitor findScene("Scene Root");
mRoot->accept(findScene);
mScene = findScene.mFoundNode;
if (!mScene)
throw std::logic_error("Couldn't find scene root");
if (mTechnique == Technique::GeometryShader_IndexedViewports)
{
mLeftCamera->addChild(mScene); // Use scene directly to avoid redundant shadow computation.
mRightCamera->addChild(mScene);
}
}
void disableStereoForCamera(osg::Camera* camera)
{
auto* viewport = camera->getViewport();
@ -553,4 +574,33 @@ namespace Misc
near = 1;
far = 6656;
}
void StereoView::setInitialDrawCallback(osg::ref_ptr<osg::Camera::DrawCallback> cb)
{
mMainCamera->setInitialDrawCallback(cb);
}
void StereoView::setPredrawCallback(osg::ref_ptr<osg::Camera::DrawCallback> cb)
{
if (mTechnique == Technique::GeometryShader_IndexedViewports)
{
mMainCamera->setPreDrawCallback(cb);
}
else
{
mLeftCamera->setPreDrawCallback(cb);
}
}
void StereoView::setPostdrawCallback(osg::ref_ptr<osg::Camera::DrawCallback> cb)
{
if (mTechnique == Technique::GeometryShader_IndexedViewports)
{
mMainCamera->setPostDrawCallback(cb);
}
else
{
mRightCamera->setPostDrawCallback(cb);
}
}
}

@ -89,6 +89,8 @@ namespace Misc
GeometryShader_IndexedViewports, //!< Frustum camera culls and draws stereo into indexed viewports using an automatically generated geometry shader.
};
static StereoView& instance();
//! Adds two cameras in stereo to the mainCamera.
//! All nodes matching the mask are rendered in stereo using brute force via two camera transforms, the rest are rendered in stereo via a geometry shader.
//! \param geometryShaderMask should mask in all nodes that use shaders.
@ -101,9 +103,21 @@ namespace Misc
void update();
void updateStateset(osg::StateSet* stateset);
//! Initialized scene. Call when the "scene root" node has been created
void initializeScene();
//! Callback that updates stereo configuration during the update pass
void setUpdateViewCallback(std::shared_ptr<UpdateViewCallback> cb);
//! Set the initial draw callback on the appropriate camera object
void setInitialDrawCallback(osg::ref_ptr<osg::Camera::DrawCallback> cb);
//! Set the predraw callback on the appropriate camera object
void setPredrawCallback(osg::ref_ptr<osg::Camera::DrawCallback> cb);
//! Set the postdraw callback on the appropriate camera object
void setPostdrawCallback(osg::ref_ptr<osg::Camera::DrawCallback> cb);
private:
void setupBruteForceTechnique();
void setupGeometryShaderIndexedViewportTechnique();

Loading…
Cancel
Save