diff --git a/apps/openmw/mwvr/vrshadow.cpp b/apps/openmw/mwvr/vrshadow.cpp index 7431d2ae4..8a8f06ef7 100644 --- a/apps/openmw/mwvr/vrshadow.cpp +++ b/apps/openmw/mwvr/vrshadow.cpp @@ -10,12 +10,8 @@ namespace MWVR { - VrShadow::VrShadow(osgViewer::Viewer* viewer, int renderOrder) - : mViewer(viewer) - , mRenderOrder(renderOrder) - , mShadowMapCamera(nullptr) - , mUpdateCallback(new UpdateShadowMapSlaveCallback) - , mMasterConfig(new SharedShadowMapConfig) + VrShadow::VrShadow() + : mMasterConfig(new SharedShadowMapConfig) , mSlaveConfig(new SharedShadowMapConfig) { mMasterConfig->_id = "VR"; @@ -24,51 +20,16 @@ namespace MWVR mSlaveConfig->_master = false; } - void VrShadow::configureShadowsForCamera(osg::Camera* camera) + void VrShadow::configureShadowsForCamera(osg::Camera* camera, bool master) { - camera->setUserData(mSlaveConfig); - if (camera->getRenderOrderNum() < mRenderOrder) - camera->setRenderOrder(camera->getRenderOrder(), mRenderOrder + 1); - } - - void VrShadow::configureShadows(bool enabled) - { - if (enabled) - { - if (!mShadowMapCamera) - { - mShadowMapCamera = new osg::Camera(); - mShadowMapCamera->setName("ShadowMap"); - mShadowMapCamera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - mShadowMapCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); - mShadowMapCamera->setRenderOrder(osg::Camera::PRE_RENDER, mRenderOrder); - mShadowMapCamera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR); - mShadowMapCamera->setAllowEventFocus(false); - mShadowMapCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); - mShadowMapCamera->setViewport(0, 0, 640, 360); - mShadowMapCamera->setGraphicsContext(mViewer->getCamera()->getGraphicsContext()); - mShadowMapCamera->setCullMask(0); - mShadowMapCamera->setUserData(mMasterConfig); - mViewer->addSlave(mShadowMapCamera, true); - auto* slave = mViewer->findSlaveForCamera(mShadowMapCamera); - assert(slave); - slave->_updateSlaveCallback = mUpdateCallback; - } - - } + if(master) + camera->setUserData(mMasterConfig); else - { - if (mShadowMapCamera) - { - mViewer->removeSlave(mViewer->findSlaveIndexForCamera(mShadowMapCamera)); - mShadowMapCamera = nullptr; - } - } + camera->setUserData(mSlaveConfig); } - void UpdateShadowMapSlaveCallback::updateSlave(osg::View& view, osg::View::Slave& slave) + void VrShadow::updateShadowConfig(osg::View& view) { - auto* camera = slave._camera.get(); auto* session = Environment::get().getSession(); auto viewMatrix = view.getCamera()->getViewMatrix(); @@ -104,8 +65,12 @@ namespace MWVR auto modifiedViewMatrix = viewMatrix * session->viewMatrix(P, osg::Quat(0, 0, 0, 1)); auto projectionMatrix = fov.perspectiveMatrix(near_, far_); - camera->setViewMatrix(modifiedViewMatrix); - camera->setProjectionMatrix(projectionMatrix); - slave.updateSlaveImplementation(view); + if (mMasterConfig->_projection == nullptr) + mMasterConfig->_projection = new osg::RefMatrix; + if (mMasterConfig->_modelView == nullptr) + mMasterConfig->_modelView = new osg::RefMatrix; + mMasterConfig->_referenceFrame = view.getCamera()->getReferenceFrame(); + mMasterConfig->_modelView->set(modifiedViewMatrix); + mMasterConfig->_projection->set(projectionMatrix); } } diff --git a/apps/openmw/mwvr/vrshadow.hpp b/apps/openmw/mwvr/vrshadow.hpp index c619b2703..1d79d1849 100644 --- a/apps/openmw/mwvr/vrshadow.hpp +++ b/apps/openmw/mwvr/vrshadow.hpp @@ -19,17 +19,13 @@ namespace MWVR { using SharedShadowMapConfig = SceneUtil::MWShadowTechnique::SharedShadowMapConfig; public: - VrShadow(osgViewer::Viewer* viewer, int renderOrder = 0); + VrShadow(); - void configureShadowsForCamera(osg::Camera* camera); + void configureShadowsForCamera(osg::Camera* camera, bool master); - void configureShadows(bool enabled); + void updateShadowConfig(osg::View& view); private: - osgViewer::Viewer* mViewer; - int mRenderOrder; - osg::ref_ptr mShadowMapCamera; - osg::ref_ptr< UpdateShadowMapSlaveCallback > mUpdateCallback; osg::ref_ptr mMasterConfig; osg::ref_ptr mSlaveConfig; }; diff --git a/apps/openmw/mwvr/vrview.cpp b/apps/openmw/mwvr/vrview.cpp index 7abd9c33b..8f0ec4672 100644 --- a/apps/openmw/mwvr/vrview.cpp +++ b/apps/openmw/mwvr/vrview.cpp @@ -78,9 +78,22 @@ namespace MWVR { void VRView::UpdateSlaveCallback::updateSlave( osg::View& view, osg::View::Slave& slave) + { + mView->updateSlave(view, slave); + } + + void VRView::postrenderCallback(osg::RenderInfo& renderInfo) + { + auto name = renderInfo.getCurrentCamera()->getName(); + } + + void VRView::swapBuffers(osg::GraphicsContext* gc) + { + mSwapchain->endFrame(gc); + } + void VRView::updateSlave(osg::View& view, osg::View::Slave& slave) { auto* camera = slave._camera.get(); - auto name = camera->getName(); // Update current cached cull mask of camera if it is active auto mask = camera->getCullMask(); @@ -89,17 +102,23 @@ namespace MWVR { else mCullMask = mask; + // If the session is not active, we do not want to waste resources rendering frames. if (Environment::get().getSession()->getFrame(VRSession::FramePhase::Update)->mShouldRender) { Side side = Side::RIGHT_SIDE; - if (name == "LeftEye") + if (mName == "LeftEye") + { + + Environment::get().getViewer()->vrShadow().updateShadowConfig(view); side = Side::LEFT_SIDE; + } auto* session = Environment::get().getSession(); auto viewMatrix = view.getCamera()->getViewMatrix(); - bool haveView = viewMatrix.getTrans().length() > 0.01; + // During main menu the view matrix will not be set, + // in that case we use the vr stage directly instead. if (haveView) { viewMatrix = viewMatrix * session->viewMatrix(VRSession::FramePhase::Update, side, true); @@ -115,19 +134,8 @@ namespace MWVR { } else { - // If the session is not active, we do not want to waste resources rendering frames. camera->setCullMask(0); } slave.updateSlaveImplementation(view); } - - void VRView::postrenderCallback(osg::RenderInfo& renderInfo) - { - auto name = renderInfo.getCurrentCamera()->getName(); - } - - void VRView::swapBuffers(osg::GraphicsContext* gc) - { - mSwapchain->endFrame(gc); - } } diff --git a/apps/openmw/mwvr/vrview.hpp b/apps/openmw/mwvr/vrview.hpp index 0d17b63a6..4a18ffb57 100644 --- a/apps/openmw/mwvr/vrview.hpp +++ b/apps/openmw/mwvr/vrview.hpp @@ -9,6 +9,8 @@ struct XrSwapchainSubImage; namespace MWVR { + class VRViewer; + /// \brief Manipulates a slave camera by replacing its framebuffer with one destined for openxr class VRView : public osg::Referenced { @@ -23,11 +25,11 @@ namespace MWVR class UpdateSlaveCallback : public osg::View::Slave::UpdateSlaveCallback { public: + UpdateSlaveCallback(osg::ref_ptr view) : mView(view) {} void updateSlave(osg::View& view, osg::View::Slave& slave) override; private: osg::ref_ptr mView; - osg::Node::NodeMask mCullMask; }; public: @@ -37,19 +39,25 @@ namespace MWVR public: //! Prepare for render (set FBO) virtual void prerenderCallback(osg::RenderInfo& renderInfo); + //! Finalize render virtual void postrenderCallback(osg::RenderInfo& renderInfo); + //! Create camera for this view osg::Camera* createCamera(int order, const osg::Vec4& clearColor, osg::GraphicsContext* gc); + //! Get the view surface OpenXRSwapchain& swapchain(void) { return *mSwapchain; } + //! Present to the openxr swapchain void swapBuffers(osg::GraphicsContext* gc); + void updateSlave(osg::View& view, osg::View::Slave& slave); public: SwapchainConfig mSwapchainConfig; std::unique_ptr mSwapchain; std::string mName{}; + osg::Node::NodeMask mCullMask; bool mRendering{ false }; }; } diff --git a/apps/openmw/mwvr/vrviewer.cpp b/apps/openmw/mwvr/vrviewer.cpp index 823e47aff..bae9da7a6 100644 --- a/apps/openmw/mwvr/vrviewer.cpp +++ b/apps/openmw/mwvr/vrviewer.cpp @@ -36,7 +36,7 @@ namespace MWVR : mViewer(viewer) , mPreDraw(new PredrawCallback(this)) , mPostDraw(new PostdrawCallback(this)) - , mVrShadow(viewer, 1) + , mVrShadow() , mConfigured(false) { mViewer->setRealizeOperation(new RealizeOperation()); @@ -90,8 +90,6 @@ namespace MWVR // TODO: If mirror is false either hide the window or paste something meaningful into it. // E.g. Fanart of Dagoth UR wearing a VR headset - mVrShadow.configureShadows(Settings::Manager::getBool("enable shadows", "Shadows")); - for (unsigned i = 0; i < sViewNames.size(); i++) { auto view = new VRView(sViewNames[i], config[i], context->getState()); @@ -106,8 +104,7 @@ namespace MWVR camera->setCullingMode(cullingMode); mViewer->addSlave(camera, true); auto* slave = mViewer->findSlaveForCamera(camera); - assert(slave); - slave->_updateSlaveCallback = new VRView::UpdateSlaveCallback(); + slave->_updateSlaveCallback = new VRView::UpdateSlaveCallback(view); if (mirror) mMsaaResolveMirrorTexture[i].reset(new VRFramebuffer(context->getState(), @@ -115,7 +112,7 @@ namespace MWVR view->swapchain().height(), 0)); - mVrShadow.configureShadowsForCamera(camera); + mVrShadow.configureShadowsForCamera(camera, i == 0); } if (mirror) diff --git a/apps/openmw/mwvr/vrviewer.hpp b/apps/openmw/mwvr/vrviewer.hpp index d29aad35a..8cca6e3d3 100644 --- a/apps/openmw/mwvr/vrviewer.hpp +++ b/apps/openmw/mwvr/vrviewer.hpp @@ -80,6 +80,7 @@ namespace MWVR void realize(osg::GraphicsContext* gc); bool realized() { return mConfigured; } VRView* getView(std::string name); + VrShadow& vrShadow() { return mVrShadow; } void enableMainCamera(void); void disableMainCamera(void);