mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-29 16:36:43 +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
|
||||
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…
Reference in a new issue