1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-03-28 20:36:42 +00:00

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

This commit is contained in:
Mads Buvik Sandvei 2020-12-10 21:29:56 +01:00
parent 1bebe51c29
commit 76fc1a8f84
3 changed files with 89 additions and 24 deletions

View file

@ -721,13 +721,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
// Create sound system // Create sound system
mEnvironment.setSoundManager (new MWSound::SoundManager(mVFS.get(), mUseSound)); 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. // VR mode will override this setting by setting mStereoOverride.
mStereoEnabled = mStereoOverride || Settings::Manager::getBool("stereo enabled", "Stereo"); mStereoEnabled = mStereoOverride || Settings::Manager::getBool("stereo enabled", "Stereo");
@ -736,6 +729,18 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
if (mStereoEnabled) if (mStereoEnabled)
{ {
mResourceSystem->getSceneManager()->getShaderManager().setStereoGeometryShaderEnabled(Misc::getStereoTechnique() == Misc::StereoView::Technique::GeometryShader_IndexedViewports); 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 // Create the world
@ -747,11 +752,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
// Set up stereo // Set up stereo
if (mStereoEnabled) if (mStereoEnabled)
{ {
// Mask in everything that does not currently use shaders. mStereoView->initializeScene();
// 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);
} }
window->setStore(mEnvironment.getWorld()->getStore()); window->setStore(mEnvironment.getWorld()->getStore());

View file

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

View file

@ -89,6 +89,8 @@ namespace Misc
GeometryShader_IndexedViewports, //!< Frustum camera culls and draws stereo into indexed viewports using an automatically generated geometry shader. 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. //! 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. //! 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. //! \param geometryShaderMask should mask in all nodes that use shaders.
@ -101,9 +103,21 @@ namespace Misc
void update(); void update();
void updateStateset(osg::StateSet* stateset); 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 //! Callback that updates stereo configuration during the update pass
void setUpdateViewCallback(std::shared_ptr<UpdateViewCallback> cb); 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: private:
void setupBruteForceTechnique(); void setupBruteForceTechnique();
void setupGeometryShaderIndexedViewportTechnique(); void setupGeometryShaderIndexedViewportTechnique();