From 499879c84e1a593c2c8ac6650d14692ebc65eb02 Mon Sep 17 00:00:00 2001 From: Emil Axelsson Date: Wed, 14 Feb 2018 15:05:52 +0100 Subject: [PATCH] Start to implement stereo support with adaptive stereoscopic depth --- .../openspace/interaction/orbitalnavigator.h | 12 ++ .../openspace/rendering/framebufferrenderer.h | 2 + include/openspace/util/camera.h | 9 +- .../rendering/atmospheredeferredcaster.cpp | 4 +- modules/base/rendering/renderablemodel.cpp | 2 +- .../globebrowsing/rendering/chunkrenderer.cpp | 4 +- .../rendering/renderableplanetprojection.cpp | 2 +- src/engine/wrapper/sgctwindowwrapper.cpp | 2 +- src/interaction/orbitalnavigator.cpp | 62 +++++++++++ src/rendering/framebufferrenderer.cpp | 104 +++++++++--------- src/rendering/renderable.cpp | 2 +- src/util/camera.cpp | 26 +++-- 12 files changed, 160 insertions(+), 71 deletions(-) diff --git a/include/openspace/interaction/orbitalnavigator.h b/include/openspace/interaction/orbitalnavigator.h index 38c569b34b..47f0614412 100644 --- a/include/openspace/interaction/orbitalnavigator.h +++ b/include/openspace/interaction/orbitalnavigator.h @@ -84,6 +84,10 @@ private: properties::FloatProperty _minimumAllowedDistance; properties::FloatProperty _sensitivity; + properties::BoolProperty _useAdaptiveStereoscopicDepth; + properties::FloatProperty _stereoscopicDepthOfFocusSurface; + properties::FloatProperty _staticViewScaleExponent; + MouseStates _mouseStates; SceneGraphNode* _focusNode = nullptr; @@ -193,6 +197,14 @@ private: const glm::dvec3& cameraPosition, const SurfacePositionHandle& positionHandle); + /** + * Get the vector from the camera to the surface of the focus object in world space. + */ + glm::dvec3 cameraToSurfaceVector( + const glm::dvec3& cameraPos, + const glm::dvec3& centerPos, + const SurfacePositionHandle& posHandle); + /** * Calculates a SurfacePositionHandle given a camera position in world space. */ diff --git a/include/openspace/rendering/framebufferrenderer.h b/include/openspace/rendering/framebufferrenderer.h index 6f61cd2238..f8f43ae9e2 100644 --- a/include/openspace/rendering/framebufferrenderer.h +++ b/include/openspace/rendering/framebufferrenderer.h @@ -82,6 +82,8 @@ public: void update() override; void render(float blackoutFactor, bool doPerformanceMeasurements) override; + void performRaycasterTasks(const std::vector& tasks); + void performDeferredTasks(const std::vector& tasks); /** * Update render data diff --git a/include/openspace/util/camera.h b/include/openspace/util/camera.h index 71dd85a0bc..70e7ea88f8 100644 --- a/include/openspace/util/camera.h +++ b/include/openspace/util/camera.h @@ -91,7 +91,7 @@ public: void setPositionVec3(Vec3 pos); void setFocusPositionVec3(Vec3 pos); void setRotation(Quat rotation); - void setScaling(glm::vec2 scaling); + void setScaling(float scaling); void setMaxFov(float fov); void setParent(SceneGraphNode* parent); @@ -106,12 +106,13 @@ public: const Vec3& viewDirectionWorldSpace() const; const Vec3& lookUpVectorCameraSpace() const; const Vec3& lookUpVectorWorldSpace() const; - const glm::vec2& scaling() const; const Mat4& viewRotationMatrix() const; + const Mat4& viewScaleMatrix() const; const Quat& rotationQuaternion() const; float maxFov() const; float sinMaxFov() const; SceneGraphNode* parent() const; + float scaling() const; // @TODO this should simply be called viewMatrix! // Or it needs to be changed so that it actually is combined. Right now it is @@ -186,10 +187,9 @@ private: SyncData _position; SyncData _rotation; - SyncData _scaling; + SyncData _scaling; SceneGraphNode* _parent; - // _focusPosition to be removed Vec3 _focusPosition; float _maxFov; @@ -198,6 +198,7 @@ private: mutable Cached _cachedViewDirection; mutable Cached _cachedLookupVector; mutable Cached _cachedViewRotationMatrix; + mutable Cached _cachedViewScaleMatrix; mutable Cached _cachedCombinedViewMatrix; mutable Cached _cachedSinMaxFov; diff --git a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp index c2842a3a33..52a7594e9c 100644 --- a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp +++ b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp @@ -248,9 +248,7 @@ void AtmosphereDeferredcaster::preRaycast(const RenderData& renderData, program.setUniform("dModelTransformMatrix", _modelTransform); // The following scale comes from PSC transformations. - float fScaleFactor = renderData.camera.scaling().x * - pow(10.0, renderData.camera.scaling().y); - glm::dmat4 dfScaleCamTransf = glm::scale(glm::dvec3(fScaleFactor)); + glm::dmat4 dfScaleCamTransf = glm::scale(glm::dvec3(1.0)); program.setUniform( "dInverseScaleTransformMatrix", glm::inverse(dfScaleCamTransf) diff --git a/modules/base/rendering/renderablemodel.cpp b/modules/base/rendering/renderablemodel.cpp index 9f94d6a74f..6ddf023ca9 100644 --- a/modules/base/rendering/renderablemodel.cpp +++ b/modules/base/rendering/renderablemodel.cpp @@ -208,7 +208,7 @@ void RenderableModel::render(const RenderData& data, RendererTasks&) { glm::vec3 directionToSun = glm::normalize(_sunPos - data.modelTransform.translation); glm::vec3 directionToSunViewSpace = - glm::mat3(data.camera.combinedViewMatrix()) * directionToSun; + glm::normalize(glm::mat3(data.camera.combinedViewMatrix()) * directionToSun); _programObject->setUniform( _uniformCache.directionToSunViewSpace, diff --git a/modules/globebrowsing/rendering/chunkrenderer.cpp b/modules/globebrowsing/rendering/chunkrenderer.cpp index 20c0e3d376..e3b370fc3d 100644 --- a/modules/globebrowsing/rendering/chunkrenderer.cpp +++ b/modules/globebrowsing/rendering/chunkrenderer.cpp @@ -263,7 +263,7 @@ void ChunkRenderer::setCommonUniforms(ghoul::opengl::ProgramObject& programObjec glm::vec3 directionToSunCameraSpace = glm::vec3(viewTransform * glm::dvec4(directionToSunWorldSpace, 0)); programObject.setUniform( - "lightDirectionCameraSpace", -directionToSunCameraSpace); + "lightDirectionCameraSpace", -glm::normalize(directionToSunCameraSpace)); } if (chunk.owner().generalProperties().performShading) { @@ -469,7 +469,7 @@ void ChunkRenderer::renderChunkLocally(const Chunk& chunk, const RenderData& dat if (_layerManager->layerGroup(layergroupid::HeightLayers).activeLayers().size() > 0) { // Apply an extra scaling to the height if the object is scaled programObject->setUniform( - "heightScale", static_cast(data.modelTransform.scale)); + "heightScale", static_cast(data.modelTransform.scale * data.camera.scaling())); } setCommonUniforms(*programObject, chunk, data); diff --git a/modules/spacecraftinstruments/rendering/renderableplanetprojection.cpp b/modules/spacecraftinstruments/rendering/renderableplanetprojection.cpp index 3430224be6..715c87c709 100644 --- a/modules/spacecraftinstruments/rendering/renderableplanetprojection.cpp +++ b/modules/spacecraftinstruments/rendering/renderableplanetprojection.cpp @@ -537,7 +537,7 @@ void RenderablePlanetProjection::render(const RenderData& data, RendererTasks&) _projectionComponent.generateMipMap(); } - _camScaling = data.camera.scaling(); + _camScaling = glm::vec2(1, 0); // Unit scaling _up = data.camera.lookUpVectorCameraSpace(); if (_capture && _projectionComponent.doesPerformProjection()) { diff --git a/src/engine/wrapper/sgctwindowwrapper.cpp b/src/engine/wrapper/sgctwindowwrapper.cpp index fef3b7b9ff..d9f2801978 100644 --- a/src/engine/wrapper/sgctwindowwrapper.cpp +++ b/src/engine/wrapper/sgctwindowwrapper.cpp @@ -51,7 +51,7 @@ namespace { namespace openspace { SGCTWindowWrapper::SGCTWindowWrapper() - : _eyeSeparation(EyeSeparationInfo, 0.f, 0.f, 10.f) + : _eyeSeparation(EyeSeparationInfo, 0.f, 0.f, 0.2f) , _showStatsGraph(ShowStatsGraphInfo, false) { _showStatsGraph.onChange([this](){ diff --git a/src/interaction/orbitalnavigator.cpp b/src/interaction/orbitalnavigator.cpp index 06ed097435..b5fbecd444 100644 --- a/src/interaction/orbitalnavigator.cpp +++ b/src/interaction/orbitalnavigator.cpp @@ -84,6 +84,33 @@ namespace { "Minimum allowed distance", "" // @TODO Missing documentation }; + + static const openspace::properties::Property::PropertyInfo + UseAdaptiveStereoscopicDepthInfo = { + "UseAdaptiveStereoscopicDepth", + "Adaptive Steroscopic Depth", + "Dynamically adjust the view scaling based on the distance to the surface of " + "the focus node. If enabled, view scale will be set to " + "StereoscopicDepthOfFocusSurface / distance. " + "If disabled, view scale will be set to 10^StaticViewScaleExponent." + }; + + static const openspace::properties::Property::PropertyInfo + StaticViewScaleExponentInfo = { + "StaticViewScaleExponent", + "Static View Scale Exponent", + "Statically scale the world by 10^StaticViewScaleExponent. " + "Only used if UseAdaptiveStereoscopicDepthInfo is set to false." + }; + + static const openspace::properties::Property::PropertyInfo + StereoscopicDepthOfFocusSurfaceInfo = { + "StereoscopicDepthOfFocusSurface", + "Stereoscopic depth of the surface in focus", + "Set the stereoscopically perceived distance (in meters) to the surface of " + "the focus node. " + "Only used if UseAdaptiveStereoscopicDepthInfo is set to true." + }; } // namespace namespace openspace::interaction { @@ -107,6 +134,9 @@ OrbitalNavigator::OrbitalNavigator() , _minimumAllowedDistance(MinimumDistanceInfo, 10.0f, 0.0f, 10000.f) , _sensitivity(SensitivityInfo, 20.0f, 1.0f, 50.f) , _mouseStates(_sensitivity * pow(10.0, -4), 1 / (_friction.friction + 0.0000001)) + , _useAdaptiveStereoscopicDepth(UseAdaptiveStereoscopicDepthInfo, true) + , _staticViewScaleExponent(StaticViewScaleExponentInfo, 0.f, -30, 10) + , _stereoscopicDepthOfFocusSurface(StereoscopicDepthOfFocusSurfaceInfo, 8, 0.25, 100) { auto smoothStep = [](double t) { @@ -158,6 +188,10 @@ OrbitalNavigator::OrbitalNavigator() addProperty(_followFocusNodeRotationDistance); addProperty(_minimumAllowedDistance); addProperty(_sensitivity); + + addProperty(_useAdaptiveStereoscopicDepth); + addProperty(_staticViewScaleExponent); + addProperty(_stereoscopicDepthOfFocusSurface); } OrbitalNavigator::~OrbitalNavigator() {} @@ -263,9 +297,37 @@ void OrbitalNavigator::updateCameraStateFromMouseStates(Camera& camera, double d // Update the camera state camera.setPositionVec3(camPos); camera.setRotation(camRot.globalRotation * camRot.localRotation); + + if (_useAdaptiveStereoscopicDepth) { + glm::vec3 surfaceToCamera = static_cast( + cameraToSurfaceVector(camPos, centerPos, posHandle) + ); + camera.setScaling( + _stereoscopicDepthOfFocusSurface / glm::length(surfaceToCamera) + ); + } else { + camera.setScaling(glm::pow(10.f, _staticViewScaleExponent)); + } } } +glm::dvec3 OrbitalNavigator::cameraToSurfaceVector( + const glm::dvec3& camPos, + const glm::dvec3& centerPos, + const SurfacePositionHandle& posHandle) +{ + glm::dmat4 modelTransform = _focusNode->modelTransform(); + glm::dvec3 posDiff = camPos - centerPos; + glm::dvec3 centerToActualSurfaceModelSpace = + posHandle.centerToReferenceSurface + + posHandle.referenceSurfaceOutDirection * posHandle.heightToSurface; + + glm::dvec3 centerToActualSurface = + glm::dmat3(modelTransform) * centerToActualSurfaceModelSpace; + + return centerToActualSurface - posDiff; +} + void OrbitalNavigator::setFocusNode(SceneGraphNode* focusNode) { _focusNode = focusNode; diff --git a/src/rendering/framebufferrenderer.cpp b/src/rendering/framebufferrenderer.cpp index 7b304eaabc..87ff1be165 100644 --- a/src/rendering/framebufferrenderer.cpp +++ b/src/rendering/framebufferrenderer.cpp @@ -925,19 +925,13 @@ void FramebufferRenderer::render(float blackoutFactor, bool doPerformanceMeasure return; } - glEnable(GL_DEPTH_TEST); - - - Time time = OsEng.timeManager().time(); - - RenderData data = { *_camera, psc(), time, doPerformanceMeasurements, 0, {} }; - RendererTasks tasks; - // Capture standard fbo GLint defaultFbo; glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFbo); glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer); + glEnable(GL_DEPTH_TEST); + // deferred g-buffer GLenum textureBuffers[3] = { GL_COLOR_ATTACHMENT0, @@ -952,6 +946,11 @@ void FramebufferRenderer::render(float blackoutFactor, bool doPerformanceMeasure glDisablei(GL_BLEND, 2); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + Time time = OsEng.timeManager().time(); + RenderData data = { *_camera, psc(), time, doPerformanceMeasurements, 0,{} }; + RendererTasks tasks; + data.renderBinMask = static_cast(Renderable::RenderBin::Background); _scene->render(data, tasks); data.renderBinMask = static_cast(Renderable::RenderBin::Opaque); @@ -961,7 +960,49 @@ void FramebufferRenderer::render(float blackoutFactor, bool doPerformanceMeasure data.renderBinMask = static_cast(Renderable::RenderBin::Overlay); _scene->render(data, tasks); - for (const RaycasterTask& raycasterTask : tasks.raycasterTasks) { + + performRaycasterTasks(tasks.raycasterTasks); + + glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); + GLenum dBuffer[1] = { GL_COLOR_ATTACHMENT0 }; + glDrawBuffers(1, dBuffer); + glClear(GL_COLOR_BUFFER_BIT); + + performDeferredTasks(tasks.deferredcasterTasks); + + if (!tasks.deferredcasterTasks.empty()) { + // JCC: Temporarily disabled. Need to test it on mac and linux before final + // merging. + /*glBindFramebuffer(GL_READ_FRAMEBUFFER, _deferredFramebuffer); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, defaultFbo); + GLenum dBuffer[] = { GL_COLOR_ATTACHMENT0 }; + glDrawBuffers(1, dBuffer); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glBlitFramebuffer(0, 0, GLsizei(_resolution.x), GLsizei(_resolution.y), + 0, 0, GLsizei(_resolution.x), GLsizei(_resolution.y), + GL_COLOR_BUFFER_BIT, GL_NEAREST); + */ + //glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); + } else { + _resolveProgram->activate(); + + ghoul::opengl::TextureUnit mainColorTextureUnit; + mainColorTextureUnit.activate(); + + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture); + _resolveProgram->setUniform(_uniformCache.mainColorTexture, mainColorTextureUnit); + _resolveProgram->setUniform(_uniformCache.blackoutFactor, blackoutFactor); + _resolveProgram->setUniform(_uniformCache.nAaSamples, _nAaSamples); + glBindVertexArray(_screenQuad); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); + + _resolveProgram->deactivate(); + } +} + +void FramebufferRenderer::performRaycasterTasks(const std::vector& tasks) { + for (const RaycasterTask& raycasterTask : tasks) { VolumeRaycaster* raycaster = raycasterTask.raycaster; glBindFramebuffer(GL_FRAMEBUFFER, _exitFramebuffer); @@ -1041,18 +1082,15 @@ void FramebufferRenderer::render(float blackoutFactor, bool doPerformanceMeasure LWARNING("Raycaster is not attached when trying to perform raycaster task"); } } +} +void FramebufferRenderer::performDeferredTasks(const std::vector& tasks) { // g-buffer - if (!tasks.deferredcasterTasks.empty()) { + if (!tasks.empty()) { //glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _deferredFramebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); - GLenum dBuffer[1] = { GL_COLOR_ATTACHMENT0 }; - glDrawBuffers(1, dBuffer); - glClear(GL_COLOR_BUFFER_BIT); - bool firstPaint = true; - for (const DeferredcasterTask& deferredcasterTask : tasks.deferredcasterTasks) { + for (const DeferredcasterTask& deferredcasterTask : tasks) { Deferredcaster* deferredcaster = deferredcasterTask.deferredcaster; @@ -1125,45 +1163,13 @@ void FramebufferRenderer::render(float blackoutFactor, bool doPerformanceMeasure if (firstPaint) { firstPaint = false; } - } - else { + } else { LWARNING( "Deferredcaster is not attached when trying to perform deferred task" ); } } } - - if (!tasks.deferredcasterTasks.empty()) { - // JCC: Temporarily disabled. Need to test it on mac and linux before final - // merging. - /*glBindFramebuffer(GL_READ_FRAMEBUFFER, _deferredFramebuffer); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, defaultFbo); - GLenum dBuffer[] = { GL_COLOR_ATTACHMENT0 }; - glDrawBuffers(1, dBuffer); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glBlitFramebuffer(0, 0, GLsizei(_resolution.x), GLsizei(_resolution.y), - 0, 0, GLsizei(_resolution.x), GLsizei(_resolution.y), - GL_COLOR_BUFFER_BIT, GL_NEAREST); - */ - //glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); - } else { - glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); - _resolveProgram->activate(); - - ghoul::opengl::TextureUnit mainColorTextureUnit; - mainColorTextureUnit.activate(); - - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture); - _resolveProgram->setUniform(_uniformCache.mainColorTexture, mainColorTextureUnit); - _resolveProgram->setUniform(_uniformCache.blackoutFactor, blackoutFactor); - _resolveProgram->setUniform(_uniformCache.nAaSamples, _nAaSamples); - glBindVertexArray(_screenQuad); - glDrawArrays(GL_TRIANGLES, 0, 6); - glBindVertexArray(0); - - _resolveProgram->deactivate(); - } } void FramebufferRenderer::setScene(Scene* scene) { diff --git a/src/rendering/renderable.cpp b/src/rendering/renderable.cpp index 6ab6e314c4..7b12f3552d 100644 --- a/src/rendering/renderable.cpp +++ b/src/rendering/renderable.cpp @@ -187,7 +187,7 @@ void Renderable::setPscUniforms(ghoul::opengl::ProgramObject& program, program.setUniform("campos", camera.position().vec4()); program.setUniform("objpos", position.vec4()); program.setUniform("camrot", glm::mat4(camera.viewRotationMatrix())); - program.setUniform("scaling", camera.scaling()); + program.setUniform("scaling", glm::vec2(1, 0)); } Renderable::RenderBin Renderable::renderBin() const { diff --git a/src/util/camera.cpp b/src/util/camera.cpp index b6483cc7cd..f8c5454c2a 100644 --- a/src/util/camera.cpp +++ b/src/util/camera.cpp @@ -49,8 +49,6 @@ namespace openspace { : _focusPosition() , _maxFov(0.f) { - - _scaling = glm::vec2(1.f, 0.f); _position = Vec3(1.0, 1.0, 1.0); Vec3 eulerAngles(1.0, 1.0, 1.0); _rotation = Quat(eulerAngles); @@ -60,7 +58,6 @@ namespace openspace { : sgctInternal(o.sgctInternal) , _position(o._position) , _rotation(o._rotation) - , _scaling(o._scaling) , _focusPosition(o._focusPosition) , _maxFov(o._maxFov) , _cachedViewDirection(o._cachedViewDirection) @@ -91,9 +88,11 @@ namespace openspace { _cachedCombinedViewMatrix.isDirty = true; } - void Camera::setScaling(glm::vec2 scaling) { + void Camera::setScaling(float scaling) { std::lock_guard _lock(_mutex); - _scaling = std::move(scaling); + _scaling = scaling; + _cachedViewScaleMatrix.isDirty = true; + _cachedCombinedViewMatrix.isDirty = true; } void Camera::setMaxFov(float fov) { @@ -154,10 +153,6 @@ namespace openspace { return _cachedLookupVector.datum; } - const glm::vec2& Camera::scaling() const { - return _scaling; - } - float Camera::maxFov() const { return _maxFov; } @@ -174,6 +169,10 @@ namespace openspace { return _parent; } + float Camera::scaling() const { + return _scaling; + } + const Camera::Mat4& Camera::viewRotationMatrix() const { if (_cachedViewRotationMatrix.isDirty) { _cachedViewRotationMatrix.datum = glm::mat4_cast( @@ -183,6 +182,14 @@ namespace openspace { return _cachedViewRotationMatrix.datum; } + const Camera::Mat4& Camera::viewScaleMatrix() const + { + if (_cachedViewScaleMatrix.isDirty) { + _cachedViewScaleMatrix.datum = glm::scale(glm::vec3(_scaling)); + } + return _cachedViewScaleMatrix.datum; + } + const Camera::Quat& Camera::rotationQuaternion() const { return _rotation; } @@ -193,6 +200,7 @@ namespace openspace { glm::inverse(glm::translate(Mat4(1.0), static_cast(_position))); _cachedCombinedViewMatrix.datum = Mat4(sgctInternal.viewMatrix()) * + Mat4(viewScaleMatrix()) * Mat4(viewRotationMatrix()) * cameraTranslation; _cachedCombinedViewMatrix.isDirty = true;