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:
parent
1bebe51c29
commit
76fc1a8f84
3 changed files with 89 additions and 24 deletions
|
@ -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());
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in a new issue