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

Single pass shadow update

This commit is contained in:
Mads Buvik Sandvei 2020-07-26 13:12:36 +02:00
parent a15188d3bc
commit e0bc56dcf7
6 changed files with 52 additions and 77 deletions

View file

@ -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);
}
}

View file

@ -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<osg::Camera> mShadowMapCamera;
osg::ref_ptr< UpdateShadowMapSlaveCallback > mUpdateCallback;
osg::ref_ptr<SharedShadowMapConfig> mMasterConfig;
osg::ref_ptr<SharedShadowMapConfig> mSlaveConfig;
};

View file

@ -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);
}
}

View file

@ -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<VRView> view) : mView(view) {}
void updateSlave(osg::View& view, osg::View::Slave& slave) override;
private:
osg::ref_ptr<VRView> 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<OpenXRSwapchain> mSwapchain;
std::string mName{};
osg::Node::NodeMask mCullMask;
bool mRendering{ false };
};
}

View file

@ -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)

View file

@ -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);