From a260aaaae898df5453ac7465e53af741cad46215 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 15 Sep 2017 16:17:41 -0700 Subject: [PATCH] Fix for lighting as IPD scale changes. --- interface/src/Application.cpp | 18 ++++++++++-------- interface/src/ui/overlays/Base3DOverlay.h | 3 --- .../src/display-plugins/hmd/HmdDisplayPlugin.h | 2 +- plugins/oculus/src/OculusBaseDisplayPlugin.cpp | 14 ++++++++++++++ plugins/oculus/src/OculusBaseDisplayPlugin.h | 1 + plugins/openvr/src/OpenVrDisplayPlugin.cpp | 13 +++++++++++++ plugins/openvr/src/OpenVrDisplayPlugin.h | 1 + 7 files changed, 40 insertions(+), 12 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3e69852e6b..dab15cfa2a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2413,10 +2413,18 @@ void Application::paintGL() { auto lodManager = DependencyManager::get(); RenderArgs renderArgs; + + float sensorToWorldScale = getMyAvatar()->getSensorToWorldScale(); { PROFILE_RANGE(render, "/buildFrustrumAndArgs"); { QMutexLocker viewLocker(&_viewMutex); + // adjust near clip plane to account for sensor scaling. + auto adjustedProjection = glm::perspective(_viewFrustum.getFieldOfView(), + _viewFrustum.getAspectRatio(), + DEFAULT_NEAR_CLIP * sensorToWorldScale, + _viewFrustum.getFarClip()); + _viewFrustum.setProjection(adjustedProjection); _viewFrustum.calculate(); } renderArgs = RenderArgs(_gpuContext, lodManager->getOctreeSizeScale(), @@ -2570,7 +2578,6 @@ void Application::paintGL() { float ipdScale = hmdInterface->getIPDScale(); // scale IPD by sensorToWorldScale, to make the world seem larger or smaller accordingly. - float sensorToWorldScale = getMyAvatar()->getSensorToWorldScale(); ipdScale *= sensorToWorldScale; mat4 eyeProjections[2]; @@ -2582,6 +2589,7 @@ void Application::paintGL() { // in the overlay render? // Viewport is assigned to the size of the framebuffer renderArgs._viewport = ivec4(0, 0, finalFramebufferSize.width(), finalFramebufferSize.height()); + auto baseProjection = renderArgs.getViewFrustum().getProjection(); if (displayPlugin->isStereo()) { // Stereo modes will typically have a larger projection matrix overall, // so we ask for the 'mono' projection matrix, which for stereo and HMD @@ -2592,17 +2600,11 @@ void Application::paintGL() { // just relying on the left FOV in each case and hoping that the // overall culling margin of error doesn't cause popping in the // right eye. There are FIXMEs in the relevant plugins - _myCamera.setProjection(displayPlugin->getCullingProjection(_myCamera.getProjection())); + _myCamera.setProjection(displayPlugin->getCullingProjection(baseProjection)); renderArgs._context->enableStereo(true); mat4 eyeOffsets[2]; mat4 eyeProjections[2]; - // adjust near clip plane by sensorToWorldScale - auto baseProjection = glm::perspective(renderArgs.getViewFrustum().getFieldOfView(), - renderArgs.getViewFrustum().getAspectRatio(), - renderArgs.getViewFrustum().getNearClip() * sensorToWorldScale, - renderArgs.getViewFrustum().getFarClip()); - // FIXME we probably don't need to set the projection matrix every frame, // only when the display plugin changes (or in non-HMD modes when the user // changes the FOV manually, which right now I don't think they can. diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index cc46fecfa5..6377b46d7d 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -16,9 +16,6 @@ #include "Overlay.h" -// AJT: keep or remove this. -// #define USE_SN_SCALE - class Base3DOverlay : public Overlay, public SpatiallyNestable { Q_OBJECT diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index bcf2b16ac6..db4e0ff7a1 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -28,7 +28,7 @@ public: float getIPD() const override final { return _ipd; } glm::mat4 getEyeToHeadTransform(Eye eye) const override final { return _eyeOffsets[eye]; } glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const override { return _eyeProjections[eye]; } - glm::mat4 getCullingProjection(const glm::mat4& baseProjection) const override final { return _cullingProjection; } + glm::mat4 getCullingProjection(const glm::mat4& baseProjection) const override { return _cullingProjection; } glm::uvec2 getRecommendedUiSize() const override final; glm::uvec2 getRecommendedRenderSize() const override final { return _renderTargetSize; } bool isDisplayVisible() const override { return isHmdMounted(); } diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp index aa39353b94..ea0af0d5f5 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp @@ -76,6 +76,20 @@ glm::mat4 OculusBaseDisplayPlugin::getEyeProjection(Eye eye, const glm::mat4& ba } } +glm::mat4 OculusBaseDisplayPlugin::getCullingProjection(const glm::mat4& baseProjection) const { + if (_session) { + ViewFrustum baseFrustum; + baseFrustum.setProjection(baseProjection); + float baseNearClip = baseFrustum.getNearClip(); + float baseFarClip = baseFrustum.getFarClip(); + auto combinedFov = _eyeFovs[0]; + combinedFov.LeftTan = combinedFov.RightTan = std::max(combinedFov.LeftTan, combinedFov.RightTan); + return toGlm(ovrMatrix4f_Projection(combinedFov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_ClipRangeOpenGL)); + } else { + return baseProjection; + } +} + // DLL based display plugins MUST initialize GLEW inside the DLL code. void OculusBaseDisplayPlugin::customizeContext() { glewExperimental = true; diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.h b/plugins/oculus/src/OculusBaseDisplayPlugin.h index 4d14223618..b3b99c0ad1 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.h +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.h @@ -20,6 +20,7 @@ public: bool isSupported() const override; glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const override; + glm::mat4 getCullingProjection(const glm::mat4& baseProjection) const override; bool hasAsyncReprojection() const override { return true; } diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 25c85737fe..96ad19f46b 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -370,6 +370,19 @@ glm::mat4 OpenVrDisplayPlugin::getEyeProjection(Eye eye, const glm::mat4& basePr } } +glm::mat4 OpenVrDisplayPlugin::getCullingProjection(const glm::mat4& baseProjection) const { + if (_system) { + ViewFrustum baseFrustum; + baseFrustum.setProjection(baseProjection); + float baseNearClip = baseFrustum.getNearClip(); + float baseFarClip = baseFrustum.getFarClip(); + // FIXME Calculate the proper combined projection by using GetProjectionRaw values from both eyes + return toGlm(_system->GetProjectionMatrix((vr::EVREye)0, baseNearClip, baseFarClip)); + } else { + return baseProjection; + } +} + float OpenVrDisplayPlugin::getTargetFrameRate() const { if (forceInterleavedReprojection && !_asyncReprojectionActive) { return TARGET_RATE_OpenVr / 2.0f; diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.h b/plugins/openvr/src/OpenVrDisplayPlugin.h index 062345943a..6aea6ef575 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.h +++ b/plugins/openvr/src/OpenVrDisplayPlugin.h @@ -39,6 +39,7 @@ public: const QString getName() const override { return NAME; } glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const override; + glm::mat4 getCullingProjection(const glm::mat4& baseProjection) const override; void init() override;