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:
parent
a15188d3bc
commit
e0bc56dcf7
6 changed files with 52 additions and 77 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 };
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue