From b59ec07171505422e958f6c87a3cce44bc302130 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 29 Sep 2017 09:49:08 -0700 Subject: [PATCH] move hud rendering to render thread, still need to separate out hud overlays --- interface/resources/qml/desktop/Desktop.qml | 10 +-- interface/resources/shaders/hmd_ui.frag | 30 ------- interface/resources/shaders/hmd_ui.vert | 28 ------ interface/src/Application.cpp | 18 +--- interface/src/Application.h | 2 +- .../ControllerScriptingInterface.cpp | 4 +- .../scripting/ControllerScriptingInterface.h | 2 +- .../scripting/DesktopScriptingInterface.cpp | 2 +- .../src/scripting/DesktopScriptingInterface.h | 2 +- interface/src/ui/overlays/Base3DOverlay.cpp | 12 ++- interface/src/ui/overlays/Base3DOverlay.h | 3 + interface/src/ui/overlays/Circle3DOverlay.cpp | 2 +- interface/src/ui/overlays/Cube3DOverlay.cpp | 2 +- interface/src/ui/overlays/Image3DOverlay.cpp | 2 +- interface/src/ui/overlays/Overlay.cpp | 14 --- interface/src/ui/overlays/Overlay.h | 3 - interface/src/ui/overlays/Overlays.cpp | 62 +------------ interface/src/ui/overlays/Overlays.h | 6 -- interface/src/ui/overlays/OverlaysPayload.cpp | 3 +- interface/src/ui/overlays/Shape3DOverlay.cpp | 2 +- interface/src/ui/overlays/Sphere3DOverlay.cpp | 2 +- .../src/display-plugins/CompositorHelper.h | 2 +- .../display-plugins/OpenGLDisplayPlugin.cpp | 54 ++++-------- .../src/display-plugins/OpenGLDisplayPlugin.h | 12 +-- .../display-plugins/hmd/HmdDisplayPlugin.cpp | 88 ++++++------------- .../display-plugins/hmd/HmdDisplayPlugin.h | 15 ++-- libraries/gpu/src/gpu/Batch.h | 2 +- libraries/gpu/src/gpu/Frame.h | 4 - .../plugins/src/plugins/DisplayPlugin.cpp | 9 ++ libraries/plugins/src/plugins/DisplayPlugin.h | 9 +- .../render-utils/src/MeshPartPayload.cpp | 2 +- libraries/render-utils/src/Model.h | 2 + .../render-utils/src/RenderDeferredTask.cpp | 15 ++++ .../render-utils/src/RenderDeferredTask.h | 8 ++ libraries/render-utils/src/hmd_ui.slf | 37 ++++++++ libraries/render-utils/src/hmd_ui.slv | 36 ++++++++ libraries/render/src/render/Args.h | 3 + .../controllerModules/hudOverlayPointer.js | 10 +-- scripts/system/libraries/toolBars.js | 10 +-- 39 files changed, 224 insertions(+), 305 deletions(-) delete mode 100644 interface/resources/shaders/hmd_ui.frag delete mode 100644 interface/resources/shaders/hmd_ui.vert create mode 100644 libraries/render-utils/src/hmd_ui.slf create mode 100644 libraries/render-utils/src/hmd_ui.slv diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index 579b4e7fd6..d5b01fd494 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -88,7 +88,7 @@ FocusScope { return; } var oldRecommendedRect = recommendedRect; - var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedOverlayRect(); + var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedHUDRect(); var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y, newRecommendedRectJS.width, newRecommendedRectJS.height); @@ -271,7 +271,7 @@ FocusScope { var oldRecommendedRect = recommendedRect; var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height }; - var newRecommendedRect = Controller.getRecommendedOverlayRect(); + var newRecommendedRect = Controller.getRecommendedHUDRect(); var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height }; var windows = d.getTopLevelWindows(); for (var i = 0; i < windows.length; ++i) { @@ -393,7 +393,7 @@ FocusScope { return; } - var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedOverlayRect(); + var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedHUDRect(); var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y, newRecommendedRectJS.width, newRecommendedRectJS.height); @@ -425,7 +425,7 @@ FocusScope { var oldRecommendedRect = recommendedRect; var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height }; - var newRecommendedRect = Controller.getRecommendedOverlayRect(); + var newRecommendedRect = Controller.getRecommendedHUDRect(); var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height }; repositionWindow(targetWindow, false, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions); } @@ -442,7 +442,7 @@ FocusScope { return; } - var recommended = Controller.getRecommendedOverlayRect(); + var recommended = Controller.getRecommendedHUDRect(); var maxX = recommended.x + recommended.width; var maxY = recommended.y + recommended.height; var newPosition = Qt.vector2d(targetWindow.x, targetWindow.y); diff --git a/interface/resources/shaders/hmd_ui.frag b/interface/resources/shaders/hmd_ui.frag deleted file mode 100644 index 5341ab575d..0000000000 --- a/interface/resources/shaders/hmd_ui.frag +++ /dev/null @@ -1,30 +0,0 @@ -// -// Created by Bradley Austin Davis on 2016/07/11 -// Copyright 2013-2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -uniform sampler2D sampler; - -struct OverlayData { - mat4 mvp; - float alpha; -}; - -layout(std140) uniform overlayBuffer { - OverlayData overlay; -}; - -in vec2 vTexCoord; - -out vec4 FragColor; - -void main() { - FragColor = texture(sampler, vTexCoord); - FragColor.a *= overlay.alpha; - if (FragColor.a <= 0.0) { - discard; - } -} \ No newline at end of file diff --git a/interface/resources/shaders/hmd_ui.vert b/interface/resources/shaders/hmd_ui.vert deleted file mode 100644 index 41b9b3666f..0000000000 --- a/interface/resources/shaders/hmd_ui.vert +++ /dev/null @@ -1,28 +0,0 @@ -// -// Created by Bradley Austin Davis on 2016/07/11 -// Copyright 2013-2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -struct OverlayData { - mat4 mvp; - float alpha; -}; - -layout(std140) uniform overlayBuffer { - OverlayData overlay; -}; - -mat4 mvp = overlay.mvp; - -layout(location = 0) in vec3 Position; -layout(location = 3) in vec2 TexCoord; - -out vec2 vTexCoord; - -void main() { - gl_Position = mvp * vec4(Position, 1); - vTexCoord = TexCoord; -} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6668f5cfa0..5e52b443e1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2590,6 +2590,8 @@ 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()); + renderArgs._hudOperator = displayPlugin->getHUDOperator(); + renderArgs._hudTexture = _applicationOverlay.getOverlayTexture(); auto baseProjection = renderArgs.getViewFrustum().getProjection(); if (displayPlugin->isStereo()) { // Stereo modes will typically have a larger projection matrix overall, @@ -2632,24 +2634,12 @@ void Application::paintGL() { displaySide(&renderArgs, _myCamera); } - gpu::Batch postCompositeBatch; - { - PROFILE_RANGE(render, "/postComposite"); - PerformanceTimer perfTimer("postComposite"); - renderArgs._batch = &postCompositeBatch; - renderArgs._batch->setViewportTransform(ivec4(0, 0, finalFramebufferSize.width(), finalFramebufferSize.height())); - renderArgs._batch->setViewTransform(renderArgs.getViewFrustum().getView()); - _overlays.render3DHUDOverlays(&renderArgs); - } - auto frame = _gpuContext->endFrame(); frame->frameIndex = _frameCount; frame->framebuffer = finalFramebuffer; frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer){ DependencyManager::get()->releaseFramebuffer(framebuffer); }; - frame->overlay = _applicationOverlay.getOverlayTexture(); - frame->postCompositeBatch = postCompositeBatch; // deliver final scene rendering commands to the display plugin { PROFILE_RANGE(render, "/pluginOutput"); @@ -7209,11 +7199,11 @@ glm::uvec2 Application::getUiSize() const { return result; } -QRect Application::getRecommendedOverlayRect() const { +QRect Application::getRecommendedHUDRect() const { auto uiSize = getUiSize(); QRect result(0, 0, uiSize.x, uiSize.y); if (_displayPlugin) { - result = getActiveDisplayPlugin()->getRecommendedOverlayRect(); + result = getActiveDisplayPlugin()->getRecommendedHUDRect(); } return result; } diff --git a/interface/src/Application.h b/interface/src/Application.h index 74e84ae92c..7d84504f70 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -157,7 +157,7 @@ public: QRect getRenderingGeometry() const; glm::uvec2 getUiSize() const; - QRect getRecommendedOverlayRect() const; + QRect getRecommendedHUDRect() const; QSize getDeviceSize() const; bool hasFocus() const; diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 9fbd01817a..5c55e2094b 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -91,8 +91,8 @@ glm::vec2 ControllerScriptingInterface::getViewportDimensions() const { return qApp->getUiSize(); } -QVariant ControllerScriptingInterface::getRecommendedOverlayRect() const { - auto rect = qApp->getRecommendedOverlayRect(); +QVariant ControllerScriptingInterface::getRecommendedHUDRect() const { + auto rect = qApp->getRecommendedHUDRect(); return qRectToVariant(rect); } diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index 6d197477bb..8c825a17de 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -66,7 +66,7 @@ public slots: virtual void releaseEntityClickEvents(); virtual glm::vec2 getViewportDimensions() const; - virtual QVariant getRecommendedOverlayRect() const; + virtual QVariant getRecommendedHUDRect() const; signals: void keyPressEvent(const KeyEvent& event); diff --git a/interface/src/scripting/DesktopScriptingInterface.cpp b/interface/src/scripting/DesktopScriptingInterface.cpp index efab178798..34f196ac70 100644 --- a/interface/src/scripting/DesktopScriptingInterface.cpp +++ b/interface/src/scripting/DesktopScriptingInterface.cpp @@ -29,7 +29,7 @@ int DesktopScriptingInterface::getHeight() { return size.height(); } -void DesktopScriptingInterface::setOverlayAlpha(float alpha) { +void DesktopScriptingInterface::setHUDAlpha(float alpha) { qApp->getApplicationCompositor().setAlpha(alpha); } diff --git a/interface/src/scripting/DesktopScriptingInterface.h b/interface/src/scripting/DesktopScriptingInterface.h index 2825065e90..e62a3584d6 100644 --- a/interface/src/scripting/DesktopScriptingInterface.h +++ b/interface/src/scripting/DesktopScriptingInterface.h @@ -22,7 +22,7 @@ class DesktopScriptingInterface : public QObject, public Dependency { Q_PROPERTY(int height READ getHeight) // Physical height of screen(s) including task bars and system menus public: - Q_INVOKABLE void setOverlayAlpha(float alpha); + Q_INVOKABLE void setHUDAlpha(float alpha); Q_INVOKABLE void show(const QString& path, const QString& title); int getWidth(); diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 9afab80243..e711767ec2 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -26,7 +26,8 @@ Base3DOverlay::Base3DOverlay() : _isSolid(DEFAULT_IS_SOLID), _isDashedLine(DEFAULT_IS_DASHED_LINE), _ignoreRayIntersection(false), - _drawInFront(false) + _drawInFront(false), + _drawHUDLayer(false) { } @@ -38,6 +39,7 @@ Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) : _isDashedLine(base3DOverlay->_isDashedLine), _ignoreRayIntersection(base3DOverlay->_ignoreRayIntersection), _drawInFront(base3DOverlay->_drawInFront), + _drawHUDLayer(base3DOverlay->_drawHUDLayer), _isGrabbable(base3DOverlay->_isGrabbable) { setTransform(base3DOverlay->getTransform()); @@ -125,13 +127,19 @@ void Base3DOverlay::setProperties(const QVariantMap& originalProperties) { bool needRenderItemUpdate = false; auto drawInFront = properties["drawInFront"]; - if (drawInFront.isValid()) { bool value = drawInFront.toBool(); setDrawInFront(value); needRenderItemUpdate = true; } + auto drawHUDLayer = properties["drawHUDLayer"]; + if (drawHUDLayer.isValid()) { + bool value = drawHUDLayer.toBool(); + setDrawHUDLayer(value); + needRenderItemUpdate = true; + } + auto isGrabbable = properties["grabbable"]; if (isGrabbable.isValid()) { setIsGrabbable(isGrabbable.toBool()); diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index 93a973e60a..190d2f6cc6 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -41,6 +41,7 @@ public: bool getIsSolidLine() const { return !_isDashedLine; } bool getIgnoreRayIntersection() const { return _ignoreRayIntersection; } bool getDrawInFront() const { return _drawInFront; } + bool getDrawHUDLayer() const { return _drawHUDLayer; } bool getIsGrabbable() const { return _isGrabbable; } void setLineWidth(float lineWidth) { _lineWidth = lineWidth; } @@ -48,6 +49,7 @@ public: void setIsDashedLine(bool isDashedLine) { _isDashedLine = isDashedLine; } void setIgnoreRayIntersection(bool value) { _ignoreRayIntersection = value; } void setDrawInFront(bool value) { _drawInFront = value; } + void setDrawHUDLayer(bool value) { _drawHUDLayer = value; } void setIsGrabbable(bool value) { _isGrabbable = value; } virtual AABox getBounds() const override = 0; @@ -81,6 +83,7 @@ protected: bool _isDashedLine; bool _ignoreRayIntersection; bool _drawInFront; + bool _drawHUDLayer; bool _isGrabbable { false }; mutable bool _renderTransformDirty{ true }; diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index 4e51844d21..536b2c764f 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -263,7 +263,7 @@ const render::ShapeKey Circle3DOverlay::getShapeKey() { if (isTransparent()) { builder.withTranslucent(); } - if (!getIsSolid() || shouldDrawHUDLayer()) { + if (!getIsSolid()) { builder.withUnlit().withDepthBias(); } return builder.build(); diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 0ac9dba34b..b6df1dbc31 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -113,7 +113,7 @@ const render::ShapeKey Cube3DOverlay::getShapeKey() { if (isTransparent()) { builder.withTranslucent(); } - if (!getIsSolid() || shouldDrawHUDLayer()) { + if (!getIsSolid()) { builder.withUnlit().withDepthBias(); } return builder.build(); diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index 998cc312eb..d0024d9710 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -132,7 +132,7 @@ void Image3DOverlay::render(RenderArgs* args) { const render::ShapeKey Image3DOverlay::getShapeKey() { auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); - if (_emissive || shouldDrawHUDLayer()) { + if (_emissive) { builder.withUnlit(); } if (isTransparent()) { diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index 8b88d1e963..01ad56f20e 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -32,7 +32,6 @@ Overlay::Overlay() : _colorPulse(0.0f), _color(DEFAULT_OVERLAY_COLOR), _visible(true), - _drawHUDLayer(false), _anchor(NO_ANCHOR) { } @@ -51,7 +50,6 @@ Overlay::Overlay(const Overlay* overlay) : _colorPulse(overlay->_colorPulse), _color(overlay->_color), _visible(overlay->_visible), - _drawHUDLayer(overlay->_drawHUDLayer), _anchor(overlay->_anchor) { } @@ -90,11 +88,6 @@ void Overlay::setProperties(const QVariantMap& properties) { setColorPulse(properties["colorPulse"].toFloat()); } - if (properties["drawHUDLayer"].isValid()) { - bool drawHUDLayer = properties["drawHUDLayer"].toBool(); - setDrawHUDLayer(drawHUDLayer); - } - if (properties["visible"].isValid()) { bool visible = properties["visible"].toBool(); setVisible(visible); @@ -170,13 +163,6 @@ float Overlay::getAlpha() { return (_alphaPulse >= 0.0f) ? _alpha * pulseLevel : _alpha * (1.0f - pulseLevel); } -void Overlay::setDrawHUDLayer(bool drawHUDLayer) { - if (drawHUDLayer != _drawHUDLayer) { - qApp->getOverlays().setOverlayDrawHUDLayer(getOverlayID(), drawHUDLayer); - _drawHUDLayer = drawHUDLayer; - } -} - // pulse travels from min to max, then max to min in one period. float Overlay::updatePulse() { if (_pulsePeriod <= 0.0f) { diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index db2979b4d5..1c35f4d8a5 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -58,7 +58,6 @@ public: virtual bool is3D() const = 0; bool isLoaded() { return _isLoaded; } bool getVisible() const { return _visible; } - bool shouldDrawHUDLayer() const { return _drawHUDLayer; } virtual bool isTransparent() { return getAlphaPulse() != 0.0f || getAlpha() != 1.0f; }; xColor getColor(); float getAlpha(); @@ -74,7 +73,6 @@ public: // setters void setVisible(bool visible) { _visible = visible; } - void setDrawHUDLayer(bool drawHUDLayer); void setColor(const xColor& color) { _color = color; } void setAlpha(float alpha) { _alpha = alpha; } void setAnchor(Anchor anchor) { _anchor = anchor; } @@ -117,7 +115,6 @@ protected: xColor _color; bool _visible; // should the overlay be drawn at all - bool _drawHUDLayer; // should the overlay be drawn on the HUD layer Anchor _anchor; unsigned int _stackOrder { 0 }; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index c93d225718..0280cf2038 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -37,29 +37,22 @@ #include "Web3DOverlay.h" #include -#include "render/ShapePipeline.h" - Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays") extern void initOverlay3DPipelines(render::ShapePlumber& plumber, bool depthTest = false); void Overlays::cleanupAllOverlays() { QMap overlaysHUD; - QMap overlays3DHUD; QMap overlaysWorld; { QMutexLocker locker(&_mutex); overlaysHUD.swap(_overlaysHUD); - overlays3DHUD.swap(_overlays3DHUD); overlaysWorld.swap(_overlaysWorld); } foreach(Overlay::Pointer overlay, overlaysHUD) { _overlaysToDelete.push_back(overlay); } - foreach(Overlay::Pointer overlay, overlays3DHUD) { - _overlaysToDelete.push_back(overlay); - } foreach(Overlay::Pointer overlay, overlaysWorld) { _overlaysToDelete.push_back(overlay); } @@ -73,8 +66,6 @@ void Overlays::init() { #if OVERLAY_PANELS _scriptEngine = new QScriptEngine(); #endif - _shapePlumber = std::make_shared(); - initOverlay3DPipelines(*_shapePlumber, true); } void Overlays::update(float deltatime) { @@ -83,9 +74,6 @@ void Overlays::update(float deltatime) { foreach(const auto& thisOverlay, _overlaysHUD) { thisOverlay->update(deltatime); } - foreach(const auto& thisOverlay, _overlays3DHUD) { - thisOverlay->update(deltatime); - } foreach(const auto& thisOverlay, _overlaysWorld) { thisOverlay->update(deltatime); } @@ -142,23 +130,6 @@ void Overlays::renderHUD(RenderArgs* renderArgs) { } } -void Overlays::render3DHUDOverlays(RenderArgs* renderArgs) { - PROFILE_RANGE(render_overlays, __FUNCTION__); - gpu::Batch& batch = *renderArgs->_batch; - - auto textureCache = DependencyManager::get(); - - QMutexLocker lock(&_mutex); - foreach(Overlay::Pointer thisOverlay, _overlays3DHUD) { - // Reset necessary batch pipeline settings between overlays - batch.setResourceTexture(0, textureCache->getWhiteTexture()); // FIXME - do we really need to do this?? - batch.setModelTransform(Transform()); - - renderArgs->_shapePipeline = _shapePlumber->pickPipeline(renderArgs, thisOverlay->getShapeKey()); - thisOverlay->render(renderArgs); - } -} - void Overlays::disable() { _enabled = false; } @@ -173,8 +144,6 @@ Overlay::Pointer Overlays::getOverlay(OverlayID id) const { QMutexLocker locker(&_mutex); if (_overlaysHUD.contains(id)) { return _overlaysHUD[id]; - } else if (_overlays3DHUD.contains(id)) { - return _overlays3DHUD[id]; } else if (_overlaysWorld.contains(id)) { return _overlaysWorld[id]; } @@ -232,7 +201,7 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) { OverlayID thisID = OverlayID(QUuid::createUuid()); overlay->setOverlayID(thisID); overlay->setStackOrder(_stackOrder++); - if (overlay->is3D() && !overlay->shouldDrawHUDLayer()) { + if (overlay->is3D()) { { QMutexLocker locker(&_mutex); _overlaysWorld[thisID] = overlay; @@ -242,9 +211,6 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) { render::Transaction transaction; overlay->addToScene(overlay, scene, transaction); scene->enqueueTransaction(transaction); - } else if (overlay->is3D() && overlay->shouldDrawHUDLayer()) { - QMutexLocker locker(&_mutex); - _overlays3DHUD[thisID] = overlay; } else { QMutexLocker locker(&_mutex); _overlaysHUD[thisID] = overlay; @@ -253,28 +219,6 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) { return thisID; } -void Overlays::setOverlayDrawHUDLayer(const OverlayID& id, const bool drawHUDLayer) { - QMutexLocker locker(&_mutex); - if (drawHUDLayer && _overlaysWorld.contains(id)) { - std::shared_ptr overlay = _overlaysWorld.take(id); - render::ScenePointer scene = qApp->getMain3DScene(); - render::Transaction transaction; - auto itemID = overlay->getRenderItemID(); - if (render::Item::isValidID(itemID)) { - overlay->removeFromScene(overlay, scene, transaction); - scene->enqueueTransaction(transaction); - } - _overlays3DHUD[id] = overlay; - } else if (!drawHUDLayer && _overlays3DHUD.contains(id)) { - std::shared_ptr overlay = _overlays3DHUD.take(id); - render::ScenePointer scene = qApp->getMain3DScene(); - render::Transaction transaction; - overlay->addToScene(overlay, scene, transaction); - scene->enqueueTransaction(transaction); - _overlaysWorld[id] = overlay; - } -} - OverlayID Overlays::cloneOverlay(OverlayID id) { if (QThread::currentThread() != thread()) { OverlayID result; @@ -361,8 +305,6 @@ void Overlays::deleteOverlay(OverlayID id) { QMutexLocker locker(&_mutex); if (_overlaysHUD.contains(id)) { overlayToDelete = _overlaysHUD.take(id); - } else if (_overlays3DHUD.contains(id)) { - overlayToDelete = _overlays3DHUD.take(id); } else if (_overlaysWorld.contains(id)) { overlayToDelete = _overlaysWorld.take(id); } else { @@ -771,7 +713,7 @@ bool Overlays::isAddedOverlay(OverlayID id) { } QMutexLocker locker(&_mutex); - return _overlaysHUD.contains(id) || _overlays3DHUD.contains(id) || _overlaysWorld.contains(id); + return _overlaysHUD.contains(id) || _overlaysWorld.contains(id); } void Overlays::sendMousePressOnOverlay(const OverlayID& overlayID, const PointerEvent& event) { diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 1e85562485..732a437eae 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -90,7 +90,6 @@ public: void init(); void update(float deltatime); void renderHUD(RenderArgs* renderArgs); - void render3DHUDOverlays(RenderArgs* renderArgs); void disable(); void enable(); @@ -103,8 +102,6 @@ public: OverlayID addOverlay(Overlay* overlay) { return addOverlay(Overlay::Pointer(overlay)); } OverlayID addOverlay(const Overlay::Pointer& overlay); - void setOverlayDrawHUDLayer(const OverlayID& id, const bool drawHUDLayer); - bool mousePressEvent(QMouseEvent* event); bool mouseDoublePressEvent(QMouseEvent* event); bool mouseReleaseEvent(QMouseEvent* event); @@ -334,11 +331,8 @@ private: mutable QMutex _mutex { QMutex::Recursive }; QMap _overlaysHUD; - QMap _overlays3DHUD; QMap _overlaysWorld; - render::ShapePlumberPointer _shapePlumber; - #if OVERLAY_PANELS QMap _panels; #endif diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp index 887bf7ff8e..7beb96c061 100644 --- a/interface/src/ui/overlays/OverlaysPayload.cpp +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -34,7 +34,8 @@ namespace render { template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay) { auto builder = ItemKey::Builder().withTypeShape(); if (overlay->is3D()) { - if (std::static_pointer_cast(overlay)->getDrawInFront()) { + auto overlay3D = std::static_pointer_cast(overlay); + if (overlay3D->getDrawInFront() || overlay3D->getDrawHUDLayer()) { builder.withLayered(); } if (overlay->isTransparent()) { diff --git a/interface/src/ui/overlays/Shape3DOverlay.cpp b/interface/src/ui/overlays/Shape3DOverlay.cpp index 2c1df478f6..a3b51d40bf 100644 --- a/interface/src/ui/overlays/Shape3DOverlay.cpp +++ b/interface/src/ui/overlays/Shape3DOverlay.cpp @@ -55,7 +55,7 @@ const render::ShapeKey Shape3DOverlay::getShapeKey() { if (isTransparent()) { builder.withTranslucent(); } - if (!getIsSolid() || shouldDrawHUDLayer()) { + if (!getIsSolid()) { builder.withUnlit().withDepthBias(); } return builder.build(); diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index f2c9968687..c9fc25b252 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -60,7 +60,7 @@ const render::ShapeKey Sphere3DOverlay::getShapeKey() { if (isTransparent()) { builder.withTranslucent(); } - if (!getIsSolid() || shouldDrawHUDLayer()) { + if (!getIsSolid()) { builder.withUnlit().withDepthBias(); } return builder.build(); diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.h b/libraries/display-plugins/src/display-plugins/CompositorHelper.h index b1d2815f65..f448375f0d 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.h +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.h @@ -74,6 +74,7 @@ public: void setModelTransform(const Transform& transform) { _modelTransform = transform; } const Transform& getModelTransform() const { return _modelTransform; } + glm::mat4 getUiTransform() const; float getAlpha() const { return _alpha; } void setAlpha(float alpha) { if (alpha != _alpha) { emit alphaChanged(); _alpha = alpha; } } @@ -122,7 +123,6 @@ protected slots: void sendFakeMouseEvent(); private: - glm::mat4 getUiTransform() const; void updateTooltips(); DisplayPluginPointer _currentDisplayPlugin; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 98f4e04492..0872edcd95 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -307,7 +307,7 @@ bool OpenGLDisplayPlugin::activate() { auto compositorHelper = DependencyManager::get(); connect(compositorHelper.data(), &CompositorHelper::alphaChanged, [this] { auto compositorHelper = DependencyManager::get(); - auto animation = new QPropertyAnimation(this, "overlayAlpha"); + auto animation = new QPropertyAnimation(this, "hudAlpha"); animation->setDuration(200); animation->setEndValue(compositorHelper->getAlpha()); animation->start(); @@ -415,7 +415,7 @@ void OpenGLDisplayPlugin::customizeContext() { state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - _overlayPipeline = gpu::Pipeline::create(program, state); + _hudPipeline = gpu::Pipeline::create(program, state); } { @@ -437,7 +437,7 @@ void OpenGLDisplayPlugin::customizeContext() { void OpenGLDisplayPlugin::uncustomizeContext() { _presentPipeline.reset(); _cursorPipeline.reset(); - _overlayPipeline.reset(); + _hudPipeline.reset(); _compositeFramebuffer.reset(); withPresentThreadLock([&] { _currentFrame.reset(); @@ -562,12 +562,11 @@ void OpenGLDisplayPlugin::updateFrameData() { }); } -void OpenGLDisplayPlugin::compositeOverlay() { - render([&](gpu::Batch& batch){ +std::function OpenGLDisplayPlugin::getHUDOperator() { + return [this](gpu::Batch& batch, const gpu::TexturePointer& hudTexture) { batch.enableStereo(false); - batch.setFramebuffer(_compositeFramebuffer); - batch.setPipeline(_overlayPipeline); - batch.setResourceTexture(0, _currentFrame->overlay); + batch.setPipeline(_hudPipeline); + batch.setResourceTexture(0, hudTexture); if (isStereo()) { for_each_eye([&](Eye eye) { batch.setViewportTransform(eyeViewport(eye)); @@ -577,7 +576,7 @@ void OpenGLDisplayPlugin::compositeOverlay() { batch.setViewportTransform(ivec4(uvec2(0), _compositeFramebuffer->getSize())); batch.draw(gpu::TRIANGLE_STRIP, 4); } - }); + }; } void OpenGLDisplayPlugin::compositePointer() { @@ -626,29 +625,15 @@ void OpenGLDisplayPlugin::compositeLayers() { compositeScene(); } - // Clear the depth framebuffer after drawing the scene so that the HUD elements can depth test against each other - render([&](gpu::Batch& batch) { - batch.enableStereo(false); - batch.setFramebuffer(_compositeFramebuffer); - batch.clearDepthFramebuffer((float) UINT32_MAX); - }); - #ifdef HIFI_ENABLE_NSIGHT_DEBUG - if (false) // do not compositeoverlay if running nsight debug + if (false) // do not draw the HUD if running nsight debug #endif { - PROFILE_RANGE_EX(render_detail, "compositeOverlay", 0xff0077ff, (uint64_t)presentCount()) - compositeOverlay(); - } - - // Only render HUD layer 3D overlays in HMD mode - if (isHmd()) { - PROFILE_RANGE_EX(render_detail, "compositeHUDOverlays", 0xff0077ff, (uint64_t)presentCount()) - render([&](gpu::Batch& batch) { - batch.enableStereo(false); - batch.setFramebuffer(_compositeFramebuffer); + PROFILE_RANGE_EX(render_detail, "handleHUDBatch", 0xff0077ff, (uint64_t)presentCount()) + auto hudOperator = getHUDOperator(); + withPresentThreadLock([&] { + _hudOperator = hudOperator; }); - _gpuContext->executeBatch(_currentFrame->postCompositeBatch); } { @@ -656,13 +641,7 @@ void OpenGLDisplayPlugin::compositeLayers() { compositeExtra(); } - // Clear the depth buffer again and draw the pointer last so it's on top of everything - render([&](gpu::Batch& batch) { - batch.enableStereo(false); - batch.setFramebuffer(_compositeFramebuffer); - batch.clearDepthFramebuffer((float) UINT32_MAX); - }); - + // Draw the pointer last so it's on top of everything auto compositorHelper = DependencyManager::get(); if (compositorHelper->getReticleVisible()) { PROFILE_RANGE_EX(render_detail, "compositePointer", 0xff0077ff, (uint64_t)presentCount()) @@ -844,7 +823,7 @@ void OpenGLDisplayPlugin::assertIsPresentThread() const { bool OpenGLDisplayPlugin::beginFrameRender(uint32_t frameIndex) { withNonPresentThreadLock([&] { - _compositeOverlayAlpha = _overlayAlpha; + _compositeHUDAlpha = _hudAlpha; }); return Parent::beginFrameRender(frameIndex); } @@ -887,8 +866,7 @@ OpenGLDisplayPlugin::~OpenGLDisplayPlugin() { void OpenGLDisplayPlugin::updateCompositeFramebuffer() { auto renderSize = getRecommendedRenderSize(); if (!_compositeFramebuffer || _compositeFramebuffer->getSize() != renderSize) { - auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); - _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_RGBA_32, depthFormat, renderSize.x, renderSize.y)); + _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_RGBA_32, renderSize.x, renderSize.y)); } } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 2080fa5ea6..c6e9b7f5be 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -22,6 +22,8 @@ #include #include +#include + namespace gpu { namespace gl { class GLBackend; @@ -30,7 +32,7 @@ namespace gpu { class OpenGLDisplayPlugin : public DisplayPlugin { Q_OBJECT - Q_PROPERTY(float overlayAlpha MEMBER _overlayAlpha) + Q_PROPERTY(float hudAlpha MEMBER _hudAlpha) using Parent = DisplayPlugin; protected: using Mutex = std::mutex; @@ -93,7 +95,7 @@ protected: virtual QThread::Priority getPresentPriority() { return QThread::HighPriority; } virtual void compositeLayers(); virtual void compositeScene(); - virtual void compositeOverlay(); + virtual std::function getHUDOperator(); virtual void compositePointer(); virtual void compositeExtra() {}; @@ -137,12 +139,12 @@ protected: gpu::FramePointer _currentFrame; gpu::Frame* _lastFrame { nullptr }; gpu::FramebufferPointer _compositeFramebuffer; - gpu::PipelinePointer _overlayPipeline; + gpu::PipelinePointer _hudPipeline; gpu::PipelinePointer _simplePipeline; gpu::PipelinePointer _presentPipeline; gpu::PipelinePointer _cursorPipeline; gpu::TexturePointer _displayTexture{}; - float _compositeOverlayAlpha { 1.0f }; + float _compositeHUDAlpha { 1.0f }; struct CursorData { QImage image; @@ -176,6 +178,6 @@ protected: // Any resource shared by the main thread and the presentation thread must // be serialized through this mutex mutable Mutex _presentMutex; - float _overlayAlpha{ 1.0f }; + float _hudAlpha{ 1.0f }; }; diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index 88ec94eefb..6d0134ec23 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -33,6 +33,9 @@ #include "../Logging.h" #include "../CompositorHelper.h" +#include "render-utils/hmd_ui_vert.h" +#include "render-utils/hmd_ui_frag.h" + static const QString MONO_PREVIEW = "Mono Preview"; static const QString DISABLE_PREVIEW = "Disable Preview"; static const QString FRAMERATE = DisplayPlugin::MENU_PATH() + ">Framerate"; @@ -58,7 +61,7 @@ glm::uvec2 HmdDisplayPlugin::getRecommendedUiSize() const { return CompositorHelper::VIRTUAL_SCREEN_SIZE; } -QRect HmdDisplayPlugin::getRecommendedOverlayRect() const { +QRect HmdDisplayPlugin::getRecommendedHUDRect() const { return CompositorHelper::VIRTUAL_SCREEN_RECOMMENDED_OVERLAY_RECT; } @@ -108,7 +111,7 @@ void HmdDisplayPlugin::internalDeactivate() { void HmdDisplayPlugin::customizeContext() { Parent::customizeContext(); - _overlayRenderer.build(); + _hudRenderer.build(); } void HmdDisplayPlugin::uncustomizeContext() { @@ -121,7 +124,7 @@ void HmdDisplayPlugin::uncustomizeContext() { batch.setFramebuffer(_compositeFramebuffer); batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, vec4(0)); }); - _overlayRenderer = OverlayRenderer(); + _hudRenderer = HUDRenderer(); _previewTexture.reset(); Parent::uncustomizeContext(); } @@ -171,7 +174,7 @@ float HmdDisplayPlugin::getLeftCenterPixel() const { void HmdDisplayPlugin::internalPresent() { PROFILE_RANGE_EX(render, __FUNCTION__, 0xff00ff00, (uint64_t)presentCount()) - // Composite together the scene, overlay and mouse cursor + // Composite together the scene, hud and mouse cursor hmdPresent(); if (_displayTexture) { @@ -344,17 +347,9 @@ void HmdDisplayPlugin::updateFrameData() { auto correction = glm::inverse(batchPose) * currentPose; getGLBackend()->setCameraCorrection(correction); } - - auto compositorHelper = DependencyManager::get(); - glm::mat4 modelMat = compositorHelper->getModelTransform().getMatrix(); - - for_each_eye([&](Eye eye) { - auto modelView = glm::inverse(_currentPresentFrameInfo.presentPose * getEyeToHeadTransform(eye)) * modelMat; - _overlayRenderer.mvps[eye] = _eyeProjections[eye] * modelView; - }); } -void HmdDisplayPlugin::OverlayRenderer::build() { +void HmdDisplayPlugin::HUDRenderer::build() { vertices = std::make_shared(); indices = std::make_shared(); @@ -410,38 +405,20 @@ void HmdDisplayPlugin::OverlayRenderer::build() { format = std::make_shared(); // 1 for everyone format->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); format->setAttribute(gpu::Stream::TEXCOORD, gpu::Stream::TEXCOORD, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); - uniformBuffers[0] = std::make_shared(sizeof(Uniforms), nullptr); - uniformBuffers[1] = std::make_shared(sizeof(Uniforms), nullptr); + uniformsBuffer = std::make_shared(sizeof(Uniforms), nullptr); updatePipeline(); } -void HmdDisplayPlugin::OverlayRenderer::updatePipeline() { - static const QString vsFile = PathUtils::resourcesPath() + "/shaders/hmd_ui.vert"; - static const QString fsFile = PathUtils::resourcesPath() + "/shaders/hmd_ui.frag"; - -#if LIVE_SHADER_RELOAD - static qint64 vsBuiltAge = 0; - static qint64 fsBuiltAge = 0; - QFileInfo vsInfo(vsFile); - QFileInfo fsInfo(fsFile); - auto vsAge = vsInfo.lastModified().toMSecsSinceEpoch(); - auto fsAge = fsInfo.lastModified().toMSecsSinceEpoch(); - if (!pipeline || vsAge > vsBuiltAge || fsAge > fsBuiltAge) { - vsBuiltAge = vsAge; - fsBuiltAge = fsAge; -#else +void HmdDisplayPlugin::HUDRenderer::updatePipeline() { if (!pipeline) { -#endif - QString vsSource = readFile(vsFile); - QString fsSource = readFile(fsFile); - auto vs = gpu::Shader::createVertex(vsSource.toLocal8Bit().toStdString()); - auto ps = gpu::Shader::createPixel(fsSource.toLocal8Bit().toStdString()); + auto vs = gpu::Shader::createVertex(std::string(hmd_ui_vert)); + auto ps = gpu::Shader::createPixel(std::string(hmd_ui_frag)); auto program = gpu::Shader::createProgram(vs, ps); gpu::gl::GLBackend::makeProgram(*program, gpu::Shader::BindingSet()); - this->uniformsLocation = program->getUniformBuffers().findLocation("overlayBuffer"); + uniformsLocation = program->getUniformBuffers().findLocation("hudBuffer"); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); - state->setDepthTest(gpu::State::DepthTest(false, false, gpu::LESS_EQUAL)); + state->setDepthTest(gpu::State::DepthTest(true, true, gpu::LESS_EQUAL)); state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); @@ -450,30 +427,27 @@ void HmdDisplayPlugin::OverlayRenderer::updatePipeline() { } } -void HmdDisplayPlugin::OverlayRenderer::render(HmdDisplayPlugin& plugin) { +std::function HmdDisplayPlugin::HUDRenderer::render(HmdDisplayPlugin& plugin) { updatePipeline(); - for_each_eye([&](Eye eye){ - uniforms.mvp = mvps[eye]; - uniformBuffers[eye]->setSubData(0, uniforms); - }); - plugin.render([&](gpu::Batch& batch) { - batch.enableStereo(false); - batch.setFramebuffer(plugin._compositeFramebuffer); + return [this](gpu::Batch& batch, const gpu::TexturePointer& hudTexture) { batch.setPipeline(pipeline); + batch.setInputFormat(format); gpu::BufferView posView(vertices, VERTEX_OFFSET, vertices->getSize(), VERTEX_STRIDE, format->getAttributes().at(gpu::Stream::POSITION)._element); gpu::BufferView uvView(vertices, TEXTURE_OFFSET, vertices->getSize(), VERTEX_STRIDE, format->getAttributes().at(gpu::Stream::TEXCOORD)._element); batch.setInputBuffer(gpu::Stream::POSITION, posView); batch.setInputBuffer(gpu::Stream::TEXCOORD, uvView); batch.setIndexBuffer(gpu::UINT16, indices, 0); - batch.setResourceTexture(0, plugin._currentFrame->overlay); - // FIXME use stereo information input to set both MVPs in the uniforms - for_each_eye([&](Eye eye) { - batch.setUniformBuffer(uniformsLocation, uniformBuffers[eye]); - batch.setViewportTransform(plugin.eyeViewport(eye)); - batch.drawIndexed(gpu::TRIANGLES, indexCount); - }); - }); + + uniformsBuffer->setSubData(0, uniforms); + batch.setUniformBuffer(uniformsLocation, uniformsBuffer); + + auto compositorHelper = DependencyManager::get(); + batch.setModelTransform(compositorHelper->getUiTransform()); + batch.setResourceTexture(0, hudTexture); + + batch.drawIndexed(gpu::TRIANGLES, indexCount); + }; } void HmdDisplayPlugin::compositePointer() { @@ -500,12 +474,8 @@ void HmdDisplayPlugin::compositePointer() { }); } -void HmdDisplayPlugin::compositeOverlay() { - if (!_currentFrame || !_currentFrame->overlay) { - return; - } - - _overlayRenderer.render(*this); +std::function HmdDisplayPlugin::getHUDOperator() { + return _hudRenderer.render(*this); } HmdDisplayPlugin::~HmdDisplayPlugin() { diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index db4e0ff7a1..a7a6d2938d 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -33,7 +33,7 @@ public: glm::uvec2 getRecommendedRenderSize() const override final { return _renderTargetSize; } bool isDisplayVisible() const override { return isHmdMounted(); } - QRect getRecommendedOverlayRect() const override final; + QRect getRecommendedHUDRect() const override final; virtual glm::mat4 getHeadPose() const override; @@ -53,7 +53,7 @@ protected: bool internalActivate() override; void internalDeactivate() override; - void compositeOverlay() override; + std::function getHUDOperator() override; void compositePointer() override; void internalPresent() override; void customizeContext() override; @@ -91,7 +91,7 @@ private: gpu::TexturePointer _previewTexture; glm::vec2 _lastWindowSize; - struct OverlayRenderer { + struct HUDRenderer { gpu::Stream::FormatPointer format; gpu::BufferPointer vertices; gpu::BufferPointer indices; @@ -99,12 +99,9 @@ private: gpu::PipelinePointer pipeline; int32_t uniformsLocation { -1 }; - // FIXME this is stupid, use the built in transformation pipeline - std::array uniformBuffers; - std::array mvps; + gpu::BufferPointer uniformsBuffer; struct Uniforms { - mat4 mvp; float alpha { 1.0f }; } uniforms; @@ -119,6 +116,6 @@ private: void build(); void updatePipeline(); - void render(HmdDisplayPlugin& plugin); - } _overlayRenderer; + std::function render(HmdDisplayPlugin& plugin); + } _hudRenderer; }; diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 77d22258b2..fca220c224 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -92,7 +92,7 @@ public: void captureNamedDrawCallInfo(std::string name); Batch(); - explicit Batch(const Batch& batch); + Batch(const Batch& batch); ~Batch(); void clear(); diff --git a/libraries/gpu/src/gpu/Frame.h b/libraries/gpu/src/gpu/Frame.h index 69872906e3..1ed77a26b7 100644 --- a/libraries/gpu/src/gpu/Frame.h +++ b/libraries/gpu/src/gpu/Frame.h @@ -32,14 +32,10 @@ namespace gpu { Mat4 pose; /// The collection of batches which make up the frame Batches batches; - /// Single batch containing overlays to be drawn in the composite framebuffer - Batch postCompositeBatch; /// The main thread updates to buffers that are applicable for this frame. BufferUpdates bufferUpdates; /// The destination framebuffer in which the results will be placed FramebufferPointer framebuffer; - /// The destination texture containing the 2D overlay - TexturePointer overlay; /// How to process the framebuffer when the frame dies. MUST BE THREAD SAFE FramebufferRecycler framebufferRecycler; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.cpp b/libraries/plugins/src/plugins/DisplayPlugin.cpp index 20c72159c4..e43d5e76f3 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.cpp +++ b/libraries/plugins/src/plugins/DisplayPlugin.cpp @@ -33,4 +33,13 @@ void DisplayPlugin::waitForPresent() { break; } } +} + +std::function DisplayPlugin::getHUDOperator() { + std::function hudOperator; + { + QMutexLocker locker(&_presentMutex); + hudOperator = _hudOperator; + } + return hudOperator; } \ No newline at end of file diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index d3054c9bd8..11ca6f754a 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -156,8 +156,8 @@ public: return aspect(getRecommendedRenderSize()); } - // The recommended bounds for primary overlay placement - virtual QRect getRecommendedOverlayRect() const { + // The recommended bounds for primary HUD placement + virtual QRect getRecommendedHUDRect() const { const int DESKTOP_SCREEN_PADDING = 50; auto recommendedSize = getRecommendedUiSize() - glm::uvec2(DESKTOP_SCREEN_PADDING); return QRect(0, 0, recommendedSize.x, recommendedSize.y); @@ -204,8 +204,9 @@ public: void waitForPresent(); - static const QString& MENU_PATH(); + std::function getHUDOperator(); + static const QString& MENU_PATH(); signals: void recommendedFramebufferSizeChanged(const QSize& size); @@ -217,6 +218,8 @@ protected: gpu::ContextPointer _gpuContext; + std::function _hudOperator { std::function() }; + private: QMutex _presentMutex; QWaitCondition _presentCondition; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index dc419c03c3..942da69dd7 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -385,7 +385,7 @@ ItemKey ModelMeshPartPayload::getKey() const { builder.withInvisible(); } - if (model->isLayeredInFront()) { + if (model->isLayeredInFront() || model->isLayeredInHUD()) { builder.withLayered(); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 6d338b4598..395a45b952 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -101,6 +101,7 @@ public: bool isVisible() const { return _isVisible; } bool isLayeredInFront() const { return _isLayeredInFront; } + bool isLayeredInHUD() const { return _isLayeredInHUD; } virtual void updateRenderItems(); void setRenderItemsNeedUpdate() { _renderItemsNeedUpdate = true; } @@ -410,6 +411,7 @@ protected: int _renderInfoHasTransparent { false }; bool _isLayeredInFront { false }; + bool _isLayeredInHUD { false }; private: float _loadingPriority { 0.0f }; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index c67a1c7875..cb00734edc 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -233,6 +233,9 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // AA job to be revisited task.addJob("Antialiasing", primaryFramebuffer); + // Composite the HUD + task.addJob("HUD"); + task.addJob("ToneAndPostRangeTimer", toneAndPostRangeTimer); // Blit! @@ -407,6 +410,18 @@ void DrawOverlay3D::run(const RenderContextPointer& renderContext, const Inputs& } } +void CompositeHUD::run(const RenderContextPointer& renderContext) { + assert(renderContext->args); + assert(renderContext->args->_context); + + // Grab the HUD texture + gpu::doInBatch(renderContext->args->_context, [&](gpu::Batch& batch) { + if (renderContext->args->_hudOperator) { + renderContext->args->_hudOperator(batch, renderContext->args->_hudTexture); + } + }); +} + void Blit::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer) { assert(renderContext->args); assert(renderContext->args->_context); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 865849b579..452420589b 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -155,6 +155,14 @@ protected: bool _opaquePass { true }; }; +class CompositeHUD { +public: + using JobModel = render::Job::Model; + + CompositeHUD() {} + void run(const render::RenderContextPointer& renderContext); +}; + class Blit { public: using JobModel = render::Job::ModelI; diff --git a/libraries/render-utils/src/hmd_ui.slf b/libraries/render-utils/src/hmd_ui.slf new file mode 100644 index 0000000000..959e8d733c --- /dev/null +++ b/libraries/render-utils/src/hmd_ui.slf @@ -0,0 +1,37 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// hmd_ui.frag +// fragment shader +// +// Created by Sam Gondelman on 9/28/17. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +uniform sampler2D hudTexture; + +struct HUDData { + float alpha; +}; + +layout(std140) uniform hudBuffer { + HUDData hud; +}; + +in vec2 _texCoord0; + +out vec4 fragColor0; + +void main() { + vec4 color = texture(hudTexture, _texCoord0); + color.a *= hud.alpha; + if (color.a <= 0.0) { + discard; + } + + fragColor0 = color; +} \ No newline at end of file diff --git a/libraries/render-utils/src/hmd_ui.slv b/libraries/render-utils/src/hmd_ui.slv new file mode 100644 index 0000000000..d6e02ff4cb --- /dev/null +++ b/libraries/render-utils/src/hmd_ui.slv @@ -0,0 +1,36 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// hmd_ui.vert +// vertex shader +// +// Created by Sam Gondelman on 9/28/17. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include gpu/Inputs.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +struct HUDData { + float alpha; +}; + +layout(std140) uniform hudBuffer { + HUDData hud; +}; + +out vec2 _texCoord0; + +void main() { + _texCoord0 = inTexCoord0.st; + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> +} diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h index 7070a4def5..a76b60ffe6 100644 --- a/libraries/render/src/render/Args.h +++ b/libraries/render/src/render/Args.h @@ -121,6 +121,9 @@ namespace render { RenderDetails _details; render::ScenePointer _scene; int8_t _cameraMode { -1 }; + + std::function _hudOperator; + gpu::TexturePointer _hudTexture; }; } diff --git a/scripts/system/controllers/controllerModules/hudOverlayPointer.js b/scripts/system/controllers/controllerModules/hudOverlayPointer.js index 487e491201..9da91417ed 100644 --- a/scripts/system/controllers/controllerModules/hudOverlayPointer.js +++ b/scripts/system/controllers/controllerModules/hudOverlayPointer.js @@ -31,7 +31,7 @@ glow: 1.0, lineWidth: 5, ignoreRayIntersection: true, // always ignore this - drawHUDLayer: true, // Even when burried inside of something, show it. + drawHUDLayer: true, parentID: AVATAR_SELF_ID }; var halfEnd = { @@ -40,7 +40,7 @@ color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE, alpha: 0.9, ignoreRayIntersection: true, - drawHUDLayer: true, // Even when burried inside of something, show it. + drawHUDLayer: true, visible: true }; var fullPath = { @@ -52,7 +52,7 @@ glow: 1.0, lineWidth: 5, ignoreRayIntersection: true, // always ignore this - drawHUDLayer: true, // Even when burried inside of something, show it. + drawHUDLayer: true, parentID: AVATAR_SELF_ID }; var fullEnd = { @@ -61,7 +61,7 @@ color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE, alpha: 0.9, ignoreRayIntersection: true, - drawHUDLayer: true, // Even when burried inside of something, show it. + drawHUDLayer: true, visible: true }; var holdPath = { @@ -73,7 +73,7 @@ glow: 1.0, lineWidth: 5, ignoreRayIntersection: true, // always ignore this - drawHUDLayer: true, // Even when burried inside of something, show it. + drawHUDLayer: true, parentID: AVATAR_SELF_ID }; diff --git a/scripts/system/libraries/toolBars.js b/scripts/system/libraries/toolBars.js index 351f10e7bd..058910940b 100644 --- a/scripts/system/libraries/toolBars.js +++ b/scripts/system/libraries/toolBars.js @@ -370,7 +370,7 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit return Math.min(Math.max(value, min), max); } - var recommendedRect = Controller.getRecommendedOverlayRect(); + var recommendedRect = Controller.getRecommendedHUDRect(); var recommendedDimmensions = { x: recommendedRect.width, y: recommendedRect.height }; that.windowDimensions = recommendedDimmensions; // Controller.getViewportDimensions(); that.origin = { x: recommendedRect.x, y: recommendedRect.y }; @@ -378,7 +378,7 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit // For example, maybe we want "keep the same percentage to whatever two edges are closest to the edge of screen". // If we change that, the places to do so are onResizeViewport, save (maybe), and the initial move based on Settings, below. that.onResizeViewport = function (newSize) { // Can be overridden or extended by clients. - var recommendedRect = Controller.getRecommendedOverlayRect(); + var recommendedRect = Controller.getRecommendedHUDRect(); var recommendedDimmensions = { x: recommendedRect.width, y: recommendedRect.height }; var originRelativeX = (that.x - that.origin.x - that.offset.x); var originRelativeY = (that.y - that.origin.y - that.offset.y); @@ -396,7 +396,7 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit // code once the new toolbar position is well established with users. this.isNewPositionKey = optionalPersistenceKey + '.isNewPosition'; this.save = function () { - var recommendedRect = Controller.getRecommendedOverlayRect(); + var recommendedRect = Controller.getRecommendedHUDRect(); var screenSize = { x: recommendedRect.width, y: recommendedRect.height }; if (screenSize.x > 0 && screenSize.y > 0) { // Guard against invalid screen size that can occur at shut-down. @@ -443,7 +443,7 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit that.move(that.dragOffsetX + event.x, that.dragOffsetY + event.y); }; that.checkResize = function () { // Can be overriden or extended, but usually not. See onResizeViewport. - var recommendedRect = Controller.getRecommendedOverlayRect(); + var recommendedRect = Controller.getRecommendedHUDRect(); var currentWindowSize = { x: recommendedRect.width, y: recommendedRect.height }; if ((currentWindowSize.x !== that.windowDimensions.x) || (currentWindowSize.y !== that.windowDimensions.y)) { @@ -471,7 +471,7 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit var savedFraction = isNewPosition ? JSON.parse(Settings.getValue(this.fractionKey) || "0") : 0; Settings.setValue(this.isNewPositionKey, true); - var recommendedRect = Controller.getRecommendedOverlayRect(); + var recommendedRect = Controller.getRecommendedHUDRect(); var screenSize = { x: recommendedRect.width, y: recommendedRect.height }; if (savedFraction) { // If we have saved data, keep the toolbar at the same proportion of the screen width/height.