1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-19 23:53:52 +00:00

More refactoring of VRSession. Moved call of BeginFrame and WaitFrame to the start of cull to keep shadow technique within openxr specs. There is still some jitter unless i change to single-threaded, and now i have no idea why.

This commit is contained in:
Mads Buvik Sandvei 2020-06-03 19:46:20 +02:00
parent 31336aba79
commit f25c3af9cb
10 changed files with 199 additions and 153 deletions

View file

@ -564,10 +564,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
// Create sound system
mEnvironment.setSoundManager (new MWSound::SoundManager(mVFS.get(), mUseSound));
#ifdef USE_OPENXR
mXrEnvironment.setGUIManager(new MWVR::VRGUIManager(mViewer));
#endif
if (!mSkipMenu)
{
const std::string& logo = Fallback::Map::getString("Movies_Company_Logo");
@ -735,6 +731,7 @@ void OMW::Engine::go()
#ifdef USE_OPENXR
mXrEnvironment.setGUIManager(new MWVR::VRGUIManager(mViewer));
//mViewer->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
#endif
// Start the game

View file

@ -1008,11 +1008,14 @@ private:
auto* vrGuiManager = Environment::get().getGUIManager();
bool vrHasFocus = vrGuiManager->updateFocus();
auto guiCursor = vrGuiManager->guiCursor();
if (vrHasFocus)
if (vrGuiManager)
{
mMouseManager->setMousePosition(guiCursor.x(), guiCursor.y());
bool vrHasFocus = vrGuiManager->updateFocus();
auto guiCursor = vrGuiManager->guiCursor();
if (vrHasFocus)
{
mMouseManager->setMousePosition(guiCursor.x(), guiCursor.y());
}
}
while (auto* action = mXRInput->nextAction())
@ -1237,7 +1240,7 @@ private:
void OpenXRInputManager::updateHead()
{
auto* session = Environment::get().getSession();
auto currentHeadPose = session->predictedPoses(VRSession::FramePhase::Predraw).head;
auto currentHeadPose = session->predictedPoses(VRSession::FramePhase::Update).head;
currentHeadPose.position *= Environment::get().unitsPerMeter();
osg::Vec3 vrMovement = currentHeadPose.position - mHeadPose.position;
mHeadPose = currentHeadPose;

View file

@ -277,44 +277,58 @@ namespace MWVR
void
OpenXRManagerImpl::waitFrame()
{
auto DC = wglGetCurrentDC();
auto GLRC = wglGetCurrentContext();
auto XRDC = mGraphicsBinding.hDC;
auto XRGLRC = mGraphicsBinding.hGLRC;
wglMakeCurrent(XRDC, XRGLRC);
Timer timer("waitFrame()");
static std::mutex waitFrameMutex;
if (!mSessionRunning)
return;
XrFrameWaitInfo frameWaitInfo{ XR_TYPE_FRAME_WAIT_INFO };
XrFrameState frameState{ XR_TYPE_FRAME_STATE };
CHECK_XRCMD(xrWaitFrame(mSession, &frameWaitInfo, &frameState));
std::unique_lock<std::mutex> lock(mFrameStateMutex);
mFrameState = frameState;
wglMakeCurrent(DC, GLRC);
}
void
OpenXRManagerImpl::beginFrame()
{
auto DC = wglGetCurrentDC();
auto GLRC = wglGetCurrentContext();
auto XRDC = mGraphicsBinding.hDC;
auto XRGLRC = mGraphicsBinding.hGLRC;
wglMakeCurrent(XRDC, XRGLRC);
Timer timer("beginFrame");
XrFrameBeginInfo frameBeginInfo{ XR_TYPE_FRAME_BEGIN_INFO };
CHECK_XRCMD(xrBeginFrame(mSession, &frameBeginInfo));
wglMakeCurrent(DC, GLRC);
}
void
OpenXRManagerImpl::endFrame(int64_t displayTime, int layerCount, XrCompositionLayerBaseHeader** layerStack)
{
Timer timer("endFrame()");
if (!mSessionRunning)
return;
auto DC = wglGetCurrentDC();
auto GLRC = wglGetCurrentContext();
auto XRDC = mGraphicsBinding.hDC;
auto XRGLRC = mGraphicsBinding.hGLRC;
wglMakeCurrent(XRDC, XRGLRC);
Timer timer("endFrame()");
XrFrameEndInfo frameEndInfo{ XR_TYPE_FRAME_END_INFO };
frameEndInfo.displayTime = displayTime;
frameEndInfo.environmentBlendMode = mEnvironmentBlendMode;
frameEndInfo.layerCount = layerCount;
frameEndInfo.layers = layerStack;
CHECK_XRCMD(xrEndFrame(mSession, &frameEndInfo));
wglMakeCurrent(DC, GLRC);
}
std::array<XrView, 2>

View file

@ -103,7 +103,7 @@ void StateMachine::update(float dt, bool enabled)
{
auto* session = Environment::get().getSession();
auto* world = MWBase::Environment::get().getWorld();
auto& predictedPoses = session->predictedPoses(VRSession::FramePhase::Predraw);
auto& predictedPoses = session->predictedPoses(VRSession::FramePhase::Update);
auto& handPose = predictedPoses.hands[(int)MWVR::Side::RIGHT_HAND];
auto weaponType = world->getActiveWeaponType();

View file

@ -114,8 +114,8 @@ void ForearmController::operator()(osg::Node* node, osg::NodeVisitor* nv)
MWBase::Environment::get().getWorld()->getRenderingManager().getCamera()->updateCamera();
}
MWVR::Pose handStage = session->predictedPoses(VRSession::FramePhase::Predraw).hands[side];
MWVR::Pose headStage = session->predictedPoses(VRSession::FramePhase::Predraw).head;
MWVR::Pose handStage = session->predictedPoses(VRSession::FramePhase::Update).hands[side];
MWVR::Pose headStage = session->predictedPoses(VRSession::FramePhase::Update).head;
auto orientation = handStage.orientation;

View file

@ -24,6 +24,7 @@
#include "vrsession.hpp"
#include "vrgui.hpp"
#include <time.h>
#include <thread>
namespace MWVR
{
@ -38,7 +39,7 @@ VRSession::~VRSession()
osg::Matrix VRSession::projectionMatrix(FramePhase phase, Side side)
{
assert(((int)side) < 2);
auto fov = predictedPoses(VRSession::FramePhase::Predraw).view[(int)side].fov;
auto fov = predictedPoses(VRSession::FramePhase::Update).view[(int)side].fov;
float near_ = Settings::Manager::getFloat("near clip", "Camera");
float far_ = Settings::Manager::getFloat("viewing distance", "Camera");
return fov.perspectiveMatrix(near_, far_);
@ -46,7 +47,7 @@ osg::Matrix VRSession::projectionMatrix(FramePhase phase, Side side)
osg::Matrix VRSession::viewMatrix(FramePhase phase, Side side)
{
MWVR::Pose pose = predictedPoses(VRSession::FramePhase::Predraw).view[(int)side].pose;
MWVR::Pose pose = predictedPoses(phase).view[(int)side].pose;
osg::Vec3 position = pose.position * Environment::get().unitsPerMeter();
osg::Quat orientation = pose.orientation;
@ -77,72 +78,120 @@ void VRSession::swapBuffers(osg::GraphicsContext* gc, VRViewer& viewer)
Timer timer("VRSession::SwapBuffers");
auto* xr = Environment::get().getManager();
beginPhase(FramePhase::Swap);
if (getFrame(FramePhase::Swap)->mShouldRender)
{
std::unique_lock<std::mutex> lock(mMutex);
auto leftView = viewer.mViews["LeftEye"];
auto rightView = viewer.mViews["RightEye"];
xr->handleEvents();
viewer.blitEyesToMirrorTexture(gc);
gc->swapBuffersImplementation();
leftView->swapBuffers(gc);
rightView->swapBuffers(gc);
mPostdrawFrame = std::move(mDrawFrame);
assert(mPostdrawFrame);
std::array<XrCompositionLayerProjectionView, 2> compositionLayerProjectionViews{};
compositionLayerProjectionViews[0].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
compositionLayerProjectionViews[1].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
compositionLayerProjectionViews[0].subImage = leftView->swapchain().subImage();
compositionLayerProjectionViews[1].subImage = rightView->swapchain().subImage();
compositionLayerProjectionViews[0].pose = toXR(getFrame(FramePhase::Swap)->mPredictedPoses.eye[(int)Side::LEFT_HAND]);
compositionLayerProjectionViews[1].pose = toXR(getFrame(FramePhase::Swap)->mPredictedPoses.eye[(int)Side::RIGHT_HAND]);
compositionLayerProjectionViews[0].fov = toXR(getFrame(FramePhase::Swap)->mPredictedPoses.view[(int)Side::LEFT_HAND].fov);
compositionLayerProjectionViews[1].fov = toXR(getFrame(FramePhase::Swap)->mPredictedPoses.view[(int)Side::RIGHT_HAND].fov);
XrCompositionLayerProjection layer{};
layer.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION;
layer.space = xr->impl().getReferenceSpace(TrackedSpace::STAGE);
layer.viewCount = 2;
layer.views = compositionLayerProjectionViews.data();
auto* layerStack = reinterpret_cast<XrCompositionLayerBaseHeader*>(&layer);
Log(Debug::Debug) << getFrame(FramePhase::Swap)->mFrameNo << ": EndFrame";
xr->endFrame(getFrame(FramePhase::Swap)->mPredictedDisplayTime, 1, &layerStack);
}
// TODO: Should blit mirror texture regardless
if (!isRunning())
return;
xr->waitFrame();
xr->beginFrame();
viewer.swapBuffers(gc);
auto leftView = viewer.mViews["LeftEye"];
auto rightView = viewer.mViews["RightEye"];
leftView->swapBuffers(gc);
rightView->swapBuffers(gc);
std::array<XrCompositionLayerProjectionView, 2> compositionLayerProjectionViews{};
compositionLayerProjectionViews[0].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
compositionLayerProjectionViews[1].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
compositionLayerProjectionViews[0].subImage = leftView->swapchain().subImage();
compositionLayerProjectionViews[1].subImage = rightView->swapchain().subImage();
compositionLayerProjectionViews[0].pose = toXR(mPostdrawFrame->mPredictedPoses.eye[(int)Side::LEFT_HAND]);
compositionLayerProjectionViews[1].pose = toXR(mPostdrawFrame->mPredictedPoses.eye[(int)Side::RIGHT_HAND]);
compositionLayerProjectionViews[0].fov = toXR(mPostdrawFrame->mPredictedPoses.view[(int)Side::LEFT_HAND].fov);
compositionLayerProjectionViews[1].fov = toXR(mPostdrawFrame->mPredictedPoses.view[(int)Side::RIGHT_HAND].fov);
XrCompositionLayerProjection layer{};
layer.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION;
layer.space = xr->impl().getReferenceSpace(TrackedSpace::STAGE);
layer.viewCount = 2;
layer.views = compositionLayerProjectionViews.data();
auto* layerStack = reinterpret_cast<XrCompositionLayerBaseHeader*>(&layer);
xr->endFrame(mPostdrawFrame->mPredictedDisplayTime, 1, &layerStack);
mLastRenderedFrame = mPostdrawFrame->mFrameNo;
std::unique_lock<std::mutex> lock(mMutex);
auto xrPredictionChange = xr->impl().frameState().predictedDisplayTime - mLastPredictedDisplayTime;
mLastPredictedDisplayTime = xr->impl().frameState().predictedDisplayTime;
mLastPredictedDisplayPeriod = xr->impl().frameState().predictedDisplayPeriod;
auto now = std::chrono::steady_clock::now();
mLastFrameInterval = std::chrono::duration_cast<std::chrono::nanoseconds>(now - mLastRenderedFrameTimestamp);
mLastRenderedFrameTimestamp = now;
mLastRenderedFrame = getFrame(FramePhase::Swap)->mFrameNo;
//Log(Debug::Verbose) << getFrame(FramePhase::Swap)->mFrameNo << ": xrPrediction=" << xr->impl().frameState().predictedDisplayTime << ", ourPrediction=" << getFrame(FramePhase::Swap)->mPredictedDisplayTime << ", miss=" << miss << "ms";
Log(Debug::Debug) << "xrPredictionChange=" << (xrPredictionChange / 1000000) << "ms";
auto seconds = std::chrono::duration_cast<std::chrono::duration<double>>(now - mStart).count();
static int sBaseFrames = 0;
if (seconds > 10.f)
{
Log(Debug::Verbose) << "Fps: " << (static_cast<double>(mLastRenderedFrame - sBaseFrames) / seconds);
mStart = now;
sBaseFrames = mLastRenderedFrame;
}
getFrame(FramePhase::Swap) = nullptr;
mCondition.notify_one();
}
void VRSession::advanceFramePhase(void)
void VRSession::beginPhase(FramePhase phase)
{
std::unique_lock<std::mutex> lock(mMutex);
Timer timer("VRSession::advanceFrame");
Log(Debug::Debug) << "beginPhase(" << ((int)phase) << ")";
assert(!mDrawFrame);
mDrawFrame = std::move(mPredrawFrame);
if (phase != FramePhase::Update)
{
std::unique_lock<std::mutex> lock(mMutex);
FramePhase previousPhase = static_cast<FramePhase>((int)phase - 1);
if (getFrame(phase))
throw std::logic_error("advanceFramePhase called with a frame alreay in the target phase");
if (!getFrame(previousPhase))
throw std::logic_error("advanceFramePhase called without a frame in the predraw phase");
getFrame(phase) = std::move(getFrame(previousPhase));
}
else
prepareFrame();
if (phase == FramePhase::Cull && getFrame(phase)->mShouldRender)
{
auto* xr = Environment::get().getManager();
// Since i am forced to do xr->beginFrame() before cull instead of draw
// i have to explicitly wait for xr->endFrame() to finish to avoid an
// out-of-order error from openxr.
// If i don't wait, we might hit beginFrame() before the previous frame
// reaches endFrame() in which case openxr will cancel the previous frame
// and we will get an out-of-order error due to two back-to-back calls to endFrame()
while (getFrame(phase)->mFrameNo != (mLastRenderedFrame + 1))
{
std::unique_lock<std::mutex> lock(mMutex);
mCondition.wait(lock);
}
Log(Debug::Debug) << getFrame(phase)->mFrameNo << ": WaitFrame";
xr->waitFrame();
Log(Debug::Debug) << getFrame(phase)->mFrameNo << ": BeginFrame";
xr->beginFrame();
}
}
void VRSession::startFrame()
std::unique_ptr<VRSession::VRFrame>& VRSession::getFrame(FramePhase phase)
{
if ((unsigned int)phase >= mFrame.size())
throw std::logic_error("Invalid frame phase");
return mFrame[(int)phase];
}
void VRSession::prepareFrame()
{
std::unique_lock<std::mutex> lock(mMutex);
assert(!mPredrawFrame);
Timer timer("VRSession::startFrame");
auto* xr = Environment::get().getManager();
auto* input = Environment::get().getInputManager();
xr->handleEvents();
// Until OpenXR allows us to get a prediction without waiting
// we make our own (bad) prediction and let openxr wait
// we make our own (bad) prediction and call xrWaitFrame when it is more convenient
auto frameState = xr->impl().frameState();
long long predictedDisplayTime = 0;
mFrames++;
@ -154,17 +203,19 @@ void VRSession::startFrame()
else if (mFrames > mLastRenderedFrame)
{
//predictedDisplayTime = mLastPredictedDisplayTime + mLastFrameInterval.count() * (mFrames - mLastRenderedFrame);
float intervalsf = static_cast<double>(mLastFrameInterval.count()) / static_cast<double>(frameState.predictedDisplayPeriod);
int intervals = (int)std::roundf(intervalsf);
predictedDisplayTime = mLastPredictedDisplayTime + intervals * (mFrames - mLastRenderedFrame) * frameState.predictedDisplayPeriod;
float intervalsf = static_cast<double>(mLastFrameInterval.count()) / static_cast<double>(mLastPredictedDisplayPeriod);
#ifdef max
#undef max
#endif
int intervals = std::max((int)std::roundf(intervalsf), 1);
predictedDisplayTime = mLastPredictedDisplayTime + intervals * (mFrames - mLastRenderedFrame) * mLastPredictedDisplayPeriod;
}
PoseSet predictedPoses{};
if (isRunning())
{
xr->impl().enablePredictions();
predictedPoses.head = xr->impl().getPredictedLimbPose(predictedDisplayTime, TrackedLimb::HEAD, TrackedSpace::STAGE) * mPlayerScale;
predictedPoses.hands[(int)Side::LEFT_HAND] = input->getHandPose(predictedDisplayTime, TrackedSpace::STAGE, Side::LEFT_HAND) * mPlayerScale;
predictedPoses.hands[(int)Side::RIGHT_HAND] = input->getHandPose(predictedDisplayTime, TrackedSpace::STAGE, Side::RIGHT_HAND) * mPlayerScale;
auto hmdViews = xr->impl().getPredictedViews(predictedDisplayTime, TrackedSpace::VIEW);
predictedPoses.view[(int)Side::LEFT_HAND].pose = fromXR(hmdViews[(int)Side::LEFT_HAND].pose) * mPlayerScale;
predictedPoses.view[(int)Side::RIGHT_HAND].pose = fromXR(hmdViews[(int)Side::RIGHT_HAND].pose) * mPlayerScale;
@ -173,43 +224,34 @@ void VRSession::startFrame()
auto stageViews = xr->impl().getPredictedViews(predictedDisplayTime, TrackedSpace::STAGE);
predictedPoses.eye[(int)Side::LEFT_HAND] = fromXR(stageViews[(int)Side::LEFT_HAND].pose) * mPlayerScale;
predictedPoses.eye[(int)Side::RIGHT_HAND] = fromXR(stageViews[(int)Side::RIGHT_HAND].pose) * mPlayerScale;
}
else
{
// If session is not running, copy poses from the last frame
if (mPostdrawFrame)
predictedPoses = mPostdrawFrame->mPredictedPoses;
auto* input = Environment::get().getInputManager();
if (input)
{
predictedPoses.hands[(int)Side::LEFT_HAND] = input->getHandPose(predictedDisplayTime, TrackedSpace::STAGE, Side::LEFT_HAND) * mPlayerScale;
predictedPoses.hands[(int)Side::RIGHT_HAND] = input->getHandPose(predictedDisplayTime, TrackedSpace::STAGE, Side::RIGHT_HAND) * mPlayerScale;
}
xr->impl().disablePredictions();
}
mPredrawFrame.reset(new VRFrame);
mPredrawFrame->mPredictedDisplayTime = predictedDisplayTime;
mPredrawFrame->mFrameNo = mFrames;
mPredrawFrame->mPredictedPoses = predictedPoses;
auto& frame = getFrame(FramePhase::Update);
frame.reset(new VRFrame);
frame->mPredictedDisplayTime = predictedDisplayTime;
frame->mFrameNo = mFrames;
frame->mPredictedPoses = predictedPoses;
frame->mShouldRender = isRunning();
}
const PoseSet& VRSession::predictedPoses(FramePhase phase)
{
switch (phase)
{
case FramePhase::Predraw:
if (!mPredrawFrame)
startFrame();
assert(mPredrawFrame);
return mPredrawFrame->mPredictedPoses;
auto& frame = getFrame(phase);
case FramePhase::Draw:
assert(mDrawFrame);
return mDrawFrame->mPredictedPoses;
if (phase == FramePhase::Update && !frame)
beginPhase(FramePhase::Update);
case FramePhase::Postdraw:
assert(mPostdrawFrame);
return mPostdrawFrame->mPredictedPoses;
}
assert(0);
return mPredrawFrame->mPredictedPoses;
if (!frame)
throw std::logic_error("Attempted to get poses from a phase with no current pose");
return frame->mPredictedPoses;
}
// OSG doesn't provide API to extract euler angles from a quat, but i need it.
@ -253,8 +295,11 @@ void VRSession::movementAngles(float& yaw, float& pitch)
{
assert(mPredrawFrame);
auto* input = Environment::get().getInputManager();
auto lhandquat = input->getHandPose(mPredrawFrame->mPredictedDisplayTime, TrackedSpace::VIEW, Side::LEFT_HAND).orientation;
//predictedPoses(FramePhase::Predraw).hands[(int)TrackedSpace::VIEW][(int)MWVR::Side::LEFT_HAND].orientation;
// TODO: This strictly speaking violates the rule of not making predictions outside of prepareFrame()
// I should either add VIEW hands to the predicted pose set, or compute this using STAGE poses
// It would likely suffice to compute euler angles for STAGE head and hand and return the difference?
auto lhandquat = input->getHandPose(getFrame(FramePhase::Update)->mPredictedDisplayTime, TrackedSpace::VIEW, Side::LEFT_HAND).orientation;
//predictedPoses(FramePhase::Predraw).hands[(int)TrackedSpace::VIEW][(int)MWVR::Side::LEFT_HAND].orientation;
float roll = 0.f;
getEulerAngles(lhandquat, yaw, pitch, roll);

View file

@ -27,9 +27,11 @@ public:
enum class FramePhase
{
Predraw = 0, //!< Get poses predicted for the next frame to be drawn
Draw = 1, //!< Get poses predicted for the current rendering frame
Postdraw = 2, //!< Get poses predicted for the last rendered frame
Update = 0, //!< The frame currently in update traversals
Cull, //!< The frame currently in cull
Draw, //!< The frame currently in draw
Swap, //!< The frame being swapped
NumPhases
};
struct VRFrame
@ -37,6 +39,8 @@ public:
long long mFrameNo{ 0 };
long long mPredictedDisplayTime{ 0 };
PoseSet mPredictedPoses{};
bool mShouldRender{ false };
bool mHasWaited{ false };
};
public:
@ -48,12 +52,13 @@ public:
const PoseSet& predictedPoses(FramePhase phase);
//! Starts a new frame
void startFrame();
void prepareFrame();
//! Angles to be used for overriding movement direction
void movementAngles(float& yaw, float& pitch);
void advanceFramePhase(void);
void beginPhase(FramePhase phase);
std::unique_ptr<VRFrame>& getFrame(FramePhase phase);
bool isRunning() const;
@ -63,9 +68,7 @@ public:
osg::Matrix viewMatrix(FramePhase phase, Side side);
osg::Matrix projectionMatrix(FramePhase phase, Side side);
std::unique_ptr<VRFrame> mPredrawFrame{ nullptr };
std::unique_ptr<VRFrame> mDrawFrame{ nullptr };
std::unique_ptr<VRFrame> mPostdrawFrame{ nullptr };
std::array<std::unique_ptr<VRFrame>, (int)FramePhase::NumPhases> mFrame{ nullptr };
std::mutex mMutex{};
std::condition_variable mCondition{};
@ -74,6 +77,7 @@ public:
long long mLastRenderedFrame{ 0 };
long long mLastPredictedDisplayTime{ 0 };
long long mLastPredictedDisplayPeriod{ 0 };
std::chrono::steady_clock::time_point mStart{ std::chrono::steady_clock::now() };
std::chrono::nanoseconds mLastFrameInterval{};
std::chrono::steady_clock::time_point mLastRenderedFrameTimestamp{std::chrono::steady_clock::now()};

View file

@ -39,6 +39,17 @@ namespace MWVR {
{
}
class CullCallback : public osg::NodeCallback
{
void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
const auto& name = node->getName();
if (name == "LeftEye")
Environment::get().getSession()->beginPhase(VRSession::FramePhase::Cull);
traverse(node, nv);
}
};
osg::Camera* VRView::createCamera(int eye, const osg::Vec4& clearColor, osg::GraphicsContext* gc)
{
osg::ref_ptr<osg::Camera> camera = new osg::Camera();
@ -53,6 +64,7 @@ namespace MWVR {
camera->setGraphicsContext(gc);
camera->setInitialDrawCallback(new VRView::InitialDrawCallback());
camera->setCullCallback(new CullCallback);
return camera.release();
}
@ -69,6 +81,10 @@ namespace MWVR {
void VRView::InitialDrawCallback::operator()(osg::RenderInfo& renderInfo) const
{
const auto& name = renderInfo.getCurrentCamera()->getName();
if (name == "LeftEye")
Environment::get().getSession()->beginPhase(VRSession::FramePhase::Draw);
osg::GraphicsOperation* graphicsOperation = renderInfo.getCurrentCamera()->getRenderer();
osgViewer::Renderer* renderer = dynamic_cast<osgViewer::Renderer*>(graphicsOperation);
if (renderer != nullptr)
@ -76,7 +92,6 @@ namespace MWVR {
// Disable normal OSG FBO camera setup
renderer->setCameraRequiresSetUp(false);
}
auto name = renderInfo.getCurrentCamera()->getName();
}
void VRView::UpdateSlaveCallback::updateSlave(
osg::View& view,
@ -93,8 +108,9 @@ namespace MWVR {
auto* session = Environment::get().getSession();
auto viewMatrix = view.getCamera()->getViewMatrix();
auto modifiedViewMatrix = viewMatrix * session->viewMatrix(VRSession::FramePhase::Predraw, side);
auto projectionMatrix = session->projectionMatrix(VRSession::FramePhase::Predraw, side);
auto modifiedViewMatrix = viewMatrix * session->viewMatrix(VRSession::FramePhase::Update, side);
auto projectionMatrix = session->projectionMatrix(VRSession::FramePhase::Update, side);
camera->setViewMatrix(modifiedViewMatrix);
camera->setProjectionMatrix(projectionMatrix);
@ -109,6 +125,6 @@ namespace MWVR {
void VRView::swapBuffers(osg::GraphicsContext* gc)
{
swapchain().endFrame(gc);
mSwapchain->endFrame(gc);
}
}

View file

@ -151,22 +151,16 @@ namespace MWVR
void VRViewer::blitEyesToMirrorTexture(osg::GraphicsContext* gc)
{
//includeMenu = false;
mMirrorTextureSwapchain->beginFrame(gc);
int mirror_width = mMirrorTextureSwapchain->width() / 2;
mMirrorTextureSwapchain->beginFrame(gc);
mViews["RightEye"]->swapchain().renderBuffer()->blit(gc, 0, 0, mirror_width, mMirrorTextureSwapchain->height());
mViews["LeftEye"]->swapchain().renderBuffer()->blit(gc, mirror_width, 0, 2 * mirror_width, mMirrorTextureSwapchain->height());
auto* state = gc->getState();
auto* gl = osg::GLExtensions::Get(state->getContextID(), false);
mMirrorTextureSwapchain->endFrame(gc);
auto* state = gc->getState();
auto* gl = osg::GLExtensions::Get(state->getContextID(), false);
gl->glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
mMirrorTextureSwapchain->renderBuffer()->blit(gc, 0, 0, mMirrorTextureSwapchain->width(), mMirrorTextureSwapchain->height());
@ -178,24 +172,6 @@ namespace MWVR
{
auto* session = Environment::get().getSession();
session->swapBuffers(gc, *mViewer);
gc->swapBuffersImplementation();
}
void VRViewer::swapBuffers(osg::GraphicsContext* gc)
{
if (!mConfigured)
return;
Timer timer("VRViewer::SwapBuffers");
for (auto& view : mViews)
view.second->swapBuffers(gc);
timer.checkpoint("Views");
blitEyesToMirrorTexture(gc);
gc->swapBuffersImplementation();
}
void
@ -217,12 +193,7 @@ namespace MWVR
{
auto* camera = info.getCurrentCamera();
auto name = camera->getName();
auto& view = mViews[name];
if (name == "LeftEye")
Environment::get().getSession()->advanceFramePhase();
view->prerenderCallback(info);
mViews[name]->prerenderCallback(info);
}
void VRViewer::postDrawCallback(osg::RenderInfo& info)
@ -239,8 +210,5 @@ namespace MWVR
camera->setPreDrawCallback(mPreDraw);
Log(Debug::Warning) << ("osg overwrote predraw");
}
//if(mDelay && name == "RightEye")
// std::this_thread::sleep_for(std::chrono::milliseconds(25));
}
}

View file

@ -77,7 +77,6 @@ namespace MWVR
void preDrawCallback(osg::RenderInfo& info);
void postDrawCallback(osg::RenderInfo& info);
void blitEyesToMirrorTexture(osg::GraphicsContext* gc);
void swapBuffers(osg::GraphicsContext* gc);
void realize(osg::GraphicsContext* gc);
bool realized() { return mConfigured; }