mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-21 23:09:39 +00:00
Single pass shadow update
This commit is contained in:
parent
a15188d3bc
commit
e0bc56dcf7
6 changed files with 52 additions and 77 deletions
|
@ -10,12 +10,8 @@
|
||||||
|
|
||||||
namespace MWVR
|
namespace MWVR
|
||||||
{
|
{
|
||||||
VrShadow::VrShadow(osgViewer::Viewer* viewer, int renderOrder)
|
VrShadow::VrShadow()
|
||||||
: mViewer(viewer)
|
: mMasterConfig(new SharedShadowMapConfig)
|
||||||
, mRenderOrder(renderOrder)
|
|
||||||
, mShadowMapCamera(nullptr)
|
|
||||||
, mUpdateCallback(new UpdateShadowMapSlaveCallback)
|
|
||||||
, mMasterConfig(new SharedShadowMapConfig)
|
|
||||||
, mSlaveConfig(new SharedShadowMapConfig)
|
, mSlaveConfig(new SharedShadowMapConfig)
|
||||||
{
|
{
|
||||||
mMasterConfig->_id = "VR";
|
mMasterConfig->_id = "VR";
|
||||||
|
@ -24,51 +20,16 @@ namespace MWVR
|
||||||
mSlaveConfig->_master = false;
|
mSlaveConfig->_master = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VrShadow::configureShadowsForCamera(osg::Camera* camera)
|
void VrShadow::configureShadowsForCamera(osg::Camera* camera, bool master)
|
||||||
{
|
{
|
||||||
camera->setUserData(mSlaveConfig);
|
if(master)
|
||||||
if (camera->getRenderOrderNum() < mRenderOrder)
|
camera->setUserData(mMasterConfig);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
camera->setUserData(mSlaveConfig);
|
||||||
if (mShadowMapCamera)
|
|
||||||
{
|
|
||||||
mViewer->removeSlave(mViewer->findSlaveIndexForCamera(mShadowMapCamera));
|
|
||||||
mShadowMapCamera = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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* session = Environment::get().getSession();
|
||||||
auto viewMatrix = view.getCamera()->getViewMatrix();
|
auto viewMatrix = view.getCamera()->getViewMatrix();
|
||||||
|
|
||||||
|
@ -104,8 +65,12 @@ namespace MWVR
|
||||||
auto modifiedViewMatrix = viewMatrix * session->viewMatrix(P, osg::Quat(0, 0, 0, 1));
|
auto modifiedViewMatrix = viewMatrix * session->viewMatrix(P, osg::Quat(0, 0, 0, 1));
|
||||||
auto projectionMatrix = fov.perspectiveMatrix(near_, far_);
|
auto projectionMatrix = fov.perspectiveMatrix(near_, far_);
|
||||||
|
|
||||||
camera->setViewMatrix(modifiedViewMatrix);
|
if (mMasterConfig->_projection == nullptr)
|
||||||
camera->setProjectionMatrix(projectionMatrix);
|
mMasterConfig->_projection = new osg::RefMatrix;
|
||||||
slave.updateSlaveImplementation(view);
|
if (mMasterConfig->_modelView == nullptr)
|
||||||
|
mMasterConfig->_modelView = new osg::RefMatrix;
|
||||||
|
mMasterConfig->_referenceFrame = view.getCamera()->getReferenceFrame();
|
||||||
|
mMasterConfig->_modelView->set(modifiedViewMatrix);
|
||||||
|
mMasterConfig->_projection->set(projectionMatrix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,17 +19,13 @@ namespace MWVR
|
||||||
{
|
{
|
||||||
using SharedShadowMapConfig = SceneUtil::MWShadowTechnique::SharedShadowMapConfig;
|
using SharedShadowMapConfig = SceneUtil::MWShadowTechnique::SharedShadowMapConfig;
|
||||||
public:
|
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:
|
private:
|
||||||
osgViewer::Viewer* mViewer;
|
|
||||||
int mRenderOrder;
|
|
||||||
osg::ref_ptr<osg::Camera> mShadowMapCamera;
|
|
||||||
osg::ref_ptr< UpdateShadowMapSlaveCallback > mUpdateCallback;
|
|
||||||
osg::ref_ptr<SharedShadowMapConfig> mMasterConfig;
|
osg::ref_ptr<SharedShadowMapConfig> mMasterConfig;
|
||||||
osg::ref_ptr<SharedShadowMapConfig> mSlaveConfig;
|
osg::ref_ptr<SharedShadowMapConfig> mSlaveConfig;
|
||||||
};
|
};
|
||||||
|
|
|
@ -78,9 +78,22 @@ namespace MWVR {
|
||||||
void VRView::UpdateSlaveCallback::updateSlave(
|
void VRView::UpdateSlaveCallback::updateSlave(
|
||||||
osg::View& view,
|
osg::View& view,
|
||||||
osg::View::Slave& slave)
|
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* camera = slave._camera.get();
|
||||||
auto name = camera->getName();
|
|
||||||
|
|
||||||
// Update current cached cull mask of camera if it is active
|
// Update current cached cull mask of camera if it is active
|
||||||
auto mask = camera->getCullMask();
|
auto mask = camera->getCullMask();
|
||||||
|
@ -89,17 +102,23 @@ namespace MWVR {
|
||||||
else
|
else
|
||||||
mCullMask = mask;
|
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)
|
if (Environment::get().getSession()->getFrame(VRSession::FramePhase::Update)->mShouldRender)
|
||||||
{
|
{
|
||||||
Side side = Side::RIGHT_SIDE;
|
Side side = Side::RIGHT_SIDE;
|
||||||
if (name == "LeftEye")
|
if (mName == "LeftEye")
|
||||||
|
{
|
||||||
|
|
||||||
|
Environment::get().getViewer()->vrShadow().updateShadowConfig(view);
|
||||||
side = Side::LEFT_SIDE;
|
side = Side::LEFT_SIDE;
|
||||||
|
}
|
||||||
|
|
||||||
auto* session = Environment::get().getSession();
|
auto* session = Environment::get().getSession();
|
||||||
auto viewMatrix = view.getCamera()->getViewMatrix();
|
auto viewMatrix = view.getCamera()->getViewMatrix();
|
||||||
|
|
||||||
bool haveView = viewMatrix.getTrans().length() > 0.01;
|
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)
|
if (haveView)
|
||||||
{
|
{
|
||||||
viewMatrix = viewMatrix * session->viewMatrix(VRSession::FramePhase::Update, side, true);
|
viewMatrix = viewMatrix * session->viewMatrix(VRSession::FramePhase::Update, side, true);
|
||||||
|
@ -115,19 +134,8 @@ namespace MWVR {
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If the session is not active, we do not want to waste resources rendering frames.
|
|
||||||
camera->setCullMask(0);
|
camera->setCullMask(0);
|
||||||
}
|
}
|
||||||
slave.updateSlaveImplementation(view);
|
slave.updateSlaveImplementation(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VRView::postrenderCallback(osg::RenderInfo& renderInfo)
|
|
||||||
{
|
|
||||||
auto name = renderInfo.getCurrentCamera()->getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VRView::swapBuffers(osg::GraphicsContext* gc)
|
|
||||||
{
|
|
||||||
mSwapchain->endFrame(gc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@ struct XrSwapchainSubImage;
|
||||||
|
|
||||||
namespace MWVR
|
namespace MWVR
|
||||||
{
|
{
|
||||||
|
class VRViewer;
|
||||||
|
|
||||||
/// \brief Manipulates a slave camera by replacing its framebuffer with one destined for openxr
|
/// \brief Manipulates a slave camera by replacing its framebuffer with one destined for openxr
|
||||||
class VRView : public osg::Referenced
|
class VRView : public osg::Referenced
|
||||||
{
|
{
|
||||||
|
@ -23,11 +25,11 @@ namespace MWVR
|
||||||
class UpdateSlaveCallback : public osg::View::Slave::UpdateSlaveCallback
|
class UpdateSlaveCallback : public osg::View::Slave::UpdateSlaveCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
UpdateSlaveCallback(osg::ref_ptr<VRView> view) : mView(view) {}
|
||||||
void updateSlave(osg::View& view, osg::View::Slave& slave) override;
|
void updateSlave(osg::View& view, osg::View::Slave& slave) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
osg::ref_ptr<VRView> mView;
|
osg::ref_ptr<VRView> mView;
|
||||||
osg::Node::NodeMask mCullMask;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -37,19 +39,25 @@ namespace MWVR
|
||||||
public:
|
public:
|
||||||
//! Prepare for render (set FBO)
|
//! Prepare for render (set FBO)
|
||||||
virtual void prerenderCallback(osg::RenderInfo& renderInfo);
|
virtual void prerenderCallback(osg::RenderInfo& renderInfo);
|
||||||
|
|
||||||
//! Finalize render
|
//! Finalize render
|
||||||
virtual void postrenderCallback(osg::RenderInfo& renderInfo);
|
virtual void postrenderCallback(osg::RenderInfo& renderInfo);
|
||||||
|
|
||||||
//! Create camera for this view
|
//! Create camera for this view
|
||||||
osg::Camera* createCamera(int order, const osg::Vec4& clearColor, osg::GraphicsContext* gc);
|
osg::Camera* createCamera(int order, const osg::Vec4& clearColor, osg::GraphicsContext* gc);
|
||||||
|
|
||||||
//! Get the view surface
|
//! Get the view surface
|
||||||
OpenXRSwapchain& swapchain(void) { return *mSwapchain; }
|
OpenXRSwapchain& swapchain(void) { return *mSwapchain; }
|
||||||
|
|
||||||
//! Present to the openxr swapchain
|
//! Present to the openxr swapchain
|
||||||
void swapBuffers(osg::GraphicsContext* gc);
|
void swapBuffers(osg::GraphicsContext* gc);
|
||||||
|
|
||||||
|
void updateSlave(osg::View& view, osg::View::Slave& slave);
|
||||||
public:
|
public:
|
||||||
SwapchainConfig mSwapchainConfig;
|
SwapchainConfig mSwapchainConfig;
|
||||||
std::unique_ptr<OpenXRSwapchain> mSwapchain;
|
std::unique_ptr<OpenXRSwapchain> mSwapchain;
|
||||||
std::string mName{};
|
std::string mName{};
|
||||||
|
osg::Node::NodeMask mCullMask;
|
||||||
bool mRendering{ false };
|
bool mRendering{ false };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace MWVR
|
||||||
: mViewer(viewer)
|
: mViewer(viewer)
|
||||||
, mPreDraw(new PredrawCallback(this))
|
, mPreDraw(new PredrawCallback(this))
|
||||||
, mPostDraw(new PostdrawCallback(this))
|
, mPostDraw(new PostdrawCallback(this))
|
||||||
, mVrShadow(viewer, 1)
|
, mVrShadow()
|
||||||
, mConfigured(false)
|
, mConfigured(false)
|
||||||
{
|
{
|
||||||
mViewer->setRealizeOperation(new RealizeOperation());
|
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.
|
// 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
|
// 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++)
|
for (unsigned i = 0; i < sViewNames.size(); i++)
|
||||||
{
|
{
|
||||||
auto view = new VRView(sViewNames[i], config[i], context->getState());
|
auto view = new VRView(sViewNames[i], config[i], context->getState());
|
||||||
|
@ -106,8 +104,7 @@ namespace MWVR
|
||||||
camera->setCullingMode(cullingMode);
|
camera->setCullingMode(cullingMode);
|
||||||
mViewer->addSlave(camera, true);
|
mViewer->addSlave(camera, true);
|
||||||
auto* slave = mViewer->findSlaveForCamera(camera);
|
auto* slave = mViewer->findSlaveForCamera(camera);
|
||||||
assert(slave);
|
slave->_updateSlaveCallback = new VRView::UpdateSlaveCallback(view);
|
||||||
slave->_updateSlaveCallback = new VRView::UpdateSlaveCallback();
|
|
||||||
|
|
||||||
if (mirror)
|
if (mirror)
|
||||||
mMsaaResolveMirrorTexture[i].reset(new VRFramebuffer(context->getState(),
|
mMsaaResolveMirrorTexture[i].reset(new VRFramebuffer(context->getState(),
|
||||||
|
@ -115,7 +112,7 @@ namespace MWVR
|
||||||
view->swapchain().height(),
|
view->swapchain().height(),
|
||||||
0));
|
0));
|
||||||
|
|
||||||
mVrShadow.configureShadowsForCamera(camera);
|
mVrShadow.configureShadowsForCamera(camera, i == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mirror)
|
if (mirror)
|
||||||
|
|
|
@ -80,6 +80,7 @@ namespace MWVR
|
||||||
void realize(osg::GraphicsContext* gc);
|
void realize(osg::GraphicsContext* gc);
|
||||||
bool realized() { return mConfigured; }
|
bool realized() { return mConfigured; }
|
||||||
VRView* getView(std::string name);
|
VRView* getView(std::string name);
|
||||||
|
VrShadow& vrShadow() { return mVrShadow; }
|
||||||
|
|
||||||
void enableMainCamera(void);
|
void enableMainCamera(void);
|
||||||
void disableMainCamera(void);
|
void disableMainCamera(void);
|
||||||
|
|
Loading…
Reference in a new issue