From 477dfdff1ea3e48ae2a580007f4ea27ead945815 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 4 Oct 2017 11:45:21 -0700 Subject: [PATCH] wip hud layering and fix crashes --- interface/src/ui/overlays/ModelOverlay.cpp | 9 +++++ interface/src/ui/overlays/ModelOverlay.h | 2 ++ interface/src/ui/overlays/OverlaysPayload.cpp | 13 +++---- .../display-plugins/OpenGLDisplayPlugin.cpp | 13 +++++-- .../src/display-plugins/OpenGLDisplayPlugin.h | 1 + .../display-plugins/hmd/HmdDisplayPlugin.cpp | 28 ++++++++------- .../render-utils/src/MeshPartPayload.cpp | 14 ++++---- libraries/render-utils/src/Model.cpp | 15 ++++++++ libraries/render-utils/src/Model.h | 1 + .../render-utils/src/RenderDeferredTask.cpp | 34 ++++++++++++++----- libraries/render/src/render/FilterTask.cpp | 13 ++++--- libraries/render/src/render/FilterTask.h | 8 ++--- libraries/render/src/render/Item.h | 7 +++- 13 files changed, 111 insertions(+), 47 deletions(-) diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 8ce6e7f1f3..a3088e1ddb 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -88,6 +88,10 @@ void ModelOverlay::update(float deltatime) { _drawInFrontDirty = false; _model->setLayeredInFront(getDrawInFront(), scene); } + if (_drawInHUDDirty) { + _drawInHUDDirty = false; + _model->setLayeredInHUD(getDrawHUDLayer(), scene); + } scene->enqueueTransaction(transaction); } @@ -112,6 +116,11 @@ void ModelOverlay::setDrawInFront(bool drawInFront) { _drawInFrontDirty = true; } +void ModelOverlay::setDrawHUDLayer(bool drawHUDLayer) { + Base3DOverlay::setDrawHUDLayer(drawHUDLayer); + _drawInHUDDirty = true; +} + void ModelOverlay::setProperties(const QVariantMap& properties) { auto origPosition = getPosition(); auto origRotation = getRotation(); diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index ba1ffa86c1..ea0eff170c 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -51,6 +51,7 @@ public: void setVisible(bool visible) override; void setDrawInFront(bool drawInFront) override; + void setDrawHUDLayer(bool drawHUDLayer) override; protected: Transform evalRenderTransform() override; @@ -98,6 +99,7 @@ private: bool _visibleDirty { false }; bool _drawInFrontDirty { false }; + bool _drawInHUDDirty { false }; }; diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp index 7beb96c061..194c530df0 100644 --- a/interface/src/ui/overlays/OverlaysPayload.cpp +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -50,20 +50,17 @@ namespace render { return overlay->getBounds(); } template <> int payloadGetLayer(const Overlay::Pointer& overlay) { - // Magic number while we are defining the layering mechanism: - const int LAYER_2D = 2; - const int LAYER_3D_FRONT = 1; - const int LAYER_3D = 0; - if (overlay->is3D()) { auto overlay3D = std::dynamic_pointer_cast(overlay); if (overlay3D->getDrawInFront()) { - return LAYER_3D_FRONT; + return Item::LAYER_3D_FRONT; + } else if (overlay3D->getDrawHUDLayer()) { + return Item::LAYER_3D_HUD; } else { - return LAYER_3D; + return Item::LAYER_3D; } } else { - return LAYER_2D; + return Item::LAYER_2D; } } template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args) { diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 0872edcd95..93e648f441 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -569,11 +569,11 @@ std::function OpenGLDisplayPlugin batch.setResourceTexture(0, hudTexture); if (isStereo()) { for_each_eye([&](Eye eye) { - batch.setViewportTransform(eyeViewport(eye)); + batch.setViewportTransform(eyeViewport(eye, getRecommendedRenderSize())); batch.draw(gpu::TRIANGLE_STRIP, 4); }); } else { - batch.setViewportTransform(ivec4(uvec2(0), _compositeFramebuffer->getSize())); + batch.setViewportTransform(ivec4(uvec2(0), getRecommendedRenderSize())); batch.draw(gpu::TRIANGLE_STRIP, 4); } }; @@ -838,6 +838,15 @@ ivec4 OpenGLDisplayPlugin::eyeViewport(Eye eye) const { return ivec4(vpPos, vpSize); } +ivec4 OpenGLDisplayPlugin::eyeViewport(Eye eye, uvec2 vpSize) const { + vpSize.x /= 2; + uvec2 vpPos; + if (eye == Eye::Right) { + vpPos.x = vpSize.x; + } + return ivec4(vpPos, vpSize); +} + gpu::gl::GLBackend* OpenGLDisplayPlugin::getGLBackend() { if (!_gpuContext || !_gpuContext->getBackend()) { return nullptr; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index ec775aed4c..4bb82f3651 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -125,6 +125,7 @@ protected: void present(); virtual void swapBuffers(); ivec4 eyeViewport(Eye eye) const; + ivec4 eyeViewport(Eye eye, uvec2 vpSize) const; void render(std::function f); diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index 6d0134ec23..e5e1295786 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -430,23 +430,25 @@ void HmdDisplayPlugin::HUDRenderer::updatePipeline() { std::function HmdDisplayPlugin::HUDRenderer::render(HmdDisplayPlugin& plugin) { updatePipeline(); return [this](gpu::Batch& batch, const gpu::TexturePointer& hudTexture) { - batch.setPipeline(pipeline); + if (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.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); - uniformsBuffer->setSubData(0, uniforms); - batch.setUniformBuffer(uniformsLocation, uniformsBuffer); + uniformsBuffer->setSubData(0, uniforms); + batch.setUniformBuffer(uniformsLocation, uniformsBuffer); - auto compositorHelper = DependencyManager::get(); - batch.setModelTransform(compositorHelper->getUiTransform()); - batch.setResourceTexture(0, hudTexture); + auto compositorHelper = DependencyManager::get(); + batch.setModelTransform(compositorHelper->getUiTransform()); + batch.setResourceTexture(0, hudTexture); - batch.drawIndexed(gpu::TRIANGLES, indexCount); + batch.drawIndexed(gpu::TRIANGLES, indexCount); + } }; } diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 942da69dd7..8b65c9f7ce 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -404,15 +404,15 @@ ItemKey ModelMeshPartPayload::getKey() const { } int ModelMeshPartPayload::getLayer() const { - // MAgic number while we are defining the layering mechanism: - const int LAYER_3D_FRONT = 1; - const int LAYER_3D = 0; ModelPointer model = _model.lock(); - if (model && model->isLayeredInFront()) { - return LAYER_3D_FRONT; - } else { - return LAYER_3D; + if (model) { + if (model->isLayeredInFront()) { + return Item::LAYER_3D_FRONT; + } else if (model->isLayeredInHUD()) { + return Item::LAYER_3D_HUD; + } } + return Item::LAYER_3D; } ShapeKey ModelMeshPartPayload::getShapeKey() const { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index f25cad8a6e..252afada5d 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -598,6 +598,21 @@ void Model::setLayeredInFront(bool layered, const render::ScenePointer& scene) { } } +void Model::setLayeredInHUD(bool layered, const render::ScenePointer& scene) { + if (_isLayeredInHUD != layered) { + _isLayeredInHUD = layered; + + render::Transaction transaction; + foreach(auto item, _modelMeshRenderItemsMap.keys()) { + transaction.resetItem(item, _modelMeshRenderItemsMap[item]); + } + foreach(auto item, _collisionRenderItemsMap.keys()) { + transaction.resetItem(item, _collisionRenderItemsMap[item]); + } + scene->enqueueTransaction(transaction); + } +} + bool Model::addToScene(const render::ScenePointer& scene, render::Transaction& transaction, render::Item::Status::Getters& statusGetters) { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 395a45b952..ee68258e2d 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -84,6 +84,7 @@ public: // new Scene/Engine rendering support void setVisibleInScene(bool newValue, const render::ScenePointer& scene); void setLayeredInFront(bool layered, const render::ScenePointer& scene); + void setLayeredInHUD(bool layered, const render::ScenePointer& scene); bool needsFixupInScene() const; bool needsReload() const { return _needsReload; } diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 7681642753..a0bef828fa 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -187,14 +187,19 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren } // Overlays - const auto overlayOpaquesInputs = DrawOverlay3D::Inputs(overlayOpaques, lightingModel).asVarying(); - const auto overlayTransparentsInputs = DrawOverlay3D::Inputs(overlayTransparents, lightingModel).asVarying(); - task.addJob("DrawOverlay3DOpaque", overlayOpaquesInputs, true); - task.addJob("DrawOverlay3DTransparent", overlayTransparentsInputs, false); + const auto filteredOverlaysOpaque = task.addJob("FilterOverlaysLayeredOpaque", overlayOpaques, Item::LAYER_3D_FRONT); + const auto filteredOverlaysTransparent = task.addJob("FilterOverlaysLayeredTransparent", overlayTransparents, Item::LAYER_3D_FRONT); + const auto overlaysInFrontOpaque = filteredOverlaysOpaque.getN(0); + const auto overlaysInFrontTransparent = filteredOverlaysTransparent.getN(0); - { // Debug the bounds of the rendered Overlay items, still look at the zbuffer - task.addJob("DrawOverlayOpaqueBounds", overlayOpaques); - task.addJob("DrawOverlayTransparentBounds", overlayTransparents); + const auto overlayInFrontOpaquesInputs = DrawOverlay3D::Inputs(overlaysInFrontOpaque, lightingModel).asVarying(); + const auto overlayInFrontTransparentsInputs = DrawOverlay3D::Inputs(overlaysInFrontTransparent, lightingModel).asVarying(); + task.addJob("DrawOverlayInFrontOpaque", overlayInFrontOpaquesInputs, true); + task.addJob("DrawOverlayInFrontTransparent", overlayInFrontTransparentsInputs, false); + + { // Debug the bounds of the rendered Overlay items that are marked drawInFront, still look at the zbuffer + task.addJob("DrawOverlayInFrontOpaqueBounds", overlaysInFrontOpaque); + task.addJob("DrawOverlayInFrontTransparentBounds", overlaysInFrontTransparent); } // Debugging stages @@ -233,9 +238,22 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // AA job to be revisited task.addJob("Antialiasing", primaryFramebuffer); - // Composite the HUD + // Composite the HUD and HUD overlays task.addJob("HUD"); + const auto overlaysHUDOpaque = filteredOverlaysOpaque.getN(1); + const auto overlaysHUDTransparent = filteredOverlaysTransparent.getN(1); + + const auto overlayHUDOpaquesInputs = DrawOverlay3D::Inputs(overlaysHUDOpaque, lightingModel).asVarying(); + const auto overlayHUDTransparentsInputs = DrawOverlay3D::Inputs(overlaysHUDTransparent, lightingModel).asVarying(); + task.addJob("DrawOverlayHUDOpaque", overlayHUDOpaquesInputs, true); + task.addJob("DrawOverlayHUDTransparent", overlayHUDTransparentsInputs, false); + + { // Debug the bounds of the rendered Overlay items that are marked drawHUDLayer, still look at the zbuffer + task.addJob("DrawOverlayHUDOpaqueBounds", overlaysHUDOpaque); + task.addJob("DrawOverlayHUDOpaqueBounds", overlaysHUDTransparent); + } + task.addJob("ToneAndPostRangeTimer", toneAndPostRangeTimer); // Blit! diff --git a/libraries/render/src/render/FilterTask.cpp b/libraries/render/src/render/FilterTask.cpp index e0298c2a44..49a9ada91e 100644 --- a/libraries/render/src/render/FilterTask.cpp +++ b/libraries/render/src/render/FilterTask.cpp @@ -21,19 +21,24 @@ using namespace render; -void FilterLayeredItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) { +void FilterLayeredItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, Outputs& outputs) { auto& scene = renderContext->_scene; - // Clear previous values - outItems.clear(); + ItemBounds matchedItems; + ItemBounds nonMatchItems; // For each item, filter it into one bucket for (auto& itemBound : inItems) { auto& item = scene->getItem(itemBound.id); if (item.getLayer() == _keepLayer) { - outItems.emplace_back(itemBound); + matchedItems.emplace_back(itemBound); + } else { + nonMatchItems.emplace_back(itemBound); } } + + outputs.edit0() = matchedItems; + outputs.edit1() = nonMatchItems; } void SliceItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) { diff --git a/libraries/render/src/render/FilterTask.h b/libraries/render/src/render/FilterTask.h index 1e023a8bb9..a7180b6cde 100644 --- a/libraries/render/src/render/FilterTask.h +++ b/libraries/render/src/render/FilterTask.h @@ -65,15 +65,15 @@ namespace render { // Filter the items belonging to the job's keep layer class FilterLayeredItems { public: - using JobModel = Job::ModelIO; + using Outputs = render::VaryingSet2; + using JobModel = Job::ModelIO; - FilterLayeredItems() {} FilterLayeredItems(int keepLayer) : _keepLayer(keepLayer) {} - int _keepLayer { 0 }; + int _keepLayer; - void run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems); + void run(const RenderContextPointer& renderContext, const ItemBounds& inItems, Outputs& outputs); }; // SliceItems job config defining the slice range diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 96faf9719e..8cdb41de45 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -356,9 +356,14 @@ public: // Get the bound of the item expressed in world space (or eye space depending on the key.isWorldSpace()) const Bound getBound() const { return _payload->getBound(); } - // Get the layer where the item belongs. 0 by default meaning NOT LAYERED + // Get the layer where the item belongs. int getLayer() const { return _payload->getLayer(); } + static const int LAYER_2D = 0; + static const int LAYER_3D = 1; + static const int LAYER_3D_FRONT = 2; + static const int LAYER_3D_HUD = 3; + // Render call for the item void render(RenderArgs* args) const { _payload->render(args); }