From e7a3d98ae5ede6b5643029b3abb5f97963283273 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 11 Jan 2018 19:34:54 -0800 Subject: [PATCH 01/57] don't draw head-descendent entities when in 1st-person camera mode --- interface/src/avatar/MyAvatar.cpp | 19 +++++++++++++++++++ interface/src/avatar/MyAvatar.h | 2 ++ .../src/RenderableModelEntityItem.cpp | 5 +++-- libraries/entities/src/EntityItem.h | 4 ++++ 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e863a58e14..b680925b3e 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include "MyHead.h" #include "MySkeletonModel.h" @@ -501,11 +502,29 @@ void MyAvatar::updateEyeContactTarget(float deltaTime) { extern QByteArray avatarStateToFrame(const AvatarData* _avatar); extern void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar); +void MyAvatar::updateChildCauterization(SpatiallyNestablePointer object) { + if (object->getNestableType() == NestableType::Entity) { + EntityItemPointer entity = std::static_pointer_cast(object); + entity->setCauterized(!_prevShouldDrawHead); + } +} + void MyAvatar::simulate(float deltaTime) { PerformanceTimer perfTimer("simulate"); animateScaleChanges(deltaTime); + const std::unordered_set& headBoneSet = _skeletonModel->getCauterizeBoneSet(); + forEachChild([&](SpatiallyNestablePointer object) { + bool isChildOfHead = headBoneSet.find(object->getParentJointIndex()) != headBoneSet.end(); + if (isChildOfHead) { + updateChildCauterization(object); + object->forEachDescendant([&](SpatiallyNestablePointer descendant) { + updateChildCauterization(descendant); + }); + } + }); + { PerformanceTimer perfTimer("transform"); bool stepAction = false; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index ab74460d4e..7b82a64e23 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -841,6 +841,8 @@ private: // height of user in sensor space, when standing erect. ThreadSafeValueCache _userHeight { DEFAULT_AVATAR_HEIGHT }; + + void updateChildCauterization(SpatiallyNestablePointer object); }; QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 86237e75a4..a08cf23d7b 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1281,11 +1281,12 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce entity->updateModelBounds(); - if (model->isVisible() != _visible) { + bool shouldBeVisible = _visible && !entity->getCauterized(); + if (model->isVisible() != shouldBeVisible) { // FIXME: this seems like it could be optimized if we tracked our last known visible state in // the renderable item. As it stands now the model checks it's visible/invisible state // so most of the time we don't do anything in this function. - model->setVisibleInScene(_visible, scene); + model->setVisibleInScene(shouldBeVisible, scene); } // TODO? early exit here when not visible? diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index ecfb7b5dcd..68639e0d3a 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -469,6 +469,9 @@ public: static QString _marketplacePublicKey; static void retrieveMarketplacePublicKey(); + void setCauterized(bool value) { _cauterized = value; } + bool getCauterized() const { return _cauterized; } + signals: void requestRenderUpdate(); @@ -622,6 +625,7 @@ protected: quint64 _lastUpdatedAccelerationTimestamp { 0 }; quint64 _lastUpdatedQueryAACubeTimestamp { 0 }; + bool _cauterized { false }; // it true, don't draw because it would obscure 1st-person camera }; #endif // hifi_EntityItem_h From 9d4ab13a10df7ffc139df39c5fc24b33f473b302 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 11 Jan 2018 19:45:15 -0800 Subject: [PATCH 02/57] cauterize all head-based entities rather than just models --- libraries/entities-renderer/src/RenderableEntityItem.cpp | 2 +- .../entities-renderer/src/RenderableModelEntityItem.cpp | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index fb9aba636b..49bc4deac5 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -365,7 +365,7 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa } _moving = entity->isMovingRelativeToParent(); - _visible = entity->getVisible(); + _visible = entity->getVisible() && !entity->getCauterized(); _needsRenderUpdate = false; }); } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index a08cf23d7b..86237e75a4 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1281,12 +1281,11 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce entity->updateModelBounds(); - bool shouldBeVisible = _visible && !entity->getCauterized(); - if (model->isVisible() != shouldBeVisible) { + if (model->isVisible() != _visible) { // FIXME: this seems like it could be optimized if we tracked our last known visible state in // the renderable item. As it stands now the model checks it's visible/invisible state // so most of the time we don't do anything in this function. - model->setVisibleInScene(shouldBeVisible, scene); + model->setVisibleInScene(_visible, scene); } // TODO? early exit here when not visible? From 9bdb89df2ea40108f440df59f89feb2a8d92c144 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 12 Jan 2018 07:26:09 -0800 Subject: [PATCH 03/57] trying to get mirror to work --- libraries/entities-renderer/src/RenderableEntityItem.cpp | 6 ++++-- libraries/entities-renderer/src/RenderableEntityItem.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 49bc4deac5..8d9cc326f3 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -185,7 +185,8 @@ void EntityRenderer::render(RenderArgs* args) { emit requestRenderUpdate(); } - if (_visible) { + bool defaultMode = args->_renderMode == RenderArgs::DEFAULT_RENDER_MODE; + if (_visible && (defaultMode || !_cauterized)) { doRender(args); } } @@ -365,7 +366,8 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa } _moving = entity->isMovingRelativeToParent(); - _visible = entity->getVisible() && !entity->getCauterized(); + _visible = entity->getVisible(); + _cauterized = entity->getCauterized(); _needsRenderUpdate = false; }); } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 8eb82e2c6e..f8685df5da 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -124,6 +124,7 @@ protected: bool _isFading{ _entitiesShouldFadeFunction() }; bool _prevIsTransparent { false }; bool _visible { false }; + bool _cauterized { false }; bool _moving { false }; bool _needsRenderUpdate { false }; // Only touched on the rendering thread From 227dbd6f684b96755429f18b356a41cc607a0733 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 12 Jan 2018 08:52:07 -0800 Subject: [PATCH 04/57] put this back to a working state --- libraries/entities-renderer/src/RenderableEntityItem.cpp | 3 +-- .../entities-renderer/src/RenderableModelEntityItem.cpp | 5 +++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 8d9cc326f3..f2876da40a 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -185,8 +185,7 @@ void EntityRenderer::render(RenderArgs* args) { emit requestRenderUpdate(); } - bool defaultMode = args->_renderMode == RenderArgs::DEFAULT_RENDER_MODE; - if (_visible && (defaultMode || !_cauterized)) { + if (_visible) { doRender(args); } } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 86237e75a4..a6d34f5826 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1281,11 +1281,12 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce entity->updateModelBounds(); - if (model->isVisible() != _visible) { + bool visible = _visible && !_cauterized; + if (model->isVisible() != visible) { // FIXME: this seems like it could be optimized if we tracked our last known visible state in // the renderable item. As it stands now the model checks it's visible/invisible state // so most of the time we don't do anything in this function. - model->setVisibleInScene(_visible, scene); + model->setVisibleInScene(visible, scene); } // TODO? early exit here when not visible? From dbdc50ed244b7cc9a18c766d7afa2d5c439eee96 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 12 Jan 2018 08:56:06 -0800 Subject: [PATCH 05/57] also cauterize non-models that are children of head --- libraries/entities-renderer/src/RenderableEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index f2876da40a..c51e1bccd7 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -185,7 +185,7 @@ void EntityRenderer::render(RenderArgs* args) { emit requestRenderUpdate(); } - if (_visible) { + if (_visible && !_cauterized) { doRender(args); } } From f81f50a6d282061fe2e5a271b4d852513f0513b4 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 12 Jan 2018 09:08:52 -0800 Subject: [PATCH 06/57] non-models act correctly in mirror now' --- libraries/entities-renderer/src/RenderableEntityItem.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index c51e1bccd7..f3ef956146 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -185,7 +185,12 @@ void EntityRenderer::render(RenderArgs* args) { emit requestRenderUpdate(); } - if (_visible && !_cauterized) { + auto& renderMode = args->_renderMode; + bool cauterized = (renderMode != RenderArgs::RenderMode::SHADOW_RENDER_MODE && + renderMode != RenderArgs::RenderMode::SECONDARY_CAMERA_RENDER_MODE) && + _cauterized; + + if (_visible && !cauterized) { doRender(args); } } From 836b69ab1b65a4d1618ffe052a60871d5d669e74 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 12 Jan 2018 17:42:18 -0800 Subject: [PATCH 07/57] exposing several visibility flags --- .../render-utils/src/RenderShadowTask.cpp | 2 +- libraries/render-utils/src/RenderViewTask.cpp | 4 +-- libraries/render-utils/src/RenderViewTask.h | 2 +- libraries/render/src/render/Item.h | 35 +++++++++++++++---- .../src/render/RenderFetchCullSortTask.cpp | 4 +-- .../src/render/RenderFetchCullSortTask.h | 2 +- 6 files changed, 35 insertions(+), 14 deletions(-) diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 2e5b7132e4..02f6d70e43 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -264,7 +264,7 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon const auto globalShadow = lightStage->getCurrentKeyShadow(); if (globalShadow && _cascadeIndexgetCascadeCount()) { - output.edit1() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered(); + output.edit1() = ItemFilter::Builder::visibleWorldItems(0x08).withTypeShape().withOpaque().withoutLayered(); globalShadow->setKeylightCascadeFrustum(_cascadeIndex, args->getViewFrustum(), SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR); diff --git a/libraries/render-utils/src/RenderViewTask.cpp b/libraries/render-utils/src/RenderViewTask.cpp index dc6c66e058..434e069d28 100644 --- a/libraries/render-utils/src/RenderViewTask.cpp +++ b/libraries/render-utils/src/RenderViewTask.cpp @@ -14,7 +14,7 @@ #include "RenderDeferredTask.h" #include "RenderForwardTask.h" -void RenderViewTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, bool isDeferred) { +void RenderViewTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, bool isDeferred, uint8_t visibilityMask) { // auto items = input.get(); // Shadows use an orthographic projection because they are linked to sunlights @@ -30,7 +30,7 @@ void RenderViewTask::build(JobModel& task, const render::Varying& input, render: return true; }); - const auto items = task.addJob("FetchCullSort", cullFunctor); + const auto items = task.addJob("FetchCullSort", cullFunctor, visibilityMask); assert(items.canCast()); if (isDeferred) { diff --git a/libraries/render-utils/src/RenderViewTask.h b/libraries/render-utils/src/RenderViewTask.h index eb61f56eab..9c2bbe0281 100644 --- a/libraries/render-utils/src/RenderViewTask.h +++ b/libraries/render-utils/src/RenderViewTask.h @@ -23,7 +23,7 @@ public: RenderViewTask() {} - void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred); + void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred, uint8_t visibilityMask = 0xFF); }; diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 77f5910b9e..c2f1312ec2 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -46,7 +46,10 @@ public: VIEW_SPACE, // Transformed in view space, and not in world space DYNAMIC, // Dynamic and bound will change unlike static item DEFORMED, // Deformed within bound, not solid - INVISIBLE, // Visible or not? could be just here to cast shadow + INVISIBLE0, // Visible or not in this mask index? + INVISIBLE1, // Visible or not in this mask index? + INVISIBLE2, // Visible or not in this mask index? + INVISIBLE3, // Visible or not in this mask index? SHADOW_CASTER, // Item cast shadows PICKABLE, // Item can be picked/selected LAYERED, // Item belongs to one of the layers different from the default layer @@ -57,6 +60,12 @@ public: }; typedef std::bitset Flags; + // VISIBLE MASK is defined from several bits in the Key. + // An Item can be visible in some mask bits and not other allowing for per view rendering + // Beware that the visibility mask is the oposite of what stored in the key vals. + const static uint8_t NUM_VISIBLE_MASK_INDICES{ 4 }; + const static uint8_t VISIBLE_MASK_ALL{ 0x0F }; + // The key is the Flags Flags _flags; @@ -82,7 +91,7 @@ public: Builder& withViewSpace() { _flags.set(VIEW_SPACE); return (*this); } Builder& withDynamic() { _flags.set(DYNAMIC); return (*this); } Builder& withDeformed() { _flags.set(DEFORMED); return (*this); } - Builder& withInvisible() { _flags.set(INVISIBLE); return (*this); } + Builder& withInvisible(uint8_t maskIndex = 0) { _flags.set(INVISIBLE0 + maskIndex); return (*this); } Builder& withShadowCaster() { _flags.set(SHADOW_CASTER); return (*this); } Builder& withPickable() { _flags.set(PICKABLE); return (*this); } Builder& withLayered() { _flags.set(LAYERED); return (*this); } @@ -111,8 +120,10 @@ public: bool isRigid() const { return !_flags[DEFORMED]; } bool isDeformed() const { return _flags[DEFORMED]; } - bool isVisible() const { return !_flags[INVISIBLE]; } - bool isInvisible() const { return _flags[INVISIBLE]; } + bool isVisible(uint8_t maskIndex) const { return !_flags[INVISIBLE0 + maskIndex]; } + bool isInvisible(uint8_t maskIndex) const { return _flags[INVISIBLE0 + maskIndex]; } + uint8_t getVisibleMask() const { return (~(_flags.to_ulong() >> INVISIBLE0) & VISIBLE_MASK_ALL);} + bool isVisibleMask(uint8_t mask) const { return getVisibleMask() & mask; } bool isShadowCaster() const { return _flags[SHADOW_CASTER]; } @@ -171,8 +182,18 @@ public: Builder& withRigid() { _value.reset(ItemKey::DEFORMED); _mask.set(ItemKey::DEFORMED); return (*this); } Builder& withDeformed() { _value.set(ItemKey::DEFORMED); _mask.set(ItemKey::DEFORMED); return (*this); } - Builder& withVisible() { _value.reset(ItemKey::INVISIBLE); _mask.set(ItemKey::INVISIBLE); return (*this); } - Builder& withInvisible() { _value.set(ItemKey::INVISIBLE); _mask.set(ItemKey::INVISIBLE); return (*this); } + Builder& withVisible(uint8_t maskIndex) { _value.reset(ItemKey::INVISIBLE0 + maskIndex); _mask.set(ItemKey::INVISIBLE0 + maskIndex); return (*this); } + Builder& withInvisible(uint8_t maskIndex) { _value.set(ItemKey::INVISIBLE0 + maskIndex); _mask.set(ItemKey::INVISIBLE0 + maskIndex); return (*this); } + Builder& withVisibilityMask(uint8_t mask) { + for (int i = 0; i < ItemKey::NUM_VISIBLE_MASK_INDICES; i++) { + if ((1 << i) && mask) { + withVisible(i); + } else { + withInvisible(i); + } + } + return (*this); + } Builder& withNoShadowCaster() { _value.reset(ItemKey::SHADOW_CASTER); _mask.set(ItemKey::SHADOW_CASTER); return (*this); } Builder& withShadowCaster() { _value.set(ItemKey::SHADOW_CASTER); _mask.set(ItemKey::SHADOW_CASTER); return (*this); } @@ -185,7 +206,7 @@ public: Builder& withNothing() { _value.reset(); _mask.reset(); return (*this); } // Convenient standard keys that we will keep on using all over the place - static Builder visibleWorldItems() { return Builder().withVisible().withWorldSpace(); } + static Builder visibleWorldItems(uint8_t visibilityMask) { return Builder().withVisibilityMask(visibilityMask).withWorldSpace(); } static Builder opaqueShape() { return Builder().withTypeShape().withOpaque().withWorldSpace(); } static Builder transparentShape() { return Builder().withTypeShape().withTransparent().withWorldSpace(); } static Builder light() { return Builder().withTypeLight(); } diff --git a/libraries/render/src/render/RenderFetchCullSortTask.cpp b/libraries/render/src/render/RenderFetchCullSortTask.cpp index d7294fa2bd..25c40ea7f7 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.cpp +++ b/libraries/render/src/render/RenderFetchCullSortTask.cpp @@ -17,12 +17,12 @@ using namespace render; -void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varying& output, CullFunctor cullFunctor) { +void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varying& output, CullFunctor cullFunctor, uint8_t visibilityMask) { cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&){ return true; }; // CPU jobs: // Fetch and cull the items from the scene - const ItemFilter filter = ItemFilter::Builder::visibleWorldItems().withoutLayered(); + const ItemFilter filter = ItemFilter::Builder::visibleWorldItems(visibilityMask).withoutLayered(); const auto spatialFilter = render::Varying(filter); const auto spatialSelection = task.addJob("FetchSceneSelection", spatialFilter); const auto cullInputs = CullSpatialSelection::Inputs(spatialSelection, spatialFilter).asVarying(); diff --git a/libraries/render/src/render/RenderFetchCullSortTask.h b/libraries/render/src/render/RenderFetchCullSortTask.h index b25480ae3a..3e5ad2bad8 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.h +++ b/libraries/render/src/render/RenderFetchCullSortTask.h @@ -36,7 +36,7 @@ public: RenderFetchCullSortTask() {} - void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor); + void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, uint8_t visibilityMask = 0xFF); }; #endif // hifi_RenderFetchCullSortTask_h From 7a9740d25878a8f516329eeefbca7f68f0c30b31 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 18 Jan 2018 02:18:46 -0800 Subject: [PATCH 08/57] visible-perview --- interface/src/Application.cpp | 2 +- interface/src/SecondaryCamera.cpp | 2 +- .../render-utils/src/CauterizedModel.cpp | 2 +- .../render-utils/src/MeshPartPayload.cpp | 5 ++++- libraries/render-utils/src/MeshPartPayload.h | 2 +- .../render-utils/src/RenderShadowTask.cpp | 2 +- libraries/render-utils/src/RenderViewTask.cpp | 4 ++-- libraries/render-utils/src/RenderViewTask.h | 2 +- libraries/render/src/render/Item.h | 19 +++++++++++++------ .../src/render/RenderFetchCullSortTask.cpp | 18 +++++++++--------- .../src/render/RenderFetchCullSortTask.h | 2 +- 11 files changed, 35 insertions(+), 25 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6849bd07b5..e9ea9a0295 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2200,7 +2200,7 @@ void Application::initializeGL() { bool isDeferred = !QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD); _renderEngine->addJob("UpdateScene"); _renderEngine->addJob("SecondaryCameraJob", cullFunctor); - _renderEngine->addJob("RenderMainView", cullFunctor, isDeferred); + _renderEngine->addJob("RenderMainView", cullFunctor, isDeferred, render::ItemKey::VISIBLE_MASK_0, render::ItemKey::VISIBLE_MASK_0); _renderEngine->load(); _renderEngine->registerScene(_main3DScene); diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index 4cfa4d6156..35eff68ab3 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -20,7 +20,7 @@ using RenderArgsPointer = std::shared_ptr; void MainRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred) { task.addJob("RenderShadowTask", cullFunctor); - const auto items = task.addJob("FetchCullSort", cullFunctor); + const auto items = task.addJob("FetchCullSort", cullFunctor, render::ItemKey::VISIBLE_MASK_1, render::ItemKey::VISIBLE_MASK_1); assert(items.canCast()); if (!isDeferred) { task.addJob("Forward", items); diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index e3f26a43d8..09b6ada8e4 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -247,7 +247,7 @@ void CauterizedModel::updateRenderItems() { data.updateTransformForCauterizedMesh(renderTransform); data.setEnableCauterization(enableCauterization); - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD); + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, enableCauterization); data.setLayer(isLayeredInFront, isLayeredInHUD); data.setShapeKey(invalidatePayloadShapeKey, isWireframe); }); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index c506887fc4..ead2a767db 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -389,13 +389,16 @@ void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& render _worldBound.transform(boundTransform); } -void ModelMeshPartPayload::setKey(bool isVisible, bool isLayered) { +void ModelMeshPartPayload::setKey(bool isVisible, bool isLayered, bool isCauterized) { ItemKey::Builder builder; builder.withTypeShape(); if (!isVisible) { builder.withInvisible(); } + else if (isCauterized) { + builder.withInvisible(0); // hide these items in the vibility mask #0 + } if (isLayered) { builder.withLayered(); diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 8160b9f009..ee515c7b3d 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -103,7 +103,7 @@ public: render::ShapeKey getShapeKey() const override; // shape interface void render(RenderArgs* args) override; - void setKey(bool isVisible, bool isLayered); + void setKey(bool isVisible, bool isLayered, bool isCauterized = false); void setLayer(bool isLayeredInFront, bool isLayeredInHUD); void setShapeKey(bool invalidateShapeKey, bool isWireframe); diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 378b164e67..7a7714e1e0 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -264,7 +264,7 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon const auto globalShadow = lightStage->getCurrentKeyShadow(); if (globalShadow && _cascadeIndexgetCascadeCount()) { - output.edit1() = ItemFilter::Builder::visibleWorldItems(0x08).withTypeShape().withOpaque().withoutLayered(); + output.edit1() = ItemFilter::Builder::visibleWorldItems(0x00, 0x00).withTypeShape().withOpaque().withoutLayered(); globalShadow->setKeylightCascadeFrustum(_cascadeIndex, args->getViewFrustum(), SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR); diff --git a/libraries/render-utils/src/RenderViewTask.cpp b/libraries/render-utils/src/RenderViewTask.cpp index 434e069d28..83868e1443 100644 --- a/libraries/render-utils/src/RenderViewTask.cpp +++ b/libraries/render-utils/src/RenderViewTask.cpp @@ -14,7 +14,7 @@ #include "RenderDeferredTask.h" #include "RenderForwardTask.h" -void RenderViewTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, bool isDeferred, uint8_t visibilityMask) { +void RenderViewTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, bool isDeferred, uint8_t visibilityMask, uint8_t visibilityMaskTouched) { // auto items = input.get(); // Shadows use an orthographic projection because they are linked to sunlights @@ -30,7 +30,7 @@ void RenderViewTask::build(JobModel& task, const render::Varying& input, render: return true; }); - const auto items = task.addJob("FetchCullSort", cullFunctor, visibilityMask); + const auto items = task.addJob("FetchCullSort", cullFunctor, visibilityMask, visibilityMaskTouched); assert(items.canCast()); if (isDeferred) { diff --git a/libraries/render-utils/src/RenderViewTask.h b/libraries/render-utils/src/RenderViewTask.h index 9c2bbe0281..faace7349e 100644 --- a/libraries/render-utils/src/RenderViewTask.h +++ b/libraries/render-utils/src/RenderViewTask.h @@ -23,7 +23,7 @@ public: RenderViewTask() {} - void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred, uint8_t visibilityMask = 0xFF); + void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred, uint8_t visibilityMask = 0xFF, uint8_t visibilityMaskTouched = 0x00); }; diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 8594bc2954..3da7b07d7d 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -65,6 +65,10 @@ public: // Beware that the visibility mask is the oposite of what stored in the key vals. const static uint8_t NUM_VISIBLE_MASK_INDICES{ 4 }; const static uint8_t VISIBLE_MASK_ALL{ 0x0F }; + const static uint8_t VISIBLE_MASK_0{ 0x01 }; + const static uint8_t VISIBLE_MASK_1{ 0x02 }; + const static uint8_t VISIBLE_MASK_2{ 0x04 }; + const static uint8_t VISIBLE_MASK_3{ 0x08 }; // The key is the Flags Flags _flags; @@ -184,12 +188,15 @@ public: Builder& withVisible(uint8_t maskIndex) { _value.reset(ItemKey::INVISIBLE0 + maskIndex); _mask.set(ItemKey::INVISIBLE0 + maskIndex); return (*this); } Builder& withInvisible(uint8_t maskIndex) { _value.set(ItemKey::INVISIBLE0 + maskIndex); _mask.set(ItemKey::INVISIBLE0 + maskIndex); return (*this); } - Builder& withVisibilityMask(uint8_t mask) { + Builder& withVisibilityMask(uint8_t mask, uint8_t touchBits) { for (int i = 0; i < ItemKey::NUM_VISIBLE_MASK_INDICES; i++) { - if ((1 << i) && mask) { - withVisible(i); - } else { - withInvisible(i); + if ((1 << i) & touchBits) { + if ((1 << i) & mask) { + withVisible(i); + } + else { + withInvisible(i); + } } } return (*this); @@ -206,7 +213,7 @@ public: Builder& withNothing() { _value.reset(); _mask.reset(); return (*this); } // Convenient standard keys that we will keep on using all over the place - static Builder visibleWorldItems(uint8_t visibilityMask) { return Builder().withVisibilityMask(visibilityMask).withWorldSpace(); } + static Builder visibleWorldItems(uint8_t visibilityMask, uint8_t visibilityMaskTouched) { return Builder().withVisibilityMask(visibilityMask, visibilityMaskTouched).withWorldSpace(); } static Builder opaqueShape() { return Builder().withTypeShape().withOpaque().withWorldSpace(); } static Builder transparentShape() { return Builder().withTypeShape().withTransparent().withWorldSpace(); } static Builder light() { return Builder().withTypeLight(); } diff --git a/libraries/render/src/render/RenderFetchCullSortTask.cpp b/libraries/render/src/render/RenderFetchCullSortTask.cpp index 25c40ea7f7..b4e1a618dc 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.cpp +++ b/libraries/render/src/render/RenderFetchCullSortTask.cpp @@ -17,12 +17,12 @@ using namespace render; -void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varying& output, CullFunctor cullFunctor, uint8_t visibilityMask) { +void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varying& output, CullFunctor cullFunctor, uint8_t visibilityMask, uint8_t visibilityMaskTouched) { cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&){ return true; }; // CPU jobs: // Fetch and cull the items from the scene - const ItemFilter filter = ItemFilter::Builder::visibleWorldItems(visibilityMask).withoutLayered(); + const ItemFilter filter = ItemFilter::Builder::visibleWorldItems(visibilityMask, visibilityMaskTouched).withoutLayered(); const auto spatialFilter = render::Varying(filter); const auto spatialSelection = task.addJob("FetchSceneSelection", spatialFilter); const auto cullInputs = CullSpatialSelection::Inputs(spatialSelection, spatialFilter).asVarying(); @@ -40,15 +40,15 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin const int META_BUCKET = 3; const int BACKGROUND_BUCKET = 2; MultiFilterItems::ItemFilterArray spatialFilters = { { - ItemFilter::Builder::opaqueShape(), - ItemFilter::Builder::transparentShape(), - ItemFilter::Builder::light(), - ItemFilter::Builder::meta() + ItemFilter::Builder::opaqueShape().withVisibilityMask(visibilityMask, visibilityMaskTouched), + ItemFilter::Builder::transparentShape().withVisibilityMask(visibilityMask, visibilityMaskTouched), + ItemFilter::Builder::light().withVisibilityMask(visibilityMask, visibilityMaskTouched), + ItemFilter::Builder::meta().withVisibilityMask(visibilityMask, visibilityMaskTouched) } }; MultiFilterItems::ItemFilterArray nonspatialFilters = { { - ItemFilter::Builder::opaqueShape(), - ItemFilter::Builder::transparentShape(), - ItemFilter::Builder::background() + ItemFilter::Builder::opaqueShape().withVisibilityMask(visibilityMask, visibilityMaskTouched), + ItemFilter::Builder::transparentShape().withVisibilityMask(visibilityMask, visibilityMaskTouched), + ItemFilter::Builder::background().withVisibilityMask(visibilityMask, visibilityMaskTouched) } }; const auto filteredSpatialBuckets = task.addJob>("FilterSceneSelection", culledSpatialSelection, spatialFilters) diff --git a/libraries/render/src/render/RenderFetchCullSortTask.h b/libraries/render/src/render/RenderFetchCullSortTask.h index 3e5ad2bad8..9aa235b3fb 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.h +++ b/libraries/render/src/render/RenderFetchCullSortTask.h @@ -36,7 +36,7 @@ public: RenderFetchCullSortTask() {} - void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, uint8_t visibilityMask = 0xFF); + void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, uint8_t visibilityMask = 0xFF, uint8_t visibilityMaskTouched = 0x00); }; #endif // hifi_RenderFetchCullSortTask_h From 97a4f141eb6048c3d245a02716f58c0bb4f67cdc Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 18 Jan 2018 08:12:14 -0800 Subject: [PATCH 09/57] fix link trouble --- libraries/render/src/render/Item.cpp | 8 ++++++++ libraries/render/src/render/Item.h | 12 ++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index 036c7d3a99..75c38ec615 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -34,6 +34,14 @@ const int Item::LAYER_3D = 1; const int Item::LAYER_3D_FRONT = 2; const int Item::LAYER_3D_HUD = 3; +const uint8_t ItemKey::NUM_VISIBLE_MASK_INDICES { 4 }; +const uint8_t ItemKey::VISIBLE_MASK_ALL { 0x0F }; +const uint8_t ItemKey::VISIBLE_MASK_0 { 0x01 }; +const uint8_t ItemKey::VISIBLE_MASK_1 { 0x02 }; +const uint8_t ItemKey::VISIBLE_MASK_2 { 0x04 }; +const uint8_t ItemKey::VISIBLE_MASK_3 { 0x08 }; + + void Item::Status::Value::setScale(float scale) { _scale = (std::numeric_limits::max() -1) * 0.5f * (1.0f + std::max(std::min(scale, 1.0f), 0.0f)); } diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 3da7b07d7d..ebf3980489 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -63,12 +63,12 @@ public: // VISIBLE MASK is defined from several bits in the Key. // An Item can be visible in some mask bits and not other allowing for per view rendering // Beware that the visibility mask is the oposite of what stored in the key vals. - const static uint8_t NUM_VISIBLE_MASK_INDICES{ 4 }; - const static uint8_t VISIBLE_MASK_ALL{ 0x0F }; - const static uint8_t VISIBLE_MASK_0{ 0x01 }; - const static uint8_t VISIBLE_MASK_1{ 0x02 }; - const static uint8_t VISIBLE_MASK_2{ 0x04 }; - const static uint8_t VISIBLE_MASK_3{ 0x08 }; + const static uint8_t NUM_VISIBLE_MASK_INDICES; + const static uint8_t VISIBLE_MASK_ALL; + const static uint8_t VISIBLE_MASK_0; + const static uint8_t VISIBLE_MASK_1; + const static uint8_t VISIBLE_MASK_2; + const static uint8_t VISIBLE_MASK_3; // The key is the Flags Flags _flags; From 1c819c84224b077fa1e203429478a0916d9b4805 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 18 Jan 2018 09:12:37 -0800 Subject: [PATCH 10/57] formatting --- libraries/entities-renderer/src/RenderableEntityItem.cpp | 4 ++-- libraries/render-utils/src/MeshPartPayload.cpp | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index f3ef956146..0988c696dd 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -187,8 +187,8 @@ void EntityRenderer::render(RenderArgs* args) { auto& renderMode = args->_renderMode; bool cauterized = (renderMode != RenderArgs::RenderMode::SHADOW_RENDER_MODE && - renderMode != RenderArgs::RenderMode::SECONDARY_CAMERA_RENDER_MODE) && - _cauterized; + renderMode != RenderArgs::RenderMode::SECONDARY_CAMERA_RENDER_MODE && + _cauterized); if (_visible && !cauterized) { doRender(args); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index ead2a767db..de03f2e03d 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -395,8 +395,7 @@ void ModelMeshPartPayload::setKey(bool isVisible, bool isLayered, bool isCauteri if (!isVisible) { builder.withInvisible(); - } - else if (isCauterized) { + } else if (isCauterized) { builder.withInvisible(0); // hide these items in the vibility mask #0 } From fb974b0b9c93f77d75fe460ae7fcfa03c83e43ad Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 18 Jan 2018 10:09:23 -0800 Subject: [PATCH 11/57] attempt to straighten out use of view-visibility masks --- interface/src/avatar/MyAvatar.cpp | 9 +++++---- interface/src/ui/overlays/ModelOverlay.cpp | 3 ++- .../src/RenderableModelEntityItem.cpp | 10 +++++++--- libraries/render-utils/src/CauterizedModel.cpp | 2 +- libraries/render-utils/src/MeshPartPayload.cpp | 6 +++--- libraries/render-utils/src/MeshPartPayload.h | 2 +- libraries/render-utils/src/Model.cpp | 16 ++++++++-------- libraries/render-utils/src/Model.h | 2 +- 8 files changed, 28 insertions(+), 22 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0b5bdad6ae..e9205157b4 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1078,7 +1078,7 @@ void MyAvatar::setEnableDebugDrawIKChains(bool isEnabled) { } void MyAvatar::setEnableMeshVisible(bool isEnabled) { - _skeletonModel->setVisibleInScene(isEnabled, qApp->getMain3DScene()); + _skeletonModel->setVisibleInScene(isEnabled, qApp->getMain3DScene(), render::ItemKey::VISIBLE_MASK_ALL); } void MyAvatar::setEnableInverseKinematics(bool isEnabled) { @@ -1428,7 +1428,7 @@ void MyAvatar::clearJointsData() { void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { Avatar::setSkeletonModelURL(skeletonModelURL); - _skeletonModel->setVisibleInScene(true, qApp->getMain3DScene()); + _skeletonModel->setVisibleInScene(true, qApp->getMain3DScene(), render::ItemKey::VISIBLE_MASK_ALL); _headBoneSet.clear(); emit skeletonChanged(); @@ -1742,7 +1742,7 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName, void MyAvatar::setVisibleInSceneIfReady(Model* model, const render::ScenePointer& scene, bool visible) { if (model->isActive() && model->isRenderable()) { - model->setVisibleInScene(visible, scene); + model->setVisibleInScene(visible, scene, render::ItemKey::VISIBLE_MASK_ALL); } } @@ -1937,7 +1937,8 @@ void MyAvatar::preDisplaySide(RenderArgs* renderArgs) { _attachmentData[i].jointName.compare("RightEye", Qt::CaseInsensitive) == 0 || _attachmentData[i].jointName.compare("HeadTop_End", Qt::CaseInsensitive) == 0 || _attachmentData[i].jointName.compare("Face", Qt::CaseInsensitive) == 0) { - _attachmentModels[i]->setVisibleInScene(shouldDrawHead, qApp->getMain3DScene()); + _attachmentModels[i]->setVisibleInScene(shouldDrawHead, qApp->getMain3DScene(), + render::ItemKey::VISIBLE_MASK_ALL); } } } diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index ec586771af..f556bc9e24 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -86,7 +86,8 @@ void ModelOverlay::update(float deltatime) { } if (_visibleDirty) { _visibleDirty = false; - _model->setVisibleInScene(getVisible(), scene); + // don't show overlays in mirrors + _model->setVisibleInScene(getVisible(), scene, render::ItemKey::VISIBLE_MASK_ALL & ~render::ItemKey::VISIBLE_MASK_1); } if (_drawInFrontDirty) { _drawInFrontDirty = false; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index f7d7eb2a06..421f8769b5 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1333,12 +1333,16 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce entity->updateModelBounds(); entity->stopModelOverrideIfNoParent(); - bool visible = _visible && !_cauterized; - if (model->isVisible() != visible) { + if (model->isVisible() != _visible) { // FIXME: this seems like it could be optimized if we tracked our last known visible state in // the renderable item. As it stands now the model checks it's visible/invisible state // so most of the time we don't do anything in this function. - model->setVisibleInScene(visible, scene); + if (_cauterized) { + // draw this in every view except the main one + model->setVisibleInScene(_visible, scene, render::ItemKey::VISIBLE_MASK_ALL & ~render::ItemKey::VISIBLE_MASK_0); + } else { + model->setVisibleInScene(_visible, scene, render::ItemKey::VISIBLE_MASK_ALL); + } } // TODO? early exit here when not visible? diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 09b6ada8e4..809be09436 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -247,7 +247,7 @@ void CauterizedModel::updateRenderItems() { data.updateTransformForCauterizedMesh(renderTransform); data.setEnableCauterization(enableCauterization); - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, enableCauterization); + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_ALL); data.setLayer(isLayeredInFront, isLayeredInHUD); data.setShapeKey(invalidatePayloadShapeKey, isWireframe); }); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index de03f2e03d..797f385695 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -389,14 +389,14 @@ void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& render _worldBound.transform(boundTransform); } -void ModelMeshPartPayload::setKey(bool isVisible, bool isLayered, bool isCauterized) { +void ModelMeshPartPayload::setKey(bool isVisible, bool isLayered, uint8_t viewVisiblityMask) { ItemKey::Builder builder; builder.withTypeShape(); if (!isVisible) { builder.withInvisible(); - } else if (isCauterized) { - builder.withInvisible(0); // hide these items in the vibility mask #0 + } else { + builder.withInvisible(viewVisiblityMask); } if (isLayered) { diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index ee515c7b3d..cf64879b3c 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -103,7 +103,7 @@ public: render::ShapeKey getShapeKey() const override; // shape interface void render(RenderArgs* args) override; - void setKey(bool isVisible, bool isLayered, bool isCauterized = false); + void setKey(bool isVisible, bool isLayered, uint8_t viewVisiblityMask); void setLayer(bool isLayeredInFront, bool isLayeredInHUD); void setShapeKey(bool invalidateShapeKey, bool isWireframe); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 6922e95d39..b04ff00f98 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -297,7 +297,7 @@ void Model::updateRenderItems() { } data.updateTransformForSkinnedMesh(renderTransform, modelTransform); - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD); + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_ALL); data.setLayer(isLayeredInFront, isLayeredInHUD); data.setShapeKey(invalidatePayloadShapeKey, isWireframe); }); @@ -659,7 +659,7 @@ void Model::calculateTriangleSets() { } } -void Model::setVisibleInScene(bool isVisible, const render::ScenePointer& scene) { +void Model::setVisibleInScene(bool isVisible, const render::ScenePointer& scene, uint8_t visibleMask) { if (_isVisible != isVisible) { _isVisible = isVisible; @@ -669,12 +669,12 @@ void Model::setVisibleInScene(bool isVisible, const render::ScenePointer& scene) render::Transaction transaction; foreach (auto item, _modelMeshRenderItemsMap.keys()) { transaction.updateItem(item, [isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD); + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_ALL); }); } foreach(auto item, _collisionRenderItemsMap.keys()) { transaction.updateItem(item, [isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD); + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_ALL); }); } scene->enqueueTransaction(transaction); @@ -692,13 +692,13 @@ void Model::setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& render::Transaction transaction; foreach(auto item, _modelMeshRenderItemsMap.keys()) { transaction.updateItem(item, [isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD); + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_ALL); data.setLayer(isLayeredInFront, isLayeredInHUD); }); } foreach(auto item, _collisionRenderItemsMap.keys()) { transaction.updateItem(item, [isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD); + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_ALL); data.setLayer(isLayeredInFront, isLayeredInHUD); }); } @@ -716,13 +716,13 @@ void Model::setLayeredInHUD(bool isLayeredInHUD, const render::ScenePointer& sce render::Transaction transaction; foreach(auto item, _modelMeshRenderItemsMap.keys()) { transaction.updateItem(item, [isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD); + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_ALL); data.setLayer(isLayeredInFront, isLayeredInHUD); }); } foreach(auto item, _collisionRenderItemsMap.keys()) { transaction.updateItem(item, [isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD); + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_ALL); data.setLayer(isLayeredInFront, isLayeredInHUD); }); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 560aa82f0c..8d2619bf13 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -86,7 +86,7 @@ public: const QUrl& getURL() const { return _url; } // new Scene/Engine rendering support - void setVisibleInScene(bool isVisible, const render::ScenePointer& scene); + void setVisibleInScene(bool isVisible, const render::ScenePointer& scene, uint8_t visibleMask); void setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& scene); void setLayeredInHUD(bool isLayeredInHUD, const render::ScenePointer& scene); bool needsFixupInScene() const; From 0ad4cdc41b47618bdb712fad907b54e980281c12 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 18 Jan 2018 13:15:47 -0800 Subject: [PATCH 12/57] works now --- .../src/RenderableModelEntityItem.cpp | 13 +++--- .../render-utils/src/MeshPartPayload.cpp | 13 +++++- libraries/render-utils/src/Model.cpp | 46 ++++++++++++------- libraries/render-utils/src/Model.h | 4 +- 4 files changed, 50 insertions(+), 26 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 421f8769b5..80c5c97799 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1333,16 +1333,15 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce entity->updateModelBounds(); entity->stopModelOverrideIfNoParent(); - if (model->isVisible() != _visible) { + uint32_t viewVisiblityMask = _cauterized ? + (render::ItemKey::VISIBLE_MASK_ALL & ~render::ItemKey::VISIBLE_MASK_0) : // draw in every view except the main one + render::ItemKey::VISIBLE_MASK_ALL; + + if (model->isVisible() != _visible || model->getViewVisibilityMask() != viewVisiblityMask) { // FIXME: this seems like it could be optimized if we tracked our last known visible state in // the renderable item. As it stands now the model checks it's visible/invisible state // so most of the time we don't do anything in this function. - if (_cauterized) { - // draw this in every view except the main one - model->setVisibleInScene(_visible, scene, render::ItemKey::VISIBLE_MASK_ALL & ~render::ItemKey::VISIBLE_MASK_0); - } else { - model->setVisibleInScene(_visible, scene, render::ItemKey::VISIBLE_MASK_ALL); - } + model->setVisibleInScene(_visible, scene, viewVisiblityMask); } // TODO? early exit here when not visible? diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 797f385695..b917f3df03 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -396,7 +396,18 @@ void ModelMeshPartPayload::setKey(bool isVisible, bool isLayered, uint8_t viewVi if (!isVisible) { builder.withInvisible(); } else { - builder.withInvisible(viewVisiblityMask); + if (!(viewVisiblityMask & render::ItemKey::VISIBLE_MASK_0)) { + builder.withInvisible(render::ItemKey::INVISIBLE0 - render::ItemKey::INVISIBLE0); + } + if (!(viewVisiblityMask & render::ItemKey::VISIBLE_MASK_1)) { + builder.withInvisible(render::ItemKey::INVISIBLE1 - render::ItemKey::INVISIBLE0); + } + if (!(viewVisiblityMask & render::ItemKey::VISIBLE_MASK_2)) { + builder.withInvisible(render::ItemKey::INVISIBLE2 - render::ItemKey::INVISIBLE0); + } + if (!(viewVisiblityMask & render::ItemKey::VISIBLE_MASK_3)) { + builder.withInvisible(render::ItemKey::INVISIBLE3 - render::ItemKey::INVISIBLE0); + } } if (isLayered) { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index b04ff00f98..9e6ec064b4 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -268,6 +268,7 @@ void Model::updateRenderItems() { bool isWireframe = self->isWireframe(); bool isVisible = self->isVisible(); + uint8_t viewVisibilityMask = self->getViewVisibilityMask(); bool isLayeredInFront = self->isLayeredInFront(); bool isLayeredInHUD = self->isLayeredInHUD(); @@ -280,8 +281,10 @@ void Model::updateRenderItems() { bool invalidatePayloadShapeKey = self->shouldInvalidatePayloadShapeKey(meshIndex); - transaction.updateItem(itemID, [modelTransform, clusterTransforms, invalidatePayloadShapeKey, - isWireframe, isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { + transaction.updateItem(itemID, [modelTransform, clusterTransforms, + invalidatePayloadShapeKey, isWireframe, isVisible, + viewVisibilityMask, isLayeredInFront, + isLayeredInHUD](ModelMeshPartPayload& data) { data.updateClusterBuffer(clusterTransforms); Transform renderTransform = modelTransform; @@ -297,7 +300,7 @@ void Model::updateRenderItems() { } data.updateTransformForSkinnedMesh(renderTransform, modelTransform); - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_ALL); + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, viewVisibilityMask); data.setLayer(isLayeredInFront, isLayeredInHUD); data.setShapeKey(invalidatePayloadShapeKey, isWireframe); }); @@ -659,22 +662,25 @@ void Model::calculateTriangleSets() { } } -void Model::setVisibleInScene(bool isVisible, const render::ScenePointer& scene, uint8_t visibleMask) { - if (_isVisible != isVisible) { +void Model::setVisibleInScene(bool isVisible, const render::ScenePointer& scene, uint8_t viewVisibilityMask) { + if (_isVisible != isVisible || _viewVisibilityMask != viewVisibilityMask) { _isVisible = isVisible; + _viewVisibilityMask = viewVisibilityMask; bool isLayeredInFront = _isLayeredInFront; bool isLayeredInHUD = _isLayeredInHUD; render::Transaction transaction; foreach (auto item, _modelMeshRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_ALL); + transaction.updateItem(item, [isVisible, viewVisibilityMask, isLayeredInFront, + isLayeredInHUD](ModelMeshPartPayload& data) { + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, 14); }); } foreach(auto item, _collisionRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_ALL); + transaction.updateItem(item, [isVisible, viewVisibilityMask, isLayeredInFront, + isLayeredInHUD](ModelMeshPartPayload& data) { + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, 14); }); } scene->enqueueTransaction(transaction); @@ -687,18 +693,21 @@ void Model::setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& _isLayeredInFront = isLayeredInFront; bool isVisible = _isVisible; + uint8_t viewVisibilityMask = _viewVisibilityMask; bool isLayeredInHUD = _isLayeredInHUD; render::Transaction transaction; foreach(auto item, _modelMeshRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_ALL); + transaction.updateItem(item, [isVisible, viewVisibilityMask, isLayeredInFront, + isLayeredInHUD](ModelMeshPartPayload& data) { + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, viewVisibilityMask); data.setLayer(isLayeredInFront, isLayeredInHUD); }); } foreach(auto item, _collisionRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_ALL); + transaction.updateItem(item, [isVisible, viewVisibilityMask, isLayeredInFront, + isLayeredInHUD](ModelMeshPartPayload& data) { + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, viewVisibilityMask); data.setLayer(isLayeredInFront, isLayeredInHUD); }); } @@ -711,18 +720,21 @@ void Model::setLayeredInHUD(bool isLayeredInHUD, const render::ScenePointer& sce _isLayeredInHUD = isLayeredInHUD; bool isVisible = _isVisible; + uint8_t viewVisibilityMask = _viewVisibilityMask; bool isLayeredInFront = _isLayeredInFront; render::Transaction transaction; foreach(auto item, _modelMeshRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_ALL); + transaction.updateItem(item, [isVisible, viewVisibilityMask, isLayeredInFront, + isLayeredInHUD](ModelMeshPartPayload& data) { + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, viewVisibilityMask); data.setLayer(isLayeredInFront, isLayeredInHUD); }); } foreach(auto item, _collisionRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_ALL); + transaction.updateItem(item, [isVisible, viewVisibilityMask, isLayeredInFront, + isLayeredInHUD](ModelMeshPartPayload& data) { + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, viewVisibilityMask); data.setLayer(isLayeredInFront, isLayeredInHUD); }); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 8d2619bf13..c2f8a3d972 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -86,7 +86,7 @@ public: const QUrl& getURL() const { return _url; } // new Scene/Engine rendering support - void setVisibleInScene(bool isVisible, const render::ScenePointer& scene, uint8_t visibleMask); + void setVisibleInScene(bool isVisible, const render::ScenePointer& scene, uint8_t viewVisiblityMask); void setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& scene); void setLayeredInHUD(bool isLayeredInHUD, const render::ScenePointer& scene); bool needsFixupInScene() const; @@ -104,6 +104,7 @@ public: bool isRenderable() const; bool isVisible() const { return _isVisible; } + uint8_t getViewVisibilityMask() const { return _viewVisibilityMask; } bool isLayeredInFront() const { return _isLayeredInFront; } bool isLayeredInHUD() const { return _isLayeredInHUD; } @@ -388,6 +389,7 @@ protected: QUrl _url; bool _isVisible; + uint32_t _viewVisibilityMask { 0 }; gpu::Buffers _blendedVertexBuffers; From 7c32d3c5360497bb8e531ad1fc1e49edc2879136 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 18 Jan 2018 13:49:17 -0800 Subject: [PATCH 13/57] flip logic back around --- interface/src/ui/overlays/ModelOverlay.cpp | 2 +- .../entities-renderer/src/RenderableModelEntityItem.cpp | 4 ++-- libraries/render-utils/src/MeshPartPayload.cpp | 8 ++++---- libraries/render-utils/src/Model.cpp | 4 ++-- libraries/render-utils/src/Model.h | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index f556bc9e24..7ba8694683 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -87,7 +87,7 @@ void ModelOverlay::update(float deltatime) { if (_visibleDirty) { _visibleDirty = false; // don't show overlays in mirrors - _model->setVisibleInScene(getVisible(), scene, render::ItemKey::VISIBLE_MASK_ALL & ~render::ItemKey::VISIBLE_MASK_1); + _model->setVisibleInScene(getVisible(), scene, render::ItemKey::VISIBLE_MASK_1); } if (_drawInFrontDirty) { _drawInFrontDirty = false; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 80c5c97799..8257e53eea 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1334,8 +1334,8 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce entity->stopModelOverrideIfNoParent(); uint32_t viewVisiblityMask = _cauterized ? - (render::ItemKey::VISIBLE_MASK_ALL & ~render::ItemKey::VISIBLE_MASK_0) : // draw in every view except the main one - render::ItemKey::VISIBLE_MASK_ALL; + render::ItemKey::VISIBLE_MASK_0 : // draw in every view except the main one + render::ItemKey::VISIBLE_MASK_ALL; // draw in all views if (model->isVisible() != _visible || model->getViewVisibilityMask() != viewVisiblityMask) { // FIXME: this seems like it could be optimized if we tracked our last known visible state in diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index b917f3df03..f0412d8332 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -396,16 +396,16 @@ void ModelMeshPartPayload::setKey(bool isVisible, bool isLayered, uint8_t viewVi if (!isVisible) { builder.withInvisible(); } else { - if (!(viewVisiblityMask & render::ItemKey::VISIBLE_MASK_0)) { + if (viewVisiblityMask & render::ItemKey::VISIBLE_MASK_0) { builder.withInvisible(render::ItemKey::INVISIBLE0 - render::ItemKey::INVISIBLE0); } - if (!(viewVisiblityMask & render::ItemKey::VISIBLE_MASK_1)) { + if (viewVisiblityMask & render::ItemKey::VISIBLE_MASK_1) { builder.withInvisible(render::ItemKey::INVISIBLE1 - render::ItemKey::INVISIBLE0); } - if (!(viewVisiblityMask & render::ItemKey::VISIBLE_MASK_2)) { + if (viewVisiblityMask & render::ItemKey::VISIBLE_MASK_2) { builder.withInvisible(render::ItemKey::INVISIBLE2 - render::ItemKey::INVISIBLE0); } - if (!(viewVisiblityMask & render::ItemKey::VISIBLE_MASK_3)) { + if (viewVisiblityMask & render::ItemKey::VISIBLE_MASK_3) { builder.withInvisible(render::ItemKey::INVISIBLE3 - render::ItemKey::INVISIBLE0); } } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 9e6ec064b4..60eb0c4280 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -674,13 +674,13 @@ void Model::setVisibleInScene(bool isVisible, const render::ScenePointer& scene, foreach (auto item, _modelMeshRenderItemsMap.keys()) { transaction.updateItem(item, [isVisible, viewVisibilityMask, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, 14); + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, viewVisibilityMask); }); } foreach(auto item, _collisionRenderItemsMap.keys()) { transaction.updateItem(item, [isVisible, viewVisibilityMask, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, 14); + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, viewVisibilityMask); }); } scene->enqueueTransaction(transaction); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index c2f8a3d972..5f58906e9f 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -389,7 +389,7 @@ protected: QUrl _url; bool _isVisible; - uint32_t _viewVisibilityMask { 0 }; + uint8_t _viewVisibilityMask { 0 }; gpu::Buffers _blendedVertexBuffers; From 31c007d1672a970dc5a1bfbe11b88801fb36f55b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 18 Jan 2018 14:15:30 -0800 Subject: [PATCH 14/57] more backwards logic, added withViewVisibilityMask call in ItemKey --- interface/src/avatar/MyAvatar.cpp | 8 ++++---- .../src/RenderableModelEntityItem.cpp | 4 ++-- libraries/entities/src/EntityItem.h | 2 +- libraries/render-utils/src/CauterizedModel.cpp | 2 +- libraries/render-utils/src/MeshPartPayload.cpp | 13 +------------ libraries/render/src/render/Item.cpp | 1 + libraries/render/src/render/Item.h | 16 ++++++++++++++++ 7 files changed, 26 insertions(+), 20 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e9205157b4..317eede6e9 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1078,7 +1078,7 @@ void MyAvatar::setEnableDebugDrawIKChains(bool isEnabled) { } void MyAvatar::setEnableMeshVisible(bool isEnabled) { - _skeletonModel->setVisibleInScene(isEnabled, qApp->getMain3DScene(), render::ItemKey::VISIBLE_MASK_ALL); + _skeletonModel->setVisibleInScene(isEnabled, qApp->getMain3DScene(), render::ItemKey::VISIBLE_MASK_NONE); } void MyAvatar::setEnableInverseKinematics(bool isEnabled) { @@ -1428,7 +1428,7 @@ void MyAvatar::clearJointsData() { void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { Avatar::setSkeletonModelURL(skeletonModelURL); - _skeletonModel->setVisibleInScene(true, qApp->getMain3DScene(), render::ItemKey::VISIBLE_MASK_ALL); + _skeletonModel->setVisibleInScene(true, qApp->getMain3DScene(), render::ItemKey::VISIBLE_MASK_NONE); _headBoneSet.clear(); emit skeletonChanged(); @@ -1742,7 +1742,7 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName, void MyAvatar::setVisibleInSceneIfReady(Model* model, const render::ScenePointer& scene, bool visible) { if (model->isActive() && model->isRenderable()) { - model->setVisibleInScene(visible, scene, render::ItemKey::VISIBLE_MASK_ALL); + model->setVisibleInScene(visible, scene, render::ItemKey::VISIBLE_MASK_NONE); } } @@ -1938,7 +1938,7 @@ void MyAvatar::preDisplaySide(RenderArgs* renderArgs) { _attachmentData[i].jointName.compare("HeadTop_End", Qt::CaseInsensitive) == 0 || _attachmentData[i].jointName.compare("Face", Qt::CaseInsensitive) == 0) { _attachmentModels[i]->setVisibleInScene(shouldDrawHead, qApp->getMain3DScene(), - render::ItemKey::VISIBLE_MASK_ALL); + render::ItemKey::VISIBLE_MASK_NONE); } } } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 8257e53eea..a6991f101c 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1334,8 +1334,8 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce entity->stopModelOverrideIfNoParent(); uint32_t viewVisiblityMask = _cauterized ? - render::ItemKey::VISIBLE_MASK_0 : // draw in every view except the main one - render::ItemKey::VISIBLE_MASK_ALL; // draw in all views + render::ItemKey::VISIBLE_MASK_0 : // draw in every view except the main one (view zero) + render::ItemKey::VISIBLE_MASK_NONE; // draw in all views if (model->isVisible() != _visible || model->getViewVisibilityMask() != viewVisiblityMask) { // FIXME: this seems like it could be optimized if we tracked our last known visible state in diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 68639e0d3a..3024d646ff 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -625,7 +625,7 @@ protected: quint64 _lastUpdatedAccelerationTimestamp { 0 }; quint64 _lastUpdatedQueryAACubeTimestamp { 0 }; - bool _cauterized { false }; // it true, don't draw because it would obscure 1st-person camera + bool _cauterized { false }; // if true, don't draw because it would obscure 1st-person camera }; #endif // hifi_EntityItem_h diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 809be09436..f67f5ef358 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -247,7 +247,7 @@ void CauterizedModel::updateRenderItems() { data.updateTransformForCauterizedMesh(renderTransform); data.setEnableCauterization(enableCauterization); - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_ALL); + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_NONE); data.setLayer(isLayeredInFront, isLayeredInHUD); data.setShapeKey(invalidatePayloadShapeKey, isWireframe); }); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index f0412d8332..da636eed06 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -396,18 +396,7 @@ void ModelMeshPartPayload::setKey(bool isVisible, bool isLayered, uint8_t viewVi if (!isVisible) { builder.withInvisible(); } else { - if (viewVisiblityMask & render::ItemKey::VISIBLE_MASK_0) { - builder.withInvisible(render::ItemKey::INVISIBLE0 - render::ItemKey::INVISIBLE0); - } - if (viewVisiblityMask & render::ItemKey::VISIBLE_MASK_1) { - builder.withInvisible(render::ItemKey::INVISIBLE1 - render::ItemKey::INVISIBLE0); - } - if (viewVisiblityMask & render::ItemKey::VISIBLE_MASK_2) { - builder.withInvisible(render::ItemKey::INVISIBLE2 - render::ItemKey::INVISIBLE0); - } - if (viewVisiblityMask & render::ItemKey::VISIBLE_MASK_3) { - builder.withInvisible(render::ItemKey::INVISIBLE3 - render::ItemKey::INVISIBLE0); - } + builder.withViewVisibilityMask(viewVisiblityMask); } if (isLayered) { diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index 75c38ec615..0e4502a47c 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -36,6 +36,7 @@ const int Item::LAYER_3D_HUD = 3; const uint8_t ItemKey::NUM_VISIBLE_MASK_INDICES { 4 }; const uint8_t ItemKey::VISIBLE_MASK_ALL { 0x0F }; +const uint8_t ItemKey::VISIBLE_MASK_NONE { 0x00 }; const uint8_t ItemKey::VISIBLE_MASK_0 { 0x01 }; const uint8_t ItemKey::VISIBLE_MASK_1 { 0x02 }; const uint8_t ItemKey::VISIBLE_MASK_2 { 0x04 }; diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index ebf3980489..552e721073 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -65,6 +65,7 @@ public: // Beware that the visibility mask is the oposite of what stored in the key vals. const static uint8_t NUM_VISIBLE_MASK_INDICES; const static uint8_t VISIBLE_MASK_ALL; + const static uint8_t VISIBLE_MASK_NONE; const static uint8_t VISIBLE_MASK_0; const static uint8_t VISIBLE_MASK_1; const static uint8_t VISIBLE_MASK_2; @@ -96,6 +97,21 @@ public: Builder& withDynamic() { _flags.set(DYNAMIC); return (*this); } Builder& withDeformed() { _flags.set(DEFORMED); return (*this); } Builder& withInvisible(uint8_t maskIndex = 0) { _flags.set(INVISIBLE0 + maskIndex); return (*this); } + Builder& withViewVisibilityMask(uint8_t mask) { + if (mask & render::ItemKey::VISIBLE_MASK_0) { + _flags.set(INVISIBLE0); + } + if (mask & render::ItemKey::VISIBLE_MASK_1) { + _flags.set(INVISIBLE1); + } + if (mask & render::ItemKey::VISIBLE_MASK_2) { + _flags.set(INVISIBLE2); + } + if (mask & render::ItemKey::VISIBLE_MASK_3) { + _flags.set(INVISIBLE3); + } + return (*this); + } Builder& withShadowCaster() { _flags.set(SHADOW_CASTER); return (*this); } Builder& withPickable() { _flags.set(PICKABLE); return (*this); } Builder& withLayered() { _flags.set(LAYERED); return (*this); } From 6aa389cad08f42b0e434dd20bbe17338adce9e78 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 19 Jan 2018 09:53:41 -0800 Subject: [PATCH 15/57] trying to now show overlays in mirrors --- interface/src/ui/overlays/OverlaysPayload.cpp | 7 +++++++ libraries/render/src/render/Item.h | 12 +++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp index fceb261503..4bbe21f9a6 100644 --- a/interface/src/ui/overlays/OverlaysPayload.cpp +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -44,6 +44,13 @@ namespace render { } else { builder.withViewSpace(); } + + if (overlay->getVisible()) { + builder.withViewVisibilityMask(render::ItemKey::VISIBLE_MASK_1); // don't draw overlays in mirror + } else { + builder.withViewVisibilityMask(render::ItemKey::VISIBLE_MASK_ALL); + } + return builder.build(); } template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay) { diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 552e721073..9ea8421f1a 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -96,7 +96,17 @@ public: Builder& withViewSpace() { _flags.set(VIEW_SPACE); return (*this); } Builder& withDynamic() { _flags.set(DYNAMIC); return (*this); } Builder& withDeformed() { _flags.set(DEFORMED); return (*this); } - Builder& withInvisible(uint8_t maskIndex = 0) { _flags.set(INVISIBLE0 + maskIndex); return (*this); } + Builder& withInvisible(uint8_t maskIndex = NUM_VISIBLE_MASK_INDICES) { + if (maskIndex == NUM_VISIBLE_MASK_INDICES) { + _flags.set(INVISIBLE0); + _flags.set(INVISIBLE1); + _flags.set(INVISIBLE2); + _flags.set(INVISIBLE3); + } else { + _flags.set(INVISIBLE0 + maskIndex); + } + return (*this); + } Builder& withViewVisibilityMask(uint8_t mask) { if (mask & render::ItemKey::VISIBLE_MASK_0) { _flags.set(INVISIBLE0); From d38d13cbb94d067f12d8fda6d4ff5f7ede15c95c Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sun, 21 Jan 2018 23:47:45 -0800 Subject: [PATCH 16/57] Trying to address the overlays to not be visisble in 2nd camera --- interface/src/ui/overlays/ModelOverlay.cpp | 8 +++++--- interface/src/ui/overlays/OverlaysPayload.cpp | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 79a7df338b..34644735ed 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -87,7 +87,7 @@ void ModelOverlay::update(float deltatime) { if (_visibleDirty) { _visibleDirty = false; // don't show overlays in mirrors - _model->setVisibleInScene(getVisible(), scene, render::ItemKey::VISIBLE_MASK_1); + _model->setVisibleInScene(getVisible(), scene, render::ItemKey::VISIBLE_MASK_0 * getVisible()); } if (_drawInFrontDirty) { _drawInFrontDirty = false; @@ -121,8 +121,10 @@ void ModelOverlay::removeFromScene(Overlay::Pointer overlay, const render::Scene } void ModelOverlay::setVisible(bool visible) { - Overlay::setVisible(visible); - _visibleDirty = true; + if (visible != getVisible()) { + Overlay::setVisible(visible); + _visibleDirty = true; + } } void ModelOverlay::setDrawInFront(bool drawInFront) { diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp index 30743964a4..c071c44d42 100644 --- a/interface/src/ui/overlays/OverlaysPayload.cpp +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -46,9 +46,9 @@ namespace render { } if (overlay->getVisible()) { - builder.withViewVisibilityMask(render::ItemKey::VISIBLE_MASK_1); // don't draw overlays in mirror + builder.withViewVisibilityMask(render::ItemKey::VISIBLE_MASK_0); // don't draw overlays in mirror } else { - builder.withViewVisibilityMask(render::ItemKey::VISIBLE_MASK_ALL); + builder.withViewVisibilityMask(render::ItemKey::VISIBLE_MASK_NONE); } return builder.build(); From 24692f13fdda4e3f6e0b36a6a871a7059592a196 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 23 Jan 2018 14:19:39 +0100 Subject: [PATCH 17/57] Added separate scribe function to evalGlobalLightingAlphaBlendedWithHaze to shorten shader C string --- libraries/render-utils/src/DeferredGlobalLight.slh | 6 ++++++ libraries/render-utils/src/model_normal_map.slf | 2 +- libraries/render-utils/src/model_translucent.slf | 2 +- libraries/render-utils/src/model_translucent_fade.slf | 2 +- libraries/render-utils/src/overlay3D_model_translucent.slf | 2 +- libraries/render-utils/src/simple_transparent_textured.slf | 2 +- 6 files changed, 11 insertions(+), 5 deletions(-) diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index fae645fdbc..51884ccbee 100644 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -203,6 +203,12 @@ vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, fl return color; } +<@endfunc@> + +<@func declareEvalGlobalLightingAlphaBlendedWithHaze()@> + +<$declareLightingAmbient(1, 1, 1)$> +<$declareLightingDirectional()$> vec3 evalGlobalLightingAlphaBlendedWithHaze( mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf index bed85b4b15..b41e226e23 100644 --- a/libraries/render-utils/src/model_normal_map.slf +++ b/libraries/render-utils/src/model_normal_map.slf @@ -47,7 +47,7 @@ void main(void) { <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; vec3 viewNormal; - <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$> + <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$> float scattering = getMaterialScattering(mat); <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>; diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf index 761e702595..67a5651ab8 100644 --- a/libraries/render-utils/src/model_translucent.slf +++ b/libraries/render-utils/src/model_translucent.slf @@ -16,7 +16,7 @@ <@include DeferredGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlended()$> +<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> <@include LightLocal.slh@> diff --git a/libraries/render-utils/src/model_translucent_fade.slf b/libraries/render-utils/src/model_translucent_fade.slf index a2d271653c..316dae7aad 100644 --- a/libraries/render-utils/src/model_translucent_fade.slf +++ b/libraries/render-utils/src/model_translucent_fade.slf @@ -16,7 +16,7 @@ <@include DeferredGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlended()$> +<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> <@include LightLocal.slh@> diff --git a/libraries/render-utils/src/overlay3D_model_translucent.slf b/libraries/render-utils/src/overlay3D_model_translucent.slf index 8dd3a81443..b66c114f4a 100644 --- a/libraries/render-utils/src/overlay3D_model_translucent.slf +++ b/libraries/render-utils/src/overlay3D_model_translucent.slf @@ -11,7 +11,7 @@ // <@include DeferredGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlended()$> +<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> <@include graphics/Material.slh@> diff --git a/libraries/render-utils/src/simple_transparent_textured.slf b/libraries/render-utils/src/simple_transparent_textured.slf index b16b19c8b4..30c420233f 100644 --- a/libraries/render-utils/src/simple_transparent_textured.slf +++ b/libraries/render-utils/src/simple_transparent_textured.slf @@ -16,7 +16,7 @@ <@include DeferredBufferWrite.slh@> <@include DeferredGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlended()$> +<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> <@include gpu/Transform.slh@> <$declareStandardCameraTransform()$> From 55abaf33fb95a5e5bafa7e8db3be3ad7c8d65e3a Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 23 Jan 2018 17:35:01 +0100 Subject: [PATCH 18/57] Added shaders to support normal maps on translucent objects --- .../render-utils/src/RenderPipelines.cpp | 26 +++-- .../src/model_translucent_normal_map.slf | 91 ++++++++++++++++ ...e.slv => model_translucent_normal_map.slv} | 6 +- .../src/model_translucent_normal_map_fade.slf | 101 ++++++++++++++++++ .../src/simple_transparent_textured_fade.slf | 2 +- 5 files changed, 212 insertions(+), 14 deletions(-) create mode 100644 libraries/render-utils/src/model_translucent_normal_map.slf rename libraries/render-utils/src/{model_translucent_fade.slv => model_translucent_normal_map.slv} (88%) create mode 100644 libraries/render-utils/src/model_translucent_normal_map_fade.slf diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 29efaf914a..1718a9b041 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -30,7 +30,7 @@ #include "model_lightmap_fade_vert.h" #include "model_lightmap_normal_map_fade_vert.h" #include "model_translucent_vert.h" -#include "model_translucent_fade_vert.h" +#include "model_translucent_normal_map_vert.h" #include "skin_model_fade_vert.h" #include "skin_model_normal_map_fade_vert.h" @@ -72,6 +72,7 @@ #include "model_lightmap_normal_specular_map_frag.h" #include "model_lightmap_specular_map_frag.h" #include "model_translucent_frag.h" +#include "model_translucent_normal_map_frag.h" #include "model_translucent_unlit_frag.h" #include "model_lightmap_fade_frag.h" @@ -79,6 +80,7 @@ #include "model_lightmap_normal_specular_map_fade_frag.h" #include "model_lightmap_specular_map_fade_frag.h" #include "model_translucent_fade_frag.h" +#include "model_translucent_normal_map_fade_frag.h" #include "model_translucent_unlit_fade_frag.h" #include "overlay3D_vert.h" @@ -191,7 +193,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip auto modelLightmapVertex = gpu::Shader::createVertex(std::string(model_lightmap_vert)); auto modelLightmapNormalMapVertex = gpu::Shader::createVertex(std::string(model_lightmap_normal_map_vert)); auto modelTranslucentVertex = gpu::Shader::createVertex(std::string(model_translucent_vert)); - auto modelTranslucentFadeVertex = gpu::Shader::createVertex(std::string(model_translucent_fade_vert)); + auto modelTranslucentNormalMapVertex = gpu::Shader::createVertex(std::string(model_translucent_normal_map_vert)); auto modelShadowVertex = gpu::Shader::createVertex(std::string(model_shadow_vert)); auto skinModelVertex = gpu::Shader::createVertex(std::string(skin_model_vert)); auto skinModelNormalMapVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_vert)); @@ -220,6 +222,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip auto modelSpecularMapPixel = gpu::Shader::createPixel(std::string(model_specular_map_frag)); auto modelNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_frag)); auto modelTranslucentPixel = gpu::Shader::createPixel(std::string(model_translucent_frag)); + auto modelTranslucentNormalMapPixel = gpu::Shader::createPixel(std::string(model_translucent_normal_map_frag)); auto modelTranslucentUnlitPixel = gpu::Shader::createPixel(std::string(model_translucent_unlit_frag)); auto modelShadowPixel = gpu::Shader::createPixel(std::string(model_shadow_frag)); auto modelLightmapPixel = gpu::Shader::createPixel(std::string(model_lightmap_frag)); @@ -238,6 +241,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip auto modelNormalSpecularMapFadePixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_fade_frag)); auto modelShadowFadePixel = gpu::Shader::createPixel(std::string(model_shadow_fade_frag)); auto modelTranslucentFadePixel = gpu::Shader::createPixel(std::string(model_translucent_fade_frag)); + auto modelTranslucentNormalMapFadePixel = gpu::Shader::createPixel(std::string(model_translucent_normal_map_fade_frag)); auto modelTranslucentUnlitFadePixel = gpu::Shader::createPixel(std::string(model_translucent_unlit_fade_frag)); auto simpleFadePixel = gpu::Shader::createPixel(std::string(simple_textured_fade_frag)); auto simpleUnlitFadePixel = gpu::Shader::createPixel(std::string(simple_textured_unlit_fade_frag)); @@ -307,13 +311,13 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip simpleVertex, simpleTranslucentUnlitPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents(), - modelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); + modelTranslucentNormalMapVertex, modelTranslucentNormalMapPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withTranslucent().withSpecular(), modelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular(), - modelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); + modelTranslucentNormalMapVertex, modelTranslucentNormalMapPixel, nullptr, nullptr); addPipeline( // FIXME: Ignore lightmap for translucents meshpart Key::Builder().withMaterial().withTranslucent().withLightmap(), @@ -321,7 +325,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withTranslucent().withFade(), - modelTranslucentFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); + modelTranslucentVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withTranslucent().withFade(), simpleFadeVertex, simpleTranslucentFadePixel, batchSetter, itemSetter); @@ -333,13 +337,13 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip simpleFadeVertex, simpleTranslucentUnlitFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents().withFade(), - modelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); + modelTranslucentNormalMapVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withTranslucent().withSpecular().withFade(), modelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular().withFade(), - modelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); + modelTranslucentNormalMapVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); addPipeline( // FIXME: Ignore lightmap for translucents meshpart Key::Builder().withMaterial().withTranslucent().withLightmap().withFade(), @@ -405,26 +409,26 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip skinModelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(), - skinModelNormalMapTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); + skinModelNormalMapTranslucentVertex, modelTranslucentNormalMapPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular(), skinModelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular(), - skinModelNormalMapTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); + skinModelNormalMapTranslucentVertex, modelTranslucentNormalMapPixel, nullptr, nullptr); // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withFade(), skinModelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withFade(), - skinModelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); + skinModelNormalMapFadeVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular().withFade(), skinModelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular().withFade(), - skinModelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); + skinModelNormalMapFadeVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); // Depth-only addPipeline( diff --git a/libraries/render-utils/src/model_translucent_normal_map.slf b/libraries/render-utils/src/model_translucent_normal_map.slf new file mode 100644 index 0000000000..759007d93e --- /dev/null +++ b/libraries/render-utils/src/model_translucent_normal_map.slf @@ -0,0 +1,91 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_translucent_normal_map.frag +// fragment shader +// +// Created by Olivier Prat on 23/01/2018. +// Copyright 2018 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 graphics/Material.slh@> + +<@include DeferredGlobalLight.slh@> + +<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> + +<@include LightLocal.slh@> + +<@include gpu/Transform.slh@> +<$declareStandardCameraTransform()$> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> + +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec4 _position; +in vec4 _worldPosition; +in vec3 _normal; +in vec3 _tangent; +in vec3 _color; +in float _alpha; + +out vec4 _fragColor; + +void main(void) { + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> + + float opacity = getMaterialOpacity(mat) * _alpha; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + + float metallic = getMaterialMetallic(mat); + vec3 fresnel = getFresnelF0(metallic, albedo); + + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + vec3 fragPosition = _position.xyz; + vec3 fragNormal; + <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, fragNormal)$> + + TransformCamera cam = getTransformCamera(); + vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0)); + vec3 fragEyeDir = normalize(fragEyeVector); + SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir); + + vec4 localLighting = vec4(0.0); + + <$fetchClusterInfo(_worldPosition)$>; + if (hasLocalLights(numLights, clusterPos, dims)) { + localLighting = evalLocalLighting(cluster, numLights, _worldPosition.xyz, surface, + metallic, fresnel, albedo, 0.0, + vec4(0), vec4(0), opacity); + } + + _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( + cam._viewInverse, + 1.0, + occlusionTex, + fragPosition, + albedo, + fresnel, + metallic, + emissive, + surface, opacity, localLighting.rgb), + opacity); +} diff --git a/libraries/render-utils/src/model_translucent_fade.slv b/libraries/render-utils/src/model_translucent_normal_map.slv similarity index 88% rename from libraries/render-utils/src/model_translucent_fade.slv rename to libraries/render-utils/src/model_translucent_normal_map.slv index 3fb9ad2cb4..db824a3709 100644 --- a/libraries/render-utils/src/model_translucent_fade.slv +++ b/libraries/render-utils/src/model_translucent_normal_map.slv @@ -1,10 +1,10 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> -// model_translucent_fade.slv +// model_translucent_normal_map.slv // vertex shader // -// Created by Olivier Prat on 15/01/18. +// Created by Olivier Prat on 23/01/18. // Copyright 2018 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -25,6 +25,7 @@ out vec2 _texCoord1; out vec4 _position; out vec4 _worldPosition; out vec3 _normal; +out vec3 _tangent; out vec3 _color; void main(void) { @@ -41,4 +42,5 @@ void main(void) { <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> <$transformModelToWorldPos(obj, inPosition, _worldPosition)$> <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> + <$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangent)$> } diff --git a/libraries/render-utils/src/model_translucent_normal_map_fade.slf b/libraries/render-utils/src/model_translucent_normal_map_fade.slf new file mode 100644 index 0000000000..204b5ac56b --- /dev/null +++ b/libraries/render-utils/src/model_translucent_normal_map_fade.slf @@ -0,0 +1,101 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_translucent_normal_map_fade.frag +// fragment shader +// +// Created by Olivier Prat on 23/01/18. +// Copyright 2018 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 graphics/Material.slh@> + +<@include DeferredGlobalLight.slh@> + +<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> + +<@include LightLocal.slh@> + +<@include gpu/Transform.slh@> +<$declareStandardCameraTransform()$> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> + +<@include Fade.slh@> +<$declareFadeFragment()$> + +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec4 _position; +in vec3 _normal; +in vec3 _tangent; +in vec3 _color; +in float _alpha; +in vec4 _worldPosition; + +out vec4 _fragColor; + +void main(void) { + vec3 fadeEmissive; + FadeObjectParams fadeParams; + + <$fetchFadeObjectParams(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> + + float opacity = getMaterialOpacity(mat) * _alpha; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + + float metallic = getMaterialMetallic(mat); + vec3 fresnel = getFresnelF0(metallic, albedo); + + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + vec3 fragPosition = _position.xyz; + // Lighting is done in world space + vec3 fragNormal; + <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, fragNormal)$> + + TransformCamera cam = getTransformCamera(); + vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0)); + vec3 fragEyeDir = normalize(fragEyeVector); + SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir); + + vec4 localLighting = vec4(0.0); + + <$fetchClusterInfo(_worldPosition)$>; + if (hasLocalLights(numLights, clusterPos, dims)) { + localLighting = evalLocalLighting(cluster, numLights, _worldPosition.xyz, surface, + metallic, fresnel, albedo, 0.0, + vec4(0), vec4(0), opacity); + } + + _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( + cam._viewInverse, + 1.0, + occlusionTex, + fragPosition, + albedo, + fresnel, + metallic, + emissive+fadeEmissive, + surface, opacity, localLighting.rgb), + opacity); +} diff --git a/libraries/render-utils/src/simple_transparent_textured_fade.slf b/libraries/render-utils/src/simple_transparent_textured_fade.slf index ad260210a7..a8a5875a4b 100644 --- a/libraries/render-utils/src/simple_transparent_textured_fade.slf +++ b/libraries/render-utils/src/simple_transparent_textured_fade.slf @@ -16,7 +16,7 @@ <@include DeferredBufferWrite.slh@> <@include DeferredGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlended()$> +<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> <@include gpu/Transform.slh@> <$declareStandardCameraTransform()$> From ae6a95ec0d4f9f3aea4c3c54236e1220b14740b4 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 24 Jan 2018 18:07:35 -0800 Subject: [PATCH 19/57] fixing my bugs on vissibility --- interface/src/SecondaryCamera.cpp | 2 +- interface/src/ui/overlays/ModelOverlay.cpp | 2 +- libraries/render-utils/src/Model.h | 2 +- libraries/render/src/render/Item.h | 20 ++++++++++++++++---- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index cad4f7f1b5..9d5b6a44a5 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -205,7 +205,7 @@ public: void SecondaryCameraRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred) { const auto cachedArg = task.addJob("SecondaryCamera"); - const auto items = task.addJob("FetchCullSort", cullFunctor); + const auto items = task.addJob("FetchCullSort", cullFunctor, render::ItemKey::VISIBLE_MASK_1, render::ItemKey::VISIBLE_MASK_1); assert(items.canCast()); if (!isDeferred) { task.addJob("Forward", items); diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 367cb397d1..59d4521307 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -87,7 +87,7 @@ void ModelOverlay::update(float deltatime) { if (_visibleDirty) { _visibleDirty = false; // don't show overlays in mirrors - _model->setVisibleInScene(getVisible(), scene, render::ItemKey::VISIBLE_MASK_0 * getVisible()); + _model->setVisibleInScene(getVisible(), scene, render::ItemKey::VISIBLE_MASK_0); } if (_drawInFrontDirty) { _drawInFrontDirty = false; diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 5f58906e9f..d9845de9ed 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -389,7 +389,7 @@ protected: QUrl _url; bool _isVisible; - uint8_t _viewVisibilityMask { 0 }; + uint8_t _viewVisibilityMask { render::ItemKey::VISIBLE_MASK_ALL }; gpu::Buffers _blendedVertexBuffers; diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 9ea8421f1a..18e626d005 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -96,6 +96,18 @@ public: Builder& withViewSpace() { _flags.set(VIEW_SPACE); return (*this); } Builder& withDynamic() { _flags.set(DYNAMIC); return (*this); } Builder& withDeformed() { _flags.set(DEFORMED); return (*this); } + Builder& withVisible(uint8_t maskIndex = NUM_VISIBLE_MASK_INDICES) { + if (maskIndex == NUM_VISIBLE_MASK_INDICES) { + _flags.reset(INVISIBLE0); + _flags.reset(INVISIBLE1); + _flags.reset(INVISIBLE2); + _flags.reset(INVISIBLE3); + } + else { + _flags.reset(INVISIBLE0 + maskIndex); + } + return (*this); + } Builder& withInvisible(uint8_t maskIndex = NUM_VISIBLE_MASK_INDICES) { if (maskIndex == NUM_VISIBLE_MASK_INDICES) { _flags.set(INVISIBLE0); @@ -109,16 +121,16 @@ public: } Builder& withViewVisibilityMask(uint8_t mask) { if (mask & render::ItemKey::VISIBLE_MASK_0) { - _flags.set(INVISIBLE0); + _flags.reset(INVISIBLE0); } if (mask & render::ItemKey::VISIBLE_MASK_1) { - _flags.set(INVISIBLE1); + _flags.reset(INVISIBLE1); } if (mask & render::ItemKey::VISIBLE_MASK_2) { - _flags.set(INVISIBLE2); + _flags.reset(INVISIBLE2); } if (mask & render::ItemKey::VISIBLE_MASK_3) { - _flags.set(INVISIBLE3); + _flags.reset(INVISIBLE3); } return (*this); } From 2f4e61888fb4636d140b0ece98f46c1e016b581c Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 25 Jan 2018 16:57:35 -0800 Subject: [PATCH 20/57] Making it work maybe --- interface/src/ui/overlays/ModelOverlay.h | 2 +- interface/src/ui/overlays/OverlaysPayload.cpp | 4 ++-- .../src/RenderableModelEntityItem.cpp | 4 ++-- .../render-utils/src/CauterizedModel.cpp | 2 +- .../render-utils/src/MeshPartPayload.cpp | 2 +- libraries/render/src/render/Item.h | 20 ++++++++----------- 6 files changed, 15 insertions(+), 19 deletions(-) diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index a39f762210..a012969621 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -106,7 +106,7 @@ private: bool _jointMappingCompleted { false }; QVector _jointMapping; // domain is index into model-joints, range is index into animation-joints - bool _visibleDirty { false }; + bool _visibleDirty { true }; bool _drawInFrontDirty { false }; bool _drawInHUDDirty { false }; diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp index c071c44d42..937de1a236 100644 --- a/interface/src/ui/overlays/OverlaysPayload.cpp +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -46,9 +46,9 @@ namespace render { } if (overlay->getVisible()) { - builder.withViewVisibilityMask(render::ItemKey::VISIBLE_MASK_0); // don't draw overlays in mirror + builder.withVisibilityMask(render::ItemKey::VISIBLE_MASK_0); // don't draw overlays in mirror } else { - builder.withViewVisibilityMask(render::ItemKey::VISIBLE_MASK_NONE); + builder.withVisibilityMask(render::ItemKey::VISIBLE_MASK_NONE); } return builder.build(); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 0ae7efb652..ee3557346d 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1334,8 +1334,8 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce entity->stopModelOverrideIfNoParent(); uint32_t viewVisiblityMask = _cauterized ? - render::ItemKey::VISIBLE_MASK_0 : // draw in every view except the main one (view zero) - render::ItemKey::VISIBLE_MASK_NONE; // draw in all views + render::ItemKey::VISIBLE_MASK_1 : // draw in every view except the main one (view zero) + render::ItemKey::VISIBLE_MASK_ALL; // draw in all views if (model->isVisible() != _visible || model->getViewVisibilityMask() != viewVisiblityMask) { // FIXME: this seems like it could be optimized if we tracked our last known visible state in diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index f67f5ef358..809be09436 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -247,7 +247,7 @@ void CauterizedModel::updateRenderItems() { data.updateTransformForCauterizedMesh(renderTransform); data.setEnableCauterization(enableCauterization); - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_NONE); + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_ALL); data.setLayer(isLayeredInFront, isLayeredInHUD); data.setShapeKey(invalidatePayloadShapeKey, isWireframe); }); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index da636eed06..451b168465 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -396,7 +396,7 @@ void ModelMeshPartPayload::setKey(bool isVisible, bool isLayered, uint8_t viewVi if (!isVisible) { builder.withInvisible(); } else { - builder.withViewVisibilityMask(viewVisiblityMask); + builder.withVisibilityMask(viewVisiblityMask); } if (isLayered) { diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 18e626d005..97eaefcb53 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -119,18 +119,14 @@ public: } return (*this); } - Builder& withViewVisibilityMask(uint8_t mask) { - if (mask & render::ItemKey::VISIBLE_MASK_0) { - _flags.reset(INVISIBLE0); - } - if (mask & render::ItemKey::VISIBLE_MASK_1) { - _flags.reset(INVISIBLE1); - } - if (mask & render::ItemKey::VISIBLE_MASK_2) { - _flags.reset(INVISIBLE2); - } - if (mask & render::ItemKey::VISIBLE_MASK_3) { - _flags.reset(INVISIBLE3); + Builder& withVisibilityMask(uint8_t mask) { + for (int i = 0; i < ItemKey::NUM_VISIBLE_MASK_INDICES; i++) { + if ((1 << i) & mask) { + withVisible(i); + } + else { + withInvisible(i); + } } return (*this); } From 51dac0437422f119d4457ca24c93b9db9e07fb55 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 26 Jan 2018 02:59:43 -0800 Subject: [PATCH 21/57] Introducing the tag in lieu of the vsisiblity mask --- interface/src/Application.cpp | 2 +- interface/src/SecondaryCamera.cpp | 4 +- interface/src/avatar/MyAvatar.cpp | 8 +- interface/src/ui/overlays/ModelOverlay.cpp | 2 +- interface/src/ui/overlays/OverlaysPayload.cpp | 8 +- .../src/RenderableModelEntityItem.cpp | 4 +- .../render-utils/src/CauterizedModel.cpp | 2 +- .../render-utils/src/MeshPartPayload.cpp | 4 +- libraries/render-utils/src/Model.h | 2 +- .../render-utils/src/RenderShadowTask.cpp | 2 +- libraries/render/src/render/Item.cpp | 20 ++- libraries/render/src/render/Item.h | 138 ++++++++---------- .../src/render/RenderFetchCullSortTask.cpp | 18 +-- .../src/render/RenderFetchCullSortTask.h | 2 +- 14 files changed, 102 insertions(+), 114 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3284ed902e..bdb97bcdd8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2274,7 +2274,7 @@ void Application::initializeGL() { #ifndef Q_OS_ANDROID _renderEngine->addJob("SecondaryCameraJob", cullFunctor, !DISABLE_DEFERRED); #endif - _renderEngine->addJob("RenderMainView", cullFunctor, !DISABLE_DEFERRED, render::ItemKey::VISIBLE_MASK_0, render::ItemKey::VISIBLE_MASK_0); + _renderEngine->addJob("RenderMainView", cullFunctor, !DISABLE_DEFERRED, render::ItemKey::TAG_BITS_0, render::ItemKey::TAG_BITS_0); _renderEngine->load(); _renderEngine->registerScene(_main3DScene); diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index 9d5b6a44a5..1ae1cc3559 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -20,7 +20,7 @@ using RenderArgsPointer = std::shared_ptr; void MainRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred) { task.addJob("RenderShadowTask", cullFunctor); - const auto items = task.addJob("FetchCullSort", cullFunctor, render::ItemKey::VISIBLE_MASK_1, render::ItemKey::VISIBLE_MASK_1); + const auto items = task.addJob("FetchCullSort", cullFunctor, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1); assert(items.canCast()); if (!isDeferred) { task.addJob("Forward", items); @@ -205,7 +205,7 @@ public: void SecondaryCameraRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred) { const auto cachedArg = task.addJob("SecondaryCamera"); - const auto items = task.addJob("FetchCullSort", cullFunctor, render::ItemKey::VISIBLE_MASK_1, render::ItemKey::VISIBLE_MASK_1); + const auto items = task.addJob("FetchCullSort", cullFunctor, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1); assert(items.canCast()); if (!isDeferred) { task.addJob("Forward", items); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index dd51de2079..a63af4435b 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1078,7 +1078,7 @@ void MyAvatar::setEnableDebugDrawIKChains(bool isEnabled) { } void MyAvatar::setEnableMeshVisible(bool isEnabled) { - _skeletonModel->setVisibleInScene(isEnabled, qApp->getMain3DScene(), render::ItemKey::VISIBLE_MASK_NONE); + _skeletonModel->setVisibleInScene(isEnabled, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE); } void MyAvatar::setEnableInverseKinematics(bool isEnabled) { @@ -1428,7 +1428,7 @@ void MyAvatar::clearJointsData() { void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { Avatar::setSkeletonModelURL(skeletonModelURL); - _skeletonModel->setVisibleInScene(true, qApp->getMain3DScene(), render::ItemKey::VISIBLE_MASK_NONE); + _skeletonModel->setVisibleInScene(true, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE); _headBoneSet.clear(); emit skeletonChanged(); @@ -1742,7 +1742,7 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName, void MyAvatar::setVisibleInSceneIfReady(Model* model, const render::ScenePointer& scene, bool visible) { if (model->isActive() && model->isRenderable()) { - model->setVisibleInScene(visible, scene, render::ItemKey::VISIBLE_MASK_NONE); + model->setVisibleInScene(visible, scene, render::ItemKey::TAG_BITS_NONE); } } @@ -1938,7 +1938,7 @@ void MyAvatar::preDisplaySide(RenderArgs* renderArgs) { _attachmentData[i].jointName.compare("HeadTop_End", Qt::CaseInsensitive) == 0 || _attachmentData[i].jointName.compare("Face", Qt::CaseInsensitive) == 0) { _attachmentModels[i]->setVisibleInScene(shouldDrawHead, qApp->getMain3DScene(), - render::ItemKey::VISIBLE_MASK_NONE); + render::ItemKey::TAG_BITS_NONE); } } } diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 59d4521307..015a1a4a3b 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -87,7 +87,7 @@ void ModelOverlay::update(float deltatime) { if (_visibleDirty) { _visibleDirty = false; // don't show overlays in mirrors - _model->setVisibleInScene(getVisible(), scene, render::ItemKey::VISIBLE_MASK_0); + _model->setVisibleInScene(getVisible(), scene, render::ItemKey::TAG_BITS_0); } if (_drawInFrontDirty) { _drawInFrontDirty = false; diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp index 937de1a236..f99ced0021 100644 --- a/interface/src/ui/overlays/OverlaysPayload.cpp +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -45,12 +45,12 @@ namespace render { builder.withViewSpace(); } - if (overlay->getVisible()) { - builder.withVisibilityMask(render::ItemKey::VISIBLE_MASK_0); // don't draw overlays in mirror - } else { - builder.withVisibilityMask(render::ItemKey::VISIBLE_MASK_NONE); + if (!overlay->getVisible()) { + builder.withInvisible(); } + builder.withTagBits(render::ItemKey::TAG_BITS_0); // Only draw overlays in main view + return builder.build(); } template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay) { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index ee3557346d..190864cecf 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1334,8 +1334,8 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce entity->stopModelOverrideIfNoParent(); uint32_t viewVisiblityMask = _cauterized ? - render::ItemKey::VISIBLE_MASK_1 : // draw in every view except the main one (view zero) - render::ItemKey::VISIBLE_MASK_ALL; // draw in all views + render::ItemKey::TAG_BITS_1 : // draw in every view except the main one (view zero) + render::ItemKey::TAG_BITS_ALL; // draw in all views if (model->isVisible() != _visible || model->getViewVisibilityMask() != viewVisiblityMask) { // FIXME: this seems like it could be optimized if we tracked our last known visible state in diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 809be09436..574d3d741c 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -247,7 +247,7 @@ void CauterizedModel::updateRenderItems() { data.updateTransformForCauterizedMesh(renderTransform); data.setEnableCauterization(enableCauterization); - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::VISIBLE_MASK_ALL); + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::TAG_BITS_ALL); data.setLayer(isLayeredInFront, isLayeredInHUD); data.setShapeKey(invalidatePayloadShapeKey, isWireframe); }); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 451b168465..aaec28e210 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -395,10 +395,10 @@ void ModelMeshPartPayload::setKey(bool isVisible, bool isLayered, uint8_t viewVi if (!isVisible) { builder.withInvisible(); - } else { - builder.withVisibilityMask(viewVisiblityMask); } + builder.withTagBits(render::ItemKey::TAG_BITS_ALL); // Draw models in all tags + if (isLayered) { builder.withLayered(); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index d9845de9ed..1fa14f92d6 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -389,7 +389,7 @@ protected: QUrl _url; bool _isVisible; - uint8_t _viewVisibilityMask { render::ItemKey::VISIBLE_MASK_ALL }; + uint8_t _viewVisibilityMask { render::ItemKey::TAG_BITS_ALL }; gpu::Buffers _blendedVertexBuffers; diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 7a7714e1e0..d83dfd73a5 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -264,7 +264,7 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon const auto globalShadow = lightStage->getCurrentKeyShadow(); if (globalShadow && _cascadeIndexgetCascadeCount()) { - output.edit1() = ItemFilter::Builder::visibleWorldItems(0x00, 0x00).withTypeShape().withOpaque().withoutLayered(); + output.edit1() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered(); globalShadow->setKeylightCascadeFrustum(_cascadeIndex, args->getViewFrustum(), SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR); diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index 0e4502a47c..1bf20ab510 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -34,13 +34,19 @@ const int Item::LAYER_3D = 1; const int Item::LAYER_3D_FRONT = 2; const int Item::LAYER_3D_HUD = 3; -const uint8_t ItemKey::NUM_VISIBLE_MASK_INDICES { 4 }; -const uint8_t ItemKey::VISIBLE_MASK_ALL { 0x0F }; -const uint8_t ItemKey::VISIBLE_MASK_NONE { 0x00 }; -const uint8_t ItemKey::VISIBLE_MASK_0 { 0x01 }; -const uint8_t ItemKey::VISIBLE_MASK_1 { 0x02 }; -const uint8_t ItemKey::VISIBLE_MASK_2 { 0x04 }; -const uint8_t ItemKey::VISIBLE_MASK_3 { 0x08 }; +const uint8_t ItemKey::TAG_BITS_ALL{ 0xFF }; +const uint8_t ItemKey::TAG_BITS_NONE{ 0x00 }; +const uint8_t ItemKey::TAG_BITS_0{ 0x01 }; +const uint8_t ItemKey::TAG_BITS_1{ 0x02 }; +const uint8_t ItemKey::TAG_BITS_2{ 0x04 }; +const uint8_t ItemKey::TAG_BITS_3{ 0x08 }; +const uint8_t ItemKey::TAG_BITS_4 { 0x10 }; +const uint8_t ItemKey::TAG_BITS_5{ 0x20 }; +const uint8_t ItemKey::TAG_BITS_6{ 0x40 }; +const uint8_t ItemKey::TAG_BITS_7 { 0x80 }; + +const uint32_t ItemKey::KEY_TAG_BITS_MASK = ((uint32_t) ItemKey::TAG_BITS_ALL) << FIRST_TAG_BIT; + void Item::Status::Value::setScale(float scale) { diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 97eaefcb53..4833bd2f42 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -38,38 +38,61 @@ class Context; // Key is the KEY to filter Items and create specialized lists class ItemKey { public: - enum FlagBit { + // 8 tags are available to organize the items and filter them against as fields of the ItemKey. + // TAG & TAG_BITS are defined from several bits in the Key. + // An Item can be tagged and filtering can rely on the tags to keep or exclude items + // ItemKey are not taged by default + enum Tag : uint8_t { + TAG_0 = 0, // 8 Tags + TAG_1, + TAG_2, + TAG_3, + TAG_4, + TAG_5, + TAG_6, + TAG_7, + + NUM_TAGS, + }; + // Tag bits are derived from the Tag enum + const static uint8_t TAG_BITS_ALL; + const static uint8_t TAG_BITS_NONE; + const static uint8_t TAG_BITS_0; + const static uint8_t TAG_BITS_1; + const static uint8_t TAG_BITS_2; + const static uint8_t TAG_BITS_3; + const static uint8_t TAG_BITS_4; + const static uint8_t TAG_BITS_5; + const static uint8_t TAG_BITS_6; + const static uint8_t TAG_BITS_7; + + enum FlagBit : uint32_t { TYPE_SHAPE = 0, // Item is a Shape TYPE_LIGHT, // Item is a Light TYPE_META, // Item is a Meta: meanning it s used to represent a higher level object, potentially represented by other render items + TRANSLUCENT, // Transparent and not opaque, for some odd reason TRANSPARENCY doesn't work... VIEW_SPACE, // Transformed in view space, and not in world space DYNAMIC, // Dynamic and bound will change unlike static item DEFORMED, // Deformed within bound, not solid - INVISIBLE0, // Visible or not in this mask index? - INVISIBLE1, // Visible or not in this mask index? - INVISIBLE2, // Visible or not in this mask index? - INVISIBLE3, // Visible or not in this mask index? + INVISIBLE, // Visible or not in the scene? SHADOW_CASTER, // Item cast shadows - PICKABLE, // Item can be picked/selected LAYERED, // Item belongs to one of the layers different from the default layer - SMALLER, + FIRST_TAG_BIT, // 8 Tags available to organize the items and filter them against + LAST_TAG_BIT = FIRST_TAG_BIT + NUM_TAGS, + + __SMALLER, // Reserved bit for spatialized item to indicate that it is smaller than expected in the cell in which it belongs (probably because it overlaps over several smaller cells) NUM_FLAGS, // Not a valid flag }; typedef std::bitset Flags; - // VISIBLE MASK is defined from several bits in the Key. - // An Item can be visible in some mask bits and not other allowing for per view rendering - // Beware that the visibility mask is the oposite of what stored in the key vals. - const static uint8_t NUM_VISIBLE_MASK_INDICES; - const static uint8_t VISIBLE_MASK_ALL; - const static uint8_t VISIBLE_MASK_NONE; - const static uint8_t VISIBLE_MASK_0; - const static uint8_t VISIBLE_MASK_1; - const static uint8_t VISIBLE_MASK_2; - const static uint8_t VISIBLE_MASK_3; + // All the bits touching tag bits sets to true + const static uint32_t KEY_TAG_BITS_MASK; + static uint32_t evalTagBitsWithKeyBits(uint8_t tagBits, const uint32_t keyBits) { + return (keyBits & ~KEY_TAG_BITS_MASK) | (((uint32_t)tagBits) << FIRST_TAG_BIT); + } // The key is the Flags Flags _flags; @@ -96,44 +119,14 @@ public: Builder& withViewSpace() { _flags.set(VIEW_SPACE); return (*this); } Builder& withDynamic() { _flags.set(DYNAMIC); return (*this); } Builder& withDeformed() { _flags.set(DEFORMED); return (*this); } - Builder& withVisible(uint8_t maskIndex = NUM_VISIBLE_MASK_INDICES) { - if (maskIndex == NUM_VISIBLE_MASK_INDICES) { - _flags.reset(INVISIBLE0); - _flags.reset(INVISIBLE1); - _flags.reset(INVISIBLE2); - _flags.reset(INVISIBLE3); - } - else { - _flags.reset(INVISIBLE0 + maskIndex); - } - return (*this); - } - Builder& withInvisible(uint8_t maskIndex = NUM_VISIBLE_MASK_INDICES) { - if (maskIndex == NUM_VISIBLE_MASK_INDICES) { - _flags.set(INVISIBLE0); - _flags.set(INVISIBLE1); - _flags.set(INVISIBLE2); - _flags.set(INVISIBLE3); - } else { - _flags.set(INVISIBLE0 + maskIndex); - } - return (*this); - } - Builder& withVisibilityMask(uint8_t mask) { - for (int i = 0; i < ItemKey::NUM_VISIBLE_MASK_INDICES; i++) { - if ((1 << i) & mask) { - withVisible(i); - } - else { - withInvisible(i); - } - } - return (*this); - } + Builder& withInvisible() { _flags.set(INVISIBLE); return (*this); } Builder& withShadowCaster() { _flags.set(SHADOW_CASTER); return (*this); } - Builder& withPickable() { _flags.set(PICKABLE); return (*this); } Builder& withLayered() { _flags.set(LAYERED); return (*this); } + Builder& withTag(Tag tag) { _flags.set(FIRST_TAG_BIT + tag); return (*this); } + // Set ALL the tags in one call using the Tag bits + Builder& withTagBits(uint8_t tagBits) { _flags = evalTagBitsWithKeyBits(tagBits, _flags.to_ulong()); return (*this); } + // Convenient standard keys that we will keep on using all over the place static Builder opaqueShape() { return Builder().withTypeShape(); } static Builder transparentShape() { return Builder().withTypeShape().withTransparent(); } @@ -158,21 +151,20 @@ public: bool isRigid() const { return !_flags[DEFORMED]; } bool isDeformed() const { return _flags[DEFORMED]; } - bool isVisible(uint8_t maskIndex) const { return !_flags[INVISIBLE0 + maskIndex]; } - bool isInvisible(uint8_t maskIndex) const { return _flags[INVISIBLE0 + maskIndex]; } - uint8_t getVisibleMask() const { return (~(_flags.to_ulong() >> INVISIBLE0) & VISIBLE_MASK_ALL);} - bool isVisibleMask(uint8_t mask) const { return getVisibleMask() & mask; } + bool isVisible() const { return !_flags[INVISIBLE]; } + bool isInvisible() const { return _flags[INVISIBLE]; } bool isShadowCaster() const { return _flags[SHADOW_CASTER]; } - bool isPickable() const { return _flags[PICKABLE]; } - bool isLayered() const { return _flags[LAYERED]; } bool isSpatial() const { return !isLayered(); } + bool isTag(Tag tag) const { return _flags[FIRST_TAG_BIT + tag]; } + uint8_t getTagBits() const { return ((_flags.to_ulong() & KEY_TAG_BITS_MASK) >> FIRST_TAG_BIT); } + // Probably not public, flags used by the scene - bool isSmall() const { return _flags[SMALLER]; } - void setSmaller(bool smaller) { (smaller ? _flags.set(SMALLER) : _flags.reset(SMALLER)); } + bool isSmall() const { return _flags[__SMALLER]; } + void setSmaller(bool smaller) { (smaller ? _flags.set(__SMALLER) : _flags.reset(__SMALLER)); } bool operator==(const ItemKey& key) { return (_flags == key._flags); } bool operator!=(const ItemKey& key) { return (_flags != key._flags); } @@ -220,34 +212,24 @@ public: Builder& withRigid() { _value.reset(ItemKey::DEFORMED); _mask.set(ItemKey::DEFORMED); return (*this); } Builder& withDeformed() { _value.set(ItemKey::DEFORMED); _mask.set(ItemKey::DEFORMED); return (*this); } - Builder& withVisible(uint8_t maskIndex) { _value.reset(ItemKey::INVISIBLE0 + maskIndex); _mask.set(ItemKey::INVISIBLE0 + maskIndex); return (*this); } - Builder& withInvisible(uint8_t maskIndex) { _value.set(ItemKey::INVISIBLE0 + maskIndex); _mask.set(ItemKey::INVISIBLE0 + maskIndex); return (*this); } - Builder& withVisibilityMask(uint8_t mask, uint8_t touchBits) { - for (int i = 0; i < ItemKey::NUM_VISIBLE_MASK_INDICES; i++) { - if ((1 << i) & touchBits) { - if ((1 << i) & mask) { - withVisible(i); - } - else { - withInvisible(i); - } - } - } - return (*this); - } + Builder& withVisible() { _value.reset(ItemKey::INVISIBLE); _mask.set(ItemKey::INVISIBLE); return (*this); } + Builder& withInvisible() { _value.set(ItemKey::INVISIBLE); _mask.set(ItemKey::INVISIBLE); return (*this); } Builder& withNoShadowCaster() { _value.reset(ItemKey::SHADOW_CASTER); _mask.set(ItemKey::SHADOW_CASTER); return (*this); } Builder& withShadowCaster() { _value.set(ItemKey::SHADOW_CASTER); _mask.set(ItemKey::SHADOW_CASTER); return (*this); } - Builder& withPickable() { _value.set(ItemKey::PICKABLE); _mask.set(ItemKey::PICKABLE); return (*this); } - Builder& withoutLayered() { _value.reset(ItemKey::LAYERED); _mask.set(ItemKey::LAYERED); return (*this); } Builder& withLayered() { _value.set(ItemKey::LAYERED); _mask.set(ItemKey::LAYERED); return (*this); } + Builder& withoutTag(ItemKey::Tag tagIndex) { _value.reset(ItemKey::FIRST_TAG_BIT + tagIndex); _mask.set(ItemKey::FIRST_TAG_BIT + tagIndex); return (*this); } + Builder& withTag(ItemKey::Tag tagIndex) { _value.set(ItemKey::FIRST_TAG_BIT + tagIndex); _mask.set(ItemKey::FIRST_TAG_BIT + tagIndex); return (*this); } + // Set ALL the tags in one call using the Tag bits and the Tag bits touched + Builder& withTagBits(uint8_t tagBits, uint8_t tagMask) { _value = ItemKey::evalTagBitsWithKeyBits(tagBits, _value.to_ulong()); _mask = ItemKey::evalTagBitsWithKeyBits(tagMask, _mask.to_ulong()); return (*this); } + Builder& withNothing() { _value.reset(); _mask.reset(); return (*this); } // Convenient standard keys that we will keep on using all over the place - static Builder visibleWorldItems(uint8_t visibilityMask, uint8_t visibilityMaskTouched) { return Builder().withVisibilityMask(visibilityMask, visibilityMaskTouched).withWorldSpace(); } + static Builder visibleWorldItems() { return Builder().withVisible().withWorldSpace(); } static Builder opaqueShape() { return Builder().withTypeShape().withOpaque().withWorldSpace(); } static Builder transparentShape() { return Builder().withTypeShape().withTransparent().withWorldSpace(); } static Builder light() { return Builder().withTypeLight(); } diff --git a/libraries/render/src/render/RenderFetchCullSortTask.cpp b/libraries/render/src/render/RenderFetchCullSortTask.cpp index b4e1a618dc..a402c3bc9d 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.cpp +++ b/libraries/render/src/render/RenderFetchCullSortTask.cpp @@ -17,12 +17,12 @@ using namespace render; -void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varying& output, CullFunctor cullFunctor, uint8_t visibilityMask, uint8_t visibilityMaskTouched) { +void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varying& output, CullFunctor cullFunctor, uint8_t tagBits, uint8_t tagMask) { cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&){ return true; }; // CPU jobs: // Fetch and cull the items from the scene - const ItemFilter filter = ItemFilter::Builder::visibleWorldItems(visibilityMask, visibilityMaskTouched).withoutLayered(); + const ItemFilter filter = ItemFilter::Builder::visibleWorldItems().withoutLayered().withTagBits(tagBits, tagMask); const auto spatialFilter = render::Varying(filter); const auto spatialSelection = task.addJob("FetchSceneSelection", spatialFilter); const auto cullInputs = CullSpatialSelection::Inputs(spatialSelection, spatialFilter).asVarying(); @@ -40,15 +40,15 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin const int META_BUCKET = 3; const int BACKGROUND_BUCKET = 2; MultiFilterItems::ItemFilterArray spatialFilters = { { - ItemFilter::Builder::opaqueShape().withVisibilityMask(visibilityMask, visibilityMaskTouched), - ItemFilter::Builder::transparentShape().withVisibilityMask(visibilityMask, visibilityMaskTouched), - ItemFilter::Builder::light().withVisibilityMask(visibilityMask, visibilityMaskTouched), - ItemFilter::Builder::meta().withVisibilityMask(visibilityMask, visibilityMaskTouched) + ItemFilter::Builder::opaqueShape().withVisible().withTagBits(tagBits, tagMask), + ItemFilter::Builder::transparentShape().withVisible().withTagBits(tagBits, tagMask), + ItemFilter::Builder::light().withVisible().withTagBits(tagBits, tagMask), + ItemFilter::Builder::meta().withVisible().withTagBits(tagBits, tagMask) } }; MultiFilterItems::ItemFilterArray nonspatialFilters = { { - ItemFilter::Builder::opaqueShape().withVisibilityMask(visibilityMask, visibilityMaskTouched), - ItemFilter::Builder::transparentShape().withVisibilityMask(visibilityMask, visibilityMaskTouched), - ItemFilter::Builder::background().withVisibilityMask(visibilityMask, visibilityMaskTouched) + ItemFilter::Builder::opaqueShape().withVisible().withTagBits(tagBits, tagMask), + ItemFilter::Builder::transparentShape().withVisible().withTagBits(tagBits, tagMask), + ItemFilter::Builder::background().withVisible().withTagBits(tagBits, tagMask) } }; const auto filteredSpatialBuckets = task.addJob>("FilterSceneSelection", culledSpatialSelection, spatialFilters) diff --git a/libraries/render/src/render/RenderFetchCullSortTask.h b/libraries/render/src/render/RenderFetchCullSortTask.h index 9aa235b3fb..8c9f2e7304 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.h +++ b/libraries/render/src/render/RenderFetchCullSortTask.h @@ -36,7 +36,7 @@ public: RenderFetchCullSortTask() {} - void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, uint8_t visibilityMask = 0xFF, uint8_t visibilityMaskTouched = 0x00); + void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, uint8_t tagBits = 0x00, uint8_t tagMask = 0x00); }; #endif // hifi_RenderFetchCullSortTask_h From 8dfa3aace3c25fe0d966c9931a856309281518e8 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 26 Jan 2018 17:34:37 -0800 Subject: [PATCH 22/57] cleaning en route --- interface/src/Application_render.cpp | 2 +- interface/src/SecondaryCamera.cpp | 1 + .../src/avatars-renderer/Avatar.cpp | 2 +- .../src/RenderableEntityItem.cpp | 4 +- .../src/RenderableModelEntityItem.cpp | 11 ++--- .../RenderableParticleEffectEntityItem.cpp | 4 +- .../src/RenderablePolyLineEntityItem.cpp | 2 +- .../src/RenderableZoneEntityItem.cpp | 2 +- libraries/render-utils/src/AnimDebugDraw.cpp | 2 +- .../render-utils/src/CauterizedModel.cpp | 2 +- libraries/render-utils/src/LightPayload.cpp | 9 ++++- .../render-utils/src/MeshPartPayload.cpp | 26 ++++++++---- libraries/render-utils/src/MeshPartPayload.h | 9 +++-- libraries/render-utils/src/Model.cpp | 40 +++++++++---------- libraries/render-utils/src/Model.h | 6 +-- .../render-utils/src/RenderShadowTask.cpp | 4 +- libraries/render-utils/src/RenderShadowTask.h | 2 +- libraries/render-utils/src/RenderViewTask.cpp | 4 +- libraries/render-utils/src/RenderViewTask.h | 2 +- .../src/render/RenderFetchCullSortTask.cpp | 14 +++---- 20 files changed, 85 insertions(+), 63 deletions(-) diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp index 1231e5834b..e1f198eed2 100644 --- a/interface/src/Application_render.cpp +++ b/interface/src/Application_render.cpp @@ -178,7 +178,7 @@ public: render::ItemID WorldBoxRenderData::_item{ render::Item::INVALID_ITEM_ID }; namespace render { - template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape(); } + template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); } template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); } template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) { if (Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) { diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index 1ae1cc3559..748f1595db 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -19,6 +19,7 @@ using RenderArgsPointer = std::shared_ptr; void MainRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred) { + task.addJob("RenderShadowTask", cullFunctor); const auto items = task.addJob("FetchCullSort", cullFunctor, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1); assert(items.canCast()); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 500a24763d..86635cd3bf 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -50,7 +50,7 @@ const glm::vec3 HAND_TO_PALM_OFFSET(0.0f, 0.12f, 0.08f); namespace render { template <> const ItemKey payloadGetKey(const AvatarSharedPointer& avatar) { - return ItemKey::Builder::opaqueShape().withTypeMeta(); + return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); } template <> const Item::Bound payloadGetBound(const AvatarSharedPointer& avatar) { return static_pointer_cast(avatar)->getBounds(); diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 0988c696dd..aca2f4d35b 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -159,10 +159,10 @@ Item::Bound EntityRenderer::getBound() { ItemKey EntityRenderer::getKey() { if (isTransparent()) { - return ItemKey::Builder::transparentShape().withTypeMeta(); + return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1); } - return ItemKey::Builder::opaqueShape().withTypeMeta(); + return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1); } uint32_t EntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 190864cecf..87767db4f4 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1014,9 +1014,9 @@ ModelEntityRenderer::ModelEntityRenderer(const EntityItemPointer& entity) : Pare void ModelEntityRenderer::setKey(bool didVisualGeometryRequestSucceed) { if (didVisualGeometryRequestSucceed) { - _itemKey = ItemKey::Builder().withTypeMeta(); + _itemKey = ItemKey::Builder().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1); } else { - _itemKey = ItemKey::Builder().withTypeMeta().withTypeShape(); + _itemKey = ItemKey::Builder().withTypeMeta().withTypeShape().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1); } } @@ -1333,15 +1333,16 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce entity->updateModelBounds(); entity->stopModelOverrideIfNoParent(); - uint32_t viewVisiblityMask = _cauterized ? + // Default behavior for model is to not be visible in main view if cauterized (aka parented to the avatar's neck joint) + uint32_t viewTaskBits = _cauterized ? render::ItemKey::TAG_BITS_1 : // draw in every view except the main one (view zero) render::ItemKey::TAG_BITS_ALL; // draw in all views - if (model->isVisible() != _visible || model->getViewVisibilityMask() != viewVisiblityMask) { + if (model->isVisible() != _visible || model->getViewTagBits() != viewTaskBits) { // FIXME: this seems like it could be optimized if we tracked our last known visible state in // the renderable item. As it stands now the model checks it's visible/invisible state // so most of the time we don't do anything in this function. - model->setVisibleInScene(_visible, scene, viewVisiblityMask); + model->setVisibleInScene(_visible, scene, viewTaskBits); } // TODO? early exit here when not visible? diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 2059487426..af95878213 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -147,9 +147,9 @@ void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEn ItemKey ParticleEffectEntityRenderer::getKey() { if (_visible) { - return ItemKey::Builder::transparentShape(); + return ItemKey::Builder::transparentShape().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1); } else { - return ItemKey::Builder().withInvisible().build(); + return ItemKey::Builder().withInvisible().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1).build(); } } diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 4d223669b4..42110170a0 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -112,7 +112,7 @@ PolyLineEntityRenderer::PolyLineEntityRenderer(const EntityItemPointer& entity) } ItemKey PolyLineEntityRenderer::getKey() { - return ItemKey::Builder::transparentShape().withTypeMeta(); + return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1); } ShapeKey PolyLineEntityRenderer::getShapeKey() { diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index b43944f26a..04f07c5bd3 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -269,7 +269,7 @@ void ZoneEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe ItemKey ZoneEntityRenderer::getKey() { - return ItemKey::Builder().withTypeMeta().build(); + return ItemKey::Builder().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1).build(); } bool ZoneEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const { diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp index c22e99cbbc..4b5b06ab0b 100644 --- a/libraries/render-utils/src/AnimDebugDraw.cpp +++ b/libraries/render-utils/src/AnimDebugDraw.cpp @@ -67,7 +67,7 @@ public: typedef render::Payload AnimDebugDrawPayload; namespace render { - template <> const ItemKey payloadGetKey(const AnimDebugDrawData::Pointer& data) { return (data->_isVisible ? ItemKey::Builder::opaqueShape() : ItemKey::Builder::opaqueShape().withInvisible()); } + template <> const ItemKey payloadGetKey(const AnimDebugDrawData::Pointer& data) { return (data->_isVisible ? ItemKey::Builder::opaqueShape() : ItemKey::Builder::opaqueShape().withInvisible()).withTagBits(ItemKey::TAG_BITS_ALL); } template <> const Item::Bound payloadGetBound(const AnimDebugDrawData::Pointer& data) { return data->_bound; } template <> void payloadRender(const AnimDebugDrawData::Pointer& data, RenderArgs* args) { data->render(args); diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 574d3d741c..e30c72e9d4 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -247,7 +247,7 @@ void CauterizedModel::updateRenderItems() { data.updateTransformForCauterizedMesh(renderTransform); data.setEnableCauterization(enableCauterization); - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::TAG_BITS_ALL); + data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::TAG_BITS_ALL); data.setLayer(isLayeredInFront, isLayeredInHUD); data.setShapeKey(invalidatePayloadShapeKey, isWireframe); }); diff --git a/libraries/render-utils/src/LightPayload.cpp b/libraries/render-utils/src/LightPayload.cpp index 09334faa13..f1eef19498 100644 --- a/libraries/render-utils/src/LightPayload.cpp +++ b/libraries/render-utils/src/LightPayload.cpp @@ -18,9 +18,13 @@ namespace render { template <> const ItemKey payloadGetKey(const LightPayload::Pointer& payload) { ItemKey::Builder builder; builder.withTypeLight(); - if (!payload || !payload->isVisible()) { - builder.withInvisible(); + builder.withTagBits(ItemKey::TAG_BITS_ALL); + if (!payload) { + if (!payload->isVisible()) { + builder.withInvisible(); + } } + return builder.build(); } @@ -87,6 +91,7 @@ namespace render { template <> const ItemKey payloadGetKey(const KeyLightPayload::Pointer& payload) { ItemKey::Builder builder; builder.withTypeLight(); + builder.withTagBits(ItemKey::TAG_BITS_ALL); if (!payload || !payload->isVisible()) { builder.withInvisible(); } diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index aaec28e210..9655b60a78 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -71,10 +71,20 @@ void MeshPartPayload::updateMaterial(graphics::MaterialPointer drawMaterial) { _drawMaterial = drawMaterial; } -ItemKey MeshPartPayload::getKey() const { +void MeshPartPayload::updateKey(bool isVisible, bool isLayered, uint8_t tagBits) { ItemKey::Builder builder; builder.withTypeShape(); + if (!isVisible) { + builder.withInvisible(); + } + + builder.withTagBits(tagBits); + + if (isLayered) { + builder.withLayered(); + } + if (_drawMaterial) { auto matKey = _drawMaterial->getKey(); if (matKey.isTranslucent()) { @@ -82,7 +92,11 @@ ItemKey MeshPartPayload::getKey() const { } } - return builder.build(); + _itemKey = builder.build(); +} + +ItemKey MeshPartPayload::getKey() const { + return _itemKey; } Item::Bound MeshPartPayload::getBound() const { @@ -389,7 +403,7 @@ void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& render _worldBound.transform(boundTransform); } -void ModelMeshPartPayload::setKey(bool isVisible, bool isLayered, uint8_t viewVisiblityMask) { +void ModelMeshPartPayload::updateKey(bool isVisible, bool isLayered, uint8_t tagBits) { ItemKey::Builder builder; builder.withTypeShape(); @@ -397,7 +411,7 @@ void ModelMeshPartPayload::setKey(bool isVisible, bool isLayered, uint8_t viewVi builder.withInvisible(); } - builder.withTagBits(render::ItemKey::TAG_BITS_ALL); // Draw models in all tags + builder.withTagBits(tagBits); if (isLayered) { builder.withLayered(); @@ -417,10 +431,6 @@ void ModelMeshPartPayload::setKey(bool isVisible, bool isLayered, uint8_t viewVi _itemKey = builder.build(); } -ItemKey ModelMeshPartPayload::getKey() const { - return _itemKey; -} - void ModelMeshPartPayload::setLayer(bool isLayeredInFront, bool isLayeredInHUD) { if (isLayeredInFront) { _layer = Item::LAYER_3D_FRONT; diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index cf64879b3c..21f9dc2e68 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -33,6 +33,8 @@ public: typedef render::Payload Payload; typedef Payload::DataPointer Pointer; + virtual void updateKey(bool isVisible, bool isLayered, uint8_t tagBits); + virtual void updateMeshPart(const std::shared_ptr& drawMesh, int partIndex); virtual void notifyLocationChanged() {} @@ -70,6 +72,9 @@ public: size_t getMaterialTextureSize() { return _drawMaterial ? _drawMaterial->getTextureSize() : 0; } int getMaterialTextureCount() { return _drawMaterial ? _drawMaterial->getTextureCount() : 0; } bool hasTextureInfo() const { return _drawMaterial ? _drawMaterial->hasTextureInfo() : false; } + +protected: + render::ItemKey _itemKey{ render::ItemKey::Builder::opaqueShape().build() }; }; namespace render { @@ -94,16 +99,15 @@ public: using TransformType = glm::mat4; #endif + void updateKey(bool isVisible, bool isLayered, uint8_t tagBits) override; void updateClusterBuffer(const std::vector& clusterTransforms); void updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform); // Render Item interface - render::ItemKey getKey() const override; int getLayer() const; render::ShapeKey getShapeKey() const override; // shape interface void render(RenderArgs* args) override; - void setKey(bool isVisible, bool isLayered, uint8_t viewVisiblityMask); void setLayer(bool isLayeredInFront, bool isLayeredInHUD); void setShapeKey(bool invalidateShapeKey, bool isWireframe); @@ -126,7 +130,6 @@ private: void initCache(const ModelPointer& model); gpu::BufferPointer _blendedVertexBuffer; - render::ItemKey _itemKey { render::ItemKey::Builder::opaqueShape().build() }; render::ShapeKey _shapeKey { render::ShapeKey::Builder::invalid() }; int _layer { render::Item::LAYER_3D }; }; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 4103dffefc..56bed15376 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -268,7 +268,7 @@ void Model::updateRenderItems() { bool isWireframe = self->isWireframe(); bool isVisible = self->isVisible(); - uint8_t viewVisibilityMask = self->getViewVisibilityMask(); + uint8_t viewTagBits = self->getViewTagBits(); bool isLayeredInFront = self->isLayeredInFront(); bool isLayeredInHUD = self->isLayeredInHUD(); @@ -283,7 +283,7 @@ void Model::updateRenderItems() { transaction.updateItem(itemID, [modelTransform, clusterTransforms, invalidatePayloadShapeKey, isWireframe, isVisible, - viewVisibilityMask, isLayeredInFront, + viewTagBits, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { data.updateClusterBuffer(clusterTransforms); @@ -300,7 +300,7 @@ void Model::updateRenderItems() { } data.updateTransformForSkinnedMesh(renderTransform, modelTransform); - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, viewVisibilityMask); + data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits); data.setLayer(isLayeredInFront, isLayeredInHUD); data.setShapeKey(invalidatePayloadShapeKey, isWireframe); }); @@ -662,25 +662,25 @@ void Model::calculateTriangleSets() { } } -void Model::setVisibleInScene(bool isVisible, const render::ScenePointer& scene, uint8_t viewVisibilityMask) { - if (_isVisible != isVisible || _viewVisibilityMask != viewVisibilityMask) { +void Model::setVisibleInScene(bool isVisible, const render::ScenePointer& scene, uint8_t viewTagBits) { + if (_isVisible != isVisible || _viewTagBits != viewTagBits) { _isVisible = isVisible; - _viewVisibilityMask = viewVisibilityMask; + _viewTagBits = viewTagBits; bool isLayeredInFront = _isLayeredInFront; bool isLayeredInHUD = _isLayeredInHUD; render::Transaction transaction; foreach (auto item, _modelMeshRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, viewVisibilityMask, isLayeredInFront, + transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, viewVisibilityMask); + data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits); }); } foreach(auto item, _collisionRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, viewVisibilityMask, isLayeredInFront, + transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, viewVisibilityMask); + data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits); }); } scene->enqueueTransaction(transaction); @@ -693,21 +693,21 @@ void Model::setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& _isLayeredInFront = isLayeredInFront; bool isVisible = _isVisible; - uint8_t viewVisibilityMask = _viewVisibilityMask; + uint8_t viewTagBits = _viewTagBits; bool isLayeredInHUD = _isLayeredInHUD; render::Transaction transaction; foreach(auto item, _modelMeshRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, viewVisibilityMask, isLayeredInFront, + transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, viewVisibilityMask); + data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits); data.setLayer(isLayeredInFront, isLayeredInHUD); }); } foreach(auto item, _collisionRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, viewVisibilityMask, isLayeredInFront, + transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, viewVisibilityMask); + data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits); data.setLayer(isLayeredInFront, isLayeredInHUD); }); } @@ -720,21 +720,21 @@ void Model::setLayeredInHUD(bool isLayeredInHUD, const render::ScenePointer& sce _isLayeredInHUD = isLayeredInHUD; bool isVisible = _isVisible; - uint8_t viewVisibilityMask = _viewVisibilityMask; + uint8_t viewTagBits = _viewTagBits; bool isLayeredInFront = _isLayeredInFront; render::Transaction transaction; foreach(auto item, _modelMeshRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, viewVisibilityMask, isLayeredInFront, + transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, viewVisibilityMask); + data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits); data.setLayer(isLayeredInFront, isLayeredInHUD); }); } foreach(auto item, _collisionRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, viewVisibilityMask, isLayeredInFront, + transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.setKey(isVisible, isLayeredInFront || isLayeredInHUD, viewVisibilityMask); + data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits); data.setLayer(isLayeredInFront, isLayeredInHUD); }); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 1fa14f92d6..72527e1fde 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -86,7 +86,7 @@ public: const QUrl& getURL() const { return _url; } // new Scene/Engine rendering support - void setVisibleInScene(bool isVisible, const render::ScenePointer& scene, uint8_t viewVisiblityMask); + void setVisibleInScene(bool isVisible, const render::ScenePointer& scene, uint8_t viewTagBits); void setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& scene); void setLayeredInHUD(bool isLayeredInHUD, const render::ScenePointer& scene); bool needsFixupInScene() const; @@ -104,7 +104,7 @@ public: bool isRenderable() const; bool isVisible() const { return _isVisible; } - uint8_t getViewVisibilityMask() const { return _viewVisibilityMask; } + uint8_t getViewTagBits() const { return _viewTagBits; } bool isLayeredInFront() const { return _isLayeredInFront; } bool isLayeredInHUD() const { return _isLayeredInHUD; } @@ -389,7 +389,7 @@ protected: QUrl _url; bool _isVisible; - uint8_t _viewVisibilityMask { render::ItemKey::TAG_BITS_ALL }; + uint8_t _viewTagBits{ render::ItemKey::TAG_BITS_ALL }; gpu::Buffers _blendedVertexBuffers; diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index d83dfd73a5..20af1278ac 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -200,7 +200,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con }); } -void RenderShadowTask::build(JobModel& task, const render::Varying& input, render::Varying& output, CullFunctor cullFunctor) { +void RenderShadowTask::build(JobModel& task, const render::Varying& input, render::Varying& output, CullFunctor cullFunctor, uint8_t tagBits, uint8_t tagMask) { cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&) { return true; }; // Prepare the ShapePipeline @@ -259,6 +259,8 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon // Cache old render args RenderArgs* args = renderContext->args; + // const auto& filterMask = inputs; + output.edit0() = args->_renderMode; output.edit2() = args->_sizeScale; diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index d8d4c624e7..2bc325cc81 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -48,7 +48,7 @@ public: using JobModel = render::Task::Model; RenderShadowTask() {} - void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor shouldRender); + void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor shouldRender, uint8_t tagBits = 0x00, uint8_t tagMask = 0x00); void configure(const Config& configuration); }; diff --git a/libraries/render-utils/src/RenderViewTask.cpp b/libraries/render-utils/src/RenderViewTask.cpp index 83868e1443..42d3044b1b 100644 --- a/libraries/render-utils/src/RenderViewTask.cpp +++ b/libraries/render-utils/src/RenderViewTask.cpp @@ -14,7 +14,7 @@ #include "RenderDeferredTask.h" #include "RenderForwardTask.h" -void RenderViewTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, bool isDeferred, uint8_t visibilityMask, uint8_t visibilityMaskTouched) { +void RenderViewTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, bool isDeferred, uint8_t tagBits, uint8_t tagMask) { // auto items = input.get(); // Shadows use an orthographic projection because they are linked to sunlights @@ -30,7 +30,7 @@ void RenderViewTask::build(JobModel& task, const render::Varying& input, render: return true; }); - const auto items = task.addJob("FetchCullSort", cullFunctor, visibilityMask, visibilityMaskTouched); + const auto items = task.addJob("FetchCullSort", cullFunctor, tagBits, tagMask); assert(items.canCast()); if (isDeferred) { diff --git a/libraries/render-utils/src/RenderViewTask.h b/libraries/render-utils/src/RenderViewTask.h index faace7349e..5da3d18474 100644 --- a/libraries/render-utils/src/RenderViewTask.h +++ b/libraries/render-utils/src/RenderViewTask.h @@ -23,7 +23,7 @@ public: RenderViewTask() {} - void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred, uint8_t visibilityMask = 0xFF, uint8_t visibilityMaskTouched = 0x00); + void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred, uint8_t tagBits = 0x00, uint8_t tagMask = 0x00); }; diff --git a/libraries/render/src/render/RenderFetchCullSortTask.cpp b/libraries/render/src/render/RenderFetchCullSortTask.cpp index a402c3bc9d..bb6bd462f6 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.cpp +++ b/libraries/render/src/render/RenderFetchCullSortTask.cpp @@ -40,15 +40,15 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin const int META_BUCKET = 3; const int BACKGROUND_BUCKET = 2; MultiFilterItems::ItemFilterArray spatialFilters = { { - ItemFilter::Builder::opaqueShape().withVisible().withTagBits(tagBits, tagMask), - ItemFilter::Builder::transparentShape().withVisible().withTagBits(tagBits, tagMask), - ItemFilter::Builder::light().withVisible().withTagBits(tagBits, tagMask), - ItemFilter::Builder::meta().withVisible().withTagBits(tagBits, tagMask) + ItemFilter::Builder::opaqueShape(), + ItemFilter::Builder::transparentShape(), + ItemFilter::Builder::light(), + ItemFilter::Builder::meta() } }; MultiFilterItems::ItemFilterArray nonspatialFilters = { { - ItemFilter::Builder::opaqueShape().withVisible().withTagBits(tagBits, tagMask), - ItemFilter::Builder::transparentShape().withVisible().withTagBits(tagBits, tagMask), - ItemFilter::Builder::background().withVisible().withTagBits(tagBits, tagMask) + ItemFilter::Builder::opaqueShape(), + ItemFilter::Builder::transparentShape(), + ItemFilter::Builder::background() } }; const auto filteredSpatialBuckets = task.addJob>("FilterSceneSelection", culledSpatialSelection, spatialFilters) From 4cbfef55efc3c0861612eebbc70e444069b659a7 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 29 Jan 2018 10:33:16 +0100 Subject: [PATCH 23/57] Merged with master. Had to add back shaders and code --- .../render-utils/src/DeferredGlobalLight.slh | 7 ++ .../render-utils/src/RenderPipelines.cpp | 22 ++-- .../render-utils/src/model_translucent.slf | 2 +- .../src/model_translucent_fade.slf | 2 +- .../src/model_translucent_normal_map.slf | 91 ++++++++++++++++ .../src/model_translucent_normal_map.slv | 46 ++++++++ .../src/model_translucent_normal_map_fade.slf | 101 ++++++++++++++++++ .../src/overlay3D_model_translucent.slf | 2 +- .../src/simple_transparent_textured.slf | 2 +- .../src/simple_transparent_textured_fade.slf | 2 +- 10 files changed, 264 insertions(+), 13 deletions(-) create mode 100644 libraries/render-utils/src/model_translucent_normal_map.slf create mode 100644 libraries/render-utils/src/model_translucent_normal_map.slv create mode 100644 libraries/render-utils/src/model_translucent_normal_map_fade.slf diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index fae645fdbc..faf8641926 100644 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -204,6 +204,13 @@ vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, fl return color; } +<@endfunc@> + +<@func declareEvalGlobalLightingAlphaBlendedWithHaze()@> + +<$declareLightingAmbient(1, 1, 1)$> +<$declareLightingDirectional()$> + vec3 evalGlobalLightingAlphaBlendedWithHaze( mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 1c828c3d06..900eacec12 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -31,6 +31,7 @@ #include "model_lightmap_normal_map_fade_vert.h" #include "model_translucent_vert.h" #include "model_translucent_fade_vert.h" +#include "model_translucent_normal_map_vert.h" #include "skin_model_fade_vert.h" #include "skin_model_normal_map_fade_vert.h" @@ -73,12 +74,14 @@ #include "model_lightmap_specular_map_frag.h" #include "model_translucent_frag.h" #include "model_translucent_unlit_frag.h" +#include "model_translucent_normal_map_frag.h" #include "model_lightmap_fade_frag.h" #include "model_lightmap_normal_map_fade_frag.h" #include "model_lightmap_normal_specular_map_fade_frag.h" #include "model_lightmap_specular_map_fade_frag.h" #include "model_translucent_fade_frag.h" +#include "model_translucent_normal_map_fade_frag.h" #include "model_translucent_unlit_fade_frag.h" #include "overlay3D_vert.h" @@ -191,6 +194,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip auto modelLightmapVertex = gpu::Shader::createVertex(std::string(model_lightmap_vert)); auto modelLightmapNormalMapVertex = gpu::Shader::createVertex(std::string(model_lightmap_normal_map_vert)); auto modelTranslucentVertex = gpu::Shader::createVertex(std::string(model_translucent_vert)); + auto modelTranslucentNormalMapVertex = gpu::Shader::createVertex(std::string(model_translucent_normal_map_vert)); auto modelTranslucentFadeVertex = gpu::Shader::createVertex(std::string(model_translucent_fade_vert)); auto modelShadowVertex = gpu::Shader::createVertex(std::string(model_shadow_vert)); auto skinModelVertex = gpu::Shader::createVertex(std::string(skin_model_vert)); @@ -220,6 +224,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip auto modelSpecularMapPixel = gpu::Shader::createPixel(std::string(model_specular_map_frag)); auto modelNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_frag)); auto modelTranslucentPixel = gpu::Shader::createPixel(std::string(model_translucent_frag)); + auto modelTranslucentNormalMapPixel = gpu::Shader::createPixel(std::string(model_translucent_normal_map_frag)); auto modelTranslucentUnlitPixel = gpu::Shader::createPixel(std::string(model_translucent_unlit_frag)); auto modelShadowPixel = gpu::Shader::createPixel(std::string(model_shadow_frag)); auto modelLightmapPixel = gpu::Shader::createPixel(std::string(model_lightmap_frag)); @@ -238,6 +243,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip auto modelNormalSpecularMapFadePixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_fade_frag)); auto modelShadowFadePixel = gpu::Shader::createPixel(std::string(model_shadow_fade_frag)); auto modelTranslucentFadePixel = gpu::Shader::createPixel(std::string(model_translucent_fade_frag)); + auto modelTranslucentNormalMapFadePixel = gpu::Shader::createPixel(std::string(model_translucent_normal_map_fade_frag)); auto modelTranslucentUnlitFadePixel = gpu::Shader::createPixel(std::string(model_translucent_unlit_fade_frag)); auto simpleFadePixel = gpu::Shader::createPixel(std::string(simple_textured_fade_frag)); auto simpleUnlitFadePixel = gpu::Shader::createPixel(std::string(simple_textured_unlit_fade_frag)); @@ -307,13 +313,13 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip simpleVertex, simpleTranslucentUnlitPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents(), - modelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); + modelTranslucentNormalMapVertex, modelTranslucentNormalMapPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withTranslucent().withSpecular(), modelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular(), - modelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); + modelTranslucentNormalMapVertex, modelTranslucentNormalMapPixel, nullptr, nullptr); addPipeline( // FIXME: Ignore lightmap for translucents meshpart Key::Builder().withMaterial().withTranslucent().withLightmap(), @@ -333,13 +339,13 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip simpleFadeVertex, simpleTranslucentUnlitFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents().withFade(), - modelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); + modelTranslucentNormalMapVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withTranslucent().withSpecular().withFade(), modelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular().withFade(), - modelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); + modelTranslucentNormalMapVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); addPipeline( // FIXME: Ignore lightmap for translucents meshpart Key::Builder().withMaterial().withTranslucent().withLightmap().withFade(), @@ -405,26 +411,26 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip skinModelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(), - skinModelNormalMapTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); + skinModelNormalMapTranslucentVertex, modelTranslucentNormalMapPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular(), skinModelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular(), - skinModelNormalMapTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); + skinModelNormalMapTranslucentVertex, modelTranslucentNormalMapPixel, nullptr, nullptr); // Same thing but with Fade on addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withFade(), skinModelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withFade(), - skinModelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); + skinModelNormalMapFadeVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular().withFade(), skinModelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular().withFade(), - skinModelNormalMapFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); + skinModelNormalMapFadeVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); // Depth-only addPipeline( diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf index 761e702595..67a5651ab8 100644 --- a/libraries/render-utils/src/model_translucent.slf +++ b/libraries/render-utils/src/model_translucent.slf @@ -16,7 +16,7 @@ <@include DeferredGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlended()$> +<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> <@include LightLocal.slh@> diff --git a/libraries/render-utils/src/model_translucent_fade.slf b/libraries/render-utils/src/model_translucent_fade.slf index a2d271653c..316dae7aad 100644 --- a/libraries/render-utils/src/model_translucent_fade.slf +++ b/libraries/render-utils/src/model_translucent_fade.slf @@ -16,7 +16,7 @@ <@include DeferredGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlended()$> +<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> <@include LightLocal.slh@> diff --git a/libraries/render-utils/src/model_translucent_normal_map.slf b/libraries/render-utils/src/model_translucent_normal_map.slf new file mode 100644 index 0000000000..759007d93e --- /dev/null +++ b/libraries/render-utils/src/model_translucent_normal_map.slf @@ -0,0 +1,91 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_translucent_normal_map.frag +// fragment shader +// +// Created by Olivier Prat on 23/01/2018. +// Copyright 2018 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 graphics/Material.slh@> + +<@include DeferredGlobalLight.slh@> + +<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> + +<@include LightLocal.slh@> + +<@include gpu/Transform.slh@> +<$declareStandardCameraTransform()$> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> + +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec4 _position; +in vec4 _worldPosition; +in vec3 _normal; +in vec3 _tangent; +in vec3 _color; +in float _alpha; + +out vec4 _fragColor; + +void main(void) { + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> + + float opacity = getMaterialOpacity(mat) * _alpha; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + + float metallic = getMaterialMetallic(mat); + vec3 fresnel = getFresnelF0(metallic, albedo); + + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + vec3 fragPosition = _position.xyz; + vec3 fragNormal; + <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, fragNormal)$> + + TransformCamera cam = getTransformCamera(); + vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0)); + vec3 fragEyeDir = normalize(fragEyeVector); + SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir); + + vec4 localLighting = vec4(0.0); + + <$fetchClusterInfo(_worldPosition)$>; + if (hasLocalLights(numLights, clusterPos, dims)) { + localLighting = evalLocalLighting(cluster, numLights, _worldPosition.xyz, surface, + metallic, fresnel, albedo, 0.0, + vec4(0), vec4(0), opacity); + } + + _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( + cam._viewInverse, + 1.0, + occlusionTex, + fragPosition, + albedo, + fresnel, + metallic, + emissive, + surface, opacity, localLighting.rgb), + opacity); +} diff --git a/libraries/render-utils/src/model_translucent_normal_map.slv b/libraries/render-utils/src/model_translucent_normal_map.slv new file mode 100644 index 0000000000..db824a3709 --- /dev/null +++ b/libraries/render-utils/src/model_translucent_normal_map.slv @@ -0,0 +1,46 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// model_translucent_normal_map.slv +// vertex shader +// +// Created by Olivier Prat on 23/01/18. +// Copyright 2018 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/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include MaterialTextures.slh@> +<$declareMaterialTexMapArrayBuffer()$> + +out float _alpha; +out vec2 _texCoord0; +out vec2 _texCoord1; +out vec4 _position; +out vec4 _worldPosition; +out vec3 _normal; +out vec3 _tangent; +out vec3 _color; + +void main(void) { + _color = colorToLinearRGB(inColor.xyz); + _alpha = inColor.w; + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$> + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> + <$transformModelToWorldPos(obj, inPosition, _worldPosition)$> + <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> + <$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangent)$> +} diff --git a/libraries/render-utils/src/model_translucent_normal_map_fade.slf b/libraries/render-utils/src/model_translucent_normal_map_fade.slf new file mode 100644 index 0000000000..204b5ac56b --- /dev/null +++ b/libraries/render-utils/src/model_translucent_normal_map_fade.slf @@ -0,0 +1,101 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_translucent_normal_map_fade.frag +// fragment shader +// +// Created by Olivier Prat on 23/01/18. +// Copyright 2018 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 graphics/Material.slh@> + +<@include DeferredGlobalLight.slh@> + +<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> + +<@include LightLocal.slh@> + +<@include gpu/Transform.slh@> +<$declareStandardCameraTransform()$> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> + +<@include Fade.slh@> +<$declareFadeFragment()$> + +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec4 _position; +in vec3 _normal; +in vec3 _tangent; +in vec3 _color; +in float _alpha; +in vec4 _worldPosition; + +out vec4 _fragColor; + +void main(void) { + vec3 fadeEmissive; + FadeObjectParams fadeParams; + + <$fetchFadeObjectParams(fadeParams)$> + applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> + + float opacity = getMaterialOpacity(mat) * _alpha; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + + float metallic = getMaterialMetallic(mat); + vec3 fresnel = getFresnelF0(metallic, albedo); + + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + vec3 fragPosition = _position.xyz; + // Lighting is done in world space + vec3 fragNormal; + <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, fragNormal)$> + + TransformCamera cam = getTransformCamera(); + vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0)); + vec3 fragEyeDir = normalize(fragEyeVector); + SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir); + + vec4 localLighting = vec4(0.0); + + <$fetchClusterInfo(_worldPosition)$>; + if (hasLocalLights(numLights, clusterPos, dims)) { + localLighting = evalLocalLighting(cluster, numLights, _worldPosition.xyz, surface, + metallic, fresnel, albedo, 0.0, + vec4(0), vec4(0), opacity); + } + + _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( + cam._viewInverse, + 1.0, + occlusionTex, + fragPosition, + albedo, + fresnel, + metallic, + emissive+fadeEmissive, + surface, opacity, localLighting.rgb), + opacity); +} diff --git a/libraries/render-utils/src/overlay3D_model_translucent.slf b/libraries/render-utils/src/overlay3D_model_translucent.slf index 8dd3a81443..b66c114f4a 100644 --- a/libraries/render-utils/src/overlay3D_model_translucent.slf +++ b/libraries/render-utils/src/overlay3D_model_translucent.slf @@ -11,7 +11,7 @@ // <@include DeferredGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlended()$> +<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> <@include graphics/Material.slh@> diff --git a/libraries/render-utils/src/simple_transparent_textured.slf b/libraries/render-utils/src/simple_transparent_textured.slf index b16b19c8b4..30c420233f 100644 --- a/libraries/render-utils/src/simple_transparent_textured.slf +++ b/libraries/render-utils/src/simple_transparent_textured.slf @@ -16,7 +16,7 @@ <@include DeferredBufferWrite.slh@> <@include DeferredGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlended()$> +<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> <@include gpu/Transform.slh@> <$declareStandardCameraTransform()$> diff --git a/libraries/render-utils/src/simple_transparent_textured_fade.slf b/libraries/render-utils/src/simple_transparent_textured_fade.slf index ad260210a7..a8a5875a4b 100644 --- a/libraries/render-utils/src/simple_transparent_textured_fade.slf +++ b/libraries/render-utils/src/simple_transparent_textured_fade.slf @@ -16,7 +16,7 @@ <@include DeferredBufferWrite.slh@> <@include DeferredGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlended()$> +<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> <@include gpu/Transform.slh@> <$declareStandardCameraTransform()$> From 1fd4c5c1a45199581e89e63a1b1ffb89cdbdfd65 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 29 Jan 2018 12:20:51 -0800 Subject: [PATCH 24/57] Integrating the tag flags to the render item key and adding configration of the render pipelien with the Tag information --- interface/src/SecondaryCamera.cpp | 2 +- libraries/render-utils/src/RenderShadowTask.cpp | 6 ++---- libraries/render-utils/src/RenderShadowTask.h | 4 +++- libraries/render-utils/src/RenderViewTask.cpp | 2 +- libraries/render/src/render/CullTask.cpp | 6 ++++-- libraries/render/src/render/CullTask.h | 4 ++-- libraries/render/src/render/RenderFetchCullSortTask.cpp | 4 +++- 7 files changed, 16 insertions(+), 12 deletions(-) diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index 748f1595db..6b8e370689 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -20,7 +20,7 @@ using RenderArgsPointer = std::shared_ptr; void MainRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred) { - task.addJob("RenderShadowTask", cullFunctor); + task.addJob("RenderShadowTask", cullFunctor, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1); const auto items = task.addJob("FetchCullSort", cullFunctor, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1); assert(items.canCast()); if (!isDeferred) { diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 20af1278ac..19a3f4ed73 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -216,7 +216,7 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende task.addJob("ShadowSetup"); for (auto i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) { - const auto setupOutput = task.addJob("ShadowCascadeSetup", i); + const auto setupOutput = task.addJob("ShadowCascadeSetup", i, tagBits, tagMask); const auto shadowFilter = setupOutput.getN(1); // CPU jobs: @@ -259,14 +259,12 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon // Cache old render args RenderArgs* args = renderContext->args; - // const auto& filterMask = inputs; - output.edit0() = args->_renderMode; output.edit2() = args->_sizeScale; const auto globalShadow = lightStage->getCurrentKeyShadow(); if (globalShadow && _cascadeIndexgetCascadeCount()) { - output.edit1() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered(); + output.edit1() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(_tagBits, _tagMask); globalShadow->setKeylightCascadeFrustum(_cascadeIndex, args->getViewFrustum(), SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR); diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index 2bc325cc81..33e0ad4daa 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -67,12 +67,14 @@ public: using Outputs = render::VaryingSet3; using JobModel = render::Job::ModelO; - RenderShadowCascadeSetup(unsigned int cascadeIndex) : _cascadeIndex{ cascadeIndex } {} + RenderShadowCascadeSetup(unsigned int cascadeIndex, uint8_t tagBits = 0x00, uint8_t tagMask = 0x00) : _cascadeIndex{ cascadeIndex }, _tagBits(tagBits), _tagMask(tagMask) {} void run(const render::RenderContextPointer& renderContext, Outputs& output); private: unsigned int _cascadeIndex; + uint8_t _tagBits{ 0x00 }; + uint8_t _tagMask{ 0x00 }; }; class RenderShadowCascadeTeardown { diff --git a/libraries/render-utils/src/RenderViewTask.cpp b/libraries/render-utils/src/RenderViewTask.cpp index 42d3044b1b..19924b4ddc 100644 --- a/libraries/render-utils/src/RenderViewTask.cpp +++ b/libraries/render-utils/src/RenderViewTask.cpp @@ -28,7 +28,7 @@ void RenderViewTask::build(JobModel& task, const render::Varying& input, render: const auto threshold = 1e-3f; return relativeBoundRadius > threshold; return true; - }); + }, tagBits, tagMask); const auto items = task.addJob("FetchCullSort", cullFunctor, tagBits, tagMask); assert(items.canCast()); diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp index 70331cdb47..8d99c3e8f2 100644 --- a/libraries/render/src/render/CullTask.cpp +++ b/libraries/render/src/render/CullTask.cpp @@ -61,7 +61,7 @@ void render::cullItems(const RenderContextPointer& renderContext, const CullFunc details._rendered += (int)outItems.size(); } -void FetchNonspatialItems::run(const RenderContextPointer& renderContext, ItemBounds& outItems) { +void FetchNonspatialItems::run(const RenderContextPointer& renderContext, const ItemFilter& filter, ItemBounds& outItems) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); auto& scene = renderContext->_scene; @@ -72,7 +72,9 @@ void FetchNonspatialItems::run(const RenderContextPointer& renderContext, ItemBo outItems.reserve(items.size()); for (auto& id : items) { auto& item = scene->getItem(id); - outItems.emplace_back(ItemBound(id, item.getBound())); + if (filter.test(item.getKey())) { + outItems.emplace_back(ItemBound(id, item.getBound())); + } } } diff --git a/libraries/render/src/render/CullTask.h b/libraries/render/src/render/CullTask.h index 486c4f4cdf..4461537109 100644 --- a/libraries/render/src/render/CullTask.h +++ b/libraries/render/src/render/CullTask.h @@ -24,8 +24,8 @@ namespace render { class FetchNonspatialItems { public: - using JobModel = Job::ModelO; - void run(const RenderContextPointer& renderContext, ItemBounds& outItems); + using JobModel = Job::ModelIO; + void run(const RenderContextPointer& renderContext, const ItemFilter& filter, ItemBounds& outItems); }; class FetchSpatialTreeConfig : public Job::Config { diff --git a/libraries/render/src/render/RenderFetchCullSortTask.cpp b/libraries/render/src/render/RenderFetchCullSortTask.cpp index bb6bd462f6..7f60d5bb52 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.cpp +++ b/libraries/render/src/render/RenderFetchCullSortTask.cpp @@ -29,7 +29,9 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin const auto culledSpatialSelection = task.addJob("CullSceneSelection", cullInputs, cullFunctor, RenderDetails::ITEM); // Overlays are not culled - const auto nonspatialSelection = task.addJob("FetchOverlaySelection"); + const ItemFilter overlayfilter = ItemFilter::Builder().withVisible().withTagBits(tagBits, tagMask); + const auto nonspatialFilter = render::Varying(overlayfilter); + const auto nonspatialSelection = task.addJob("FetchOverlaySelection", nonspatialFilter); // Multi filter visible items into different buckets const int NUM_SPATIAL_FILTERS = 4; From 2dcedf9f3901dac39067d6bf6aedad9b4ead28df Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 30 Jan 2018 12:52:05 -0800 Subject: [PATCH 25/57] cherry picking Tony's fix for shader compilation time not taking soo long and adding better feedback from shader compilation --- interface/src/Application.cpp | 23 ++- libraries/gl/src/gl/GLShaders.cpp | 161 +++++++++++------- libraries/gl/src/gl/GLShaders.h | 6 +- libraries/gpu-gl/src/gpu/gl/GLBackend.h | 4 +- .../gpu-gl/src/gpu/gl/GLBackendShader.cpp | 44 +++-- libraries/gpu-gl/src/gpu/gl/GLShader.cpp | 8 +- libraries/gpu-gl/src/gpu/gl/GLShader.h | 4 +- libraries/gpu-gles/src/gpu/gl/GLBackend.h | 4 +- .../gpu-gles/src/gpu/gl/GLBackendShader.cpp | 65 ++++++- libraries/gpu-gles/src/gpu/gl/GLShader.cpp | 8 +- libraries/gpu-gles/src/gpu/gl/GLShader.h | 4 +- libraries/gpu/src/gpu/Context.cpp | 4 +- libraries/gpu/src/gpu/Context.h | 4 +- libraries/gpu/src/gpu/Shader.cpp | 11 +- libraries/gpu/src/gpu/Shader.h | 29 +++- libraries/render/src/render/ShapePipeline.cpp | 52 +++--- 16 files changed, 297 insertions(+), 134 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 64e9feea02..f1d0378792 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -396,6 +396,7 @@ public: setObjectName("Deadlock Watchdog"); // Give the heartbeat an initial value _heartbeat = usecTimestampNow(); + _paused = false; connect(qApp, &QCoreApplication::aboutToQuit, [this] { _quit = true; }); @@ -413,11 +414,20 @@ public: *crashTrigger = 0xDEAD10CC; } + static void pause() { + _paused = true; + } + + static void resume() { + _paused = false; + updateHeartbeat(); + } + void run() override { while (!_quit) { QThread::sleep(HEARTBEAT_UPDATE_INTERVAL_SECS); // Don't do heartbeat detection under nsight - if (nsightActive()) { + if (nsightActive() || _paused) { continue; } uint64_t lastHeartbeat = _heartbeat; // sample atomic _heartbeat, because we could context switch away and have it updated on us @@ -473,6 +483,7 @@ public: } } + static std::atomic _paused; static std::atomic _heartbeat; static std::atomic _maxElapsed; static std::atomic _maxElapsedAverage; @@ -481,6 +492,7 @@ public: bool _quit { false }; }; +std::atomic DeadlockWatchdogThread::_paused; std::atomic DeadlockWatchdogThread::_heartbeat; std::atomic DeadlockWatchdogThread::_maxElapsed; std::atomic DeadlockWatchdogThread::_maxElapsedAverage; @@ -2269,6 +2281,11 @@ void Application::initializeGL() { initDisplay(); qCDebug(interfaceapp, "Initialized Display."); +#ifdef Q_OS_OSX + // FIXME: on mac os the shaders take up to 1 minute to compile, so we pause the deadlock watchdog thread. + +DeadlockWatchdogThread::pause(); +#endif + // Set up the render engine render::CullFunctor cullFunctor = LODManager::shouldRender; static const QString RENDER_FORWARD = "HIFI_RENDER_FORWARD"; @@ -2283,6 +2300,10 @@ void Application::initializeGL() { // Now that OpenGL is initialized, we are sure we have a valid context and can create the various pipeline shaders with success. DependencyManager::get()->initializeShapePipelines(); +#ifdef Q_OS_OSX + DeadlockWatchdogThread::resume(); +#endif + _offscreenContext = new OffscreenGLCanvas(); _offscreenContext->setObjectName("MainThreadContext"); _offscreenContext->create(_glWidget->qglContext()); diff --git a/libraries/gl/src/gl/GLShaders.cpp b/libraries/gl/src/gl/GLShaders.cpp index 017c92b71c..ecd6fe3323 100644 --- a/libraries/gl/src/gl/GLShaders.cpp +++ b/libraries/gl/src/gl/GLShaders.cpp @@ -6,9 +6,9 @@ namespace gl { #ifdef SEPARATE_PROGRAM - bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const std::string& defines, GLuint &shaderObject, GLuint &programObject, std::string& error) { + bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const std::string& defines, GLuint &shaderObject, GLuint &programObject, std::string& message) { #else - bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const std::string& defines, GLuint &shaderObject, std::string& error) { + bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const std::string& defines, GLuint &shaderObject, std::string& message) { #endif if (shaderSource.empty()) { qCDebug(glLogging) << "GLShader::compileShader - no GLSL shader source code ? so failed to create"; @@ -34,52 +34,57 @@ namespace gl { GLint compiled = 0; glGetShaderiv(glshader, GL_COMPILE_STATUS, &compiled); - // if compilation fails - if (!compiled) { - - // save the source code to a temp file so we can debug easily - /* - std::ofstream filestream; - filestream.open("debugshader.glsl"); - if (filestream.is_open()) { - filestream << srcstr[0]; - filestream << srcstr[1]; - filestream.close(); - } - */ - - GLint infoLength = 0; - glGetShaderiv(glshader, GL_INFO_LOG_LENGTH, &infoLength); + GLint infoLength = 0; + glGetShaderiv(glshader, GL_INFO_LOG_LENGTH, &infoLength); + if ((infoLength > 0) || !compiled) { char* temp = new char[infoLength]; glGetShaderInfoLog(glshader, infoLength, NULL, temp); + message = std::string(temp); - /* - filestream.open("debugshader.glsl.info.txt"); - if (filestream.is_open()) { - filestream << std::string(temp); - filestream.close(); - } - */ - - qCCritical(glLogging) << "GLShader::compileShader - failed to compile the gl shader object:"; - int lineNumber = 0; - for (auto s : srcstr) { - QString str(s); - QStringList lines = str.split("\n"); - for (auto& line : lines) { - qCCritical(glLogging).noquote() << QString("%1: %2").arg(lineNumber++, 5, 10, QChar('0')).arg(line); + // if compilation fails + if (!compiled) { + // save the source code to a temp file so we can debug easily + /* + std::ofstream filestream; + filestream.open("debugshader.glsl"); + if (filestream.is_open()) { + filestream << srcstr[0]; + filestream << srcstr[1]; + filestream.close(); } + */ + + /* + filestream.open("debugshader.glsl.info.txt"); + if (filestream.is_open()) { + filestream << std::string(temp); + filestream.close(); + } + */ + + qCCritical(glLogging) << "GLShader::compileShader - failed to compile the gl shader object:"; + int lineNumber = 0; + for (auto s : srcstr) { + QString str(s); + QStringList lines = str.split("\n"); + for (auto& line : lines) { + qCCritical(glLogging).noquote() << QString("%1: %2").arg(lineNumber++, 5, 10, QChar('0')).arg(line); + } + } + qCCritical(glLogging) << "GLShader::compileShader - errors:"; + qCCritical(glLogging) << temp; + + delete[] temp; + glDeleteShader(glshader); + return false; } - qCCritical(glLogging) << "GLShader::compileShader - errors:"; - qCCritical(glLogging) << temp; - error = std::string(temp); + // Compilation success + qCWarning(glLogging) << "GLShader::compileShader - Success:"; + qCWarning(glLogging) << temp; delete[] temp; - - glDeleteShader(glshader); - return false; } #ifdef SEPARATE_PROGRAM @@ -137,7 +142,7 @@ namespace gl { return true; } -GLuint compileProgram(const std::vector& glshaders, std::string& error) { +GLuint compileProgram(const std::vector& glshaders, std::string& message, std::vector& binary) { // A brand new program: GLuint glprogram = glCreateProgram(); if (!glprogram) { @@ -157,39 +162,65 @@ GLuint compileProgram(const std::vector& glshaders, std::string& error) GLint linked = 0; glGetProgramiv(glprogram, GL_LINK_STATUS, &linked); - if (!linked) { - /* - // save the source code to a temp file so we can debug easily - std::ofstream filestream; - filestream.open("debugshader.glsl"); - if (filestream.is_open()) { - filestream << shaderSource->source; - filestream.close(); - } - */ - - GLint infoLength = 0; - glGetProgramiv(glprogram, GL_INFO_LOG_LENGTH, &infoLength); + GLint infoLength = 0; + glGetProgramiv(glprogram, GL_INFO_LOG_LENGTH, &infoLength); + if ((infoLength > 0) || !linked) { char* temp = new char[infoLength]; glGetProgramInfoLog(glprogram, infoLength, NULL, temp); - qCDebug(glLogging) << "GLShader::compileProgram - failed to LINK the gl program object :"; - qCDebug(glLogging) << temp; + message = std::string(temp); - error = std::string(temp); - delete[] temp; + if (!linked) { + /* + // save the source code to a temp file so we can debug easily + std::ofstream filestream; + filestream.open("debugshader.glsl"); + if (filestream.is_open()) { + filestream << shaderSource->source; + filestream.close(); + } + */ - /* - filestream.open("debugshader.glsl.info.txt"); - if (filestream.is_open()) { - filestream << std::string(temp); - filestream.close(); + qCDebug(glLogging) << "GLShader::compileProgram - failed to LINK the gl program object :"; + qCDebug(glLogging) << temp; + + delete[] temp; + + /* + filestream.open("debugshader.glsl.info.txt"); + if (filestream.is_open()) { + filestream << std::string(temp); + filestream.close(); + } + */ + + glDeleteProgram(glprogram); + return 0; + } else { + qCDebug(glLogging) << "GLShader::compileProgram - success:"; + qCDebug(glLogging) << temp; + delete[] temp; } - */ + } - glDeleteProgram(glprogram); - return 0; + // If linked get the binaries + if (linked) { + GLint binaryLength = 0; + glGetProgramiv(glprogram, GL_PROGRAM_BINARY_LENGTH, &binaryLength); + + if (binaryLength > 0) { + GLint numBinFormats = 0; + glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &numBinFormats); + if (numBinFormats > 0) { + binary.resize(binaryLength); + std::vector binFormats(numBinFormats); + glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, binFormats.data()); + + GLenum programBinFormat; + glGetProgramBinary(glprogram, binaryLength, NULL, &programBinFormat, binary.data()); + } + } } return glprogram; diff --git a/libraries/gl/src/gl/GLShaders.h b/libraries/gl/src/gl/GLShaders.h index a6213fd280..c5262b6b61 100644 --- a/libraries/gl/src/gl/GLShaders.h +++ b/libraries/gl/src/gl/GLShaders.h @@ -17,12 +17,12 @@ namespace gl { #ifdef SEPARATE_PROGRAM - bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const std::string& defines, GLuint &shaderObject, GLuint &programObject, std::string& error); + bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const std::string& defines, GLuint &shaderObject, GLuint &programObject, std::string& message); #else - bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const std::string& defines, GLuint &shaderObject, std::string& error); + bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const std::string& defines, GLuint &shaderObject, std::string& message); #endif - GLuint compileProgram(const std::vector& glshaders, std::string& error); + GLuint compileProgram(const std::vector& glshaders, std::string& message, , std::vector& binary); } diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.h b/libraries/gpu-gl/src/gpu/gl/GLBackend.h index 5558d3ada1..004bfe1c85 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.h @@ -64,7 +64,7 @@ protected: explicit GLBackend(bool syncCache); GLBackend(); public: - static bool makeProgram(Shader& shader, const Shader::BindingSet& slotBindings = Shader::BindingSet()); + static bool makeProgram(Shader& shader, const Shader::BindingSet& slotBindings = Shader::BindingSet(), Shader::CompilationHandler handler = nullptr); virtual ~GLBackend(); @@ -424,7 +424,7 @@ protected: // Backend dependant compilation of the shader virtual GLShader* compileBackendProgram(const Shader& program); - virtual GLShader* compileBackendShader(const Shader& shader); + virtual GLShader* compileBackendShader(const Shader& shader, Shader::CompilationHandler handler); virtual std::string getBackendShaderHeader() const; virtual void makeProgramBindings(ShaderObject& shaderObject); class ElementResource { diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp index 9adfd550ef..84170dbffd 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp @@ -56,28 +56,43 @@ static const std::array VERSION_DEFINES { { stereoVersion } }; -GLShader* GLBackend::compileBackendShader(const Shader& shader) { +GLShader* GLBackend::compileBackendShader(const Shader& shader, Shader::CompilationHandler handler) { // Any GLSLprogram ? normally yes... const std::string& shaderSource = shader.getSource().getCode(); GLenum shaderDomain = SHADER_DOMAINS[shader.getType()]; GLShader::ShaderObjects shaderObjects; + Shader::CompilationLogs compilationLogs(GLShader::NumVersions); for (int version = 0; version < GLShader::NumVersions; version++) { auto& shaderObject = shaderObjects[version]; std::string shaderDefines = getBackendShaderHeader() + "\n" + DOMAIN_DEFINES[shader.getType()] + "\n" + VERSION_DEFINES[version]; - std::string error; + if (handler) { + bool retest = true; + std::string currentSrc = shaderSource; + while (retest) { + bool result = ::gl::compileShader(shaderDomain, currentSrc, shaderDefines, shaderObject.glshader, compilationLogs[version].message); + compilationLogs[version].compiled = result; + if (!result) { + std::string newSrc; + retest = handler(shader, currentSrc, compilationLogs[version], newSrc); + currentSrc = newSrc; + } else { + retest = false; + } + } + } else { + compilationLogs[version].compiled = ::gl::compileShader(shaderDomain, shaderSource, shaderDefines, shaderObject.glshader, compilationLogs[version].message); + } -#ifdef SEPARATE_PROGRAM - bool result = ::gl::compileShader(shaderDomain, shaderSource, shaderDefines, shaderObject.glshader, shaderObject.glprogram, error); -#else - bool result = ::gl::compileShader(shaderDomain, shaderSource, shaderDefines, shaderObject.glshader, error); -#endif - if (!result) { - qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - Shader didn't compile:\n" << error.c_str(); + if (!compilationLogs[version].compiled) { + qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - Shader didn't compile:\n" << compilationLogs[version].message.c_str(); + shader.setCompilationLogs(compilationLogs); return nullptr; } } + // Compilation feedback + shader.setCompilationLogs(compilationLogs); // So far so good, the shader is created successfully GLShader* object = new GLShader(this->shared_from_this()); @@ -93,6 +108,8 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program) { GLShader::ShaderObjects programObjects; + Shader::CompilationLogs compilationLogs(GLShader::NumVersions); + for (int version = 0; version < GLShader::NumVersions; version++) { auto& programObject = programObjects[version]; @@ -104,14 +121,15 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program) { shaderGLObjects.push_back(object->_shaderObjects[version].glshader); } else { qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - One of the shaders of the program is not compiled?"; + program.setCompilationLogs(compilationLogs); return nullptr; } } - std::string error; - GLuint glprogram = ::gl::compileProgram(shaderGLObjects, error); + GLuint glprogram = ::gl::compileProgram(shaderGLObjects, compilationLogs[version].message, compilationLogs[version].binary); if (glprogram == 0) { - qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - Program didn't link:\n" << error.c_str(); + qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - Program didn't link:\n" << compilationLogs[version].message.c_str(); + program.setCompilationLogs(compilationLogs); return nullptr; } @@ -119,6 +137,8 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program) { makeProgramBindings(programObject); } + // Compilation feedback + program.setCompilationLogs(compilationLogs); // So far so good, the program versions have all been created successfully GLShader* object = new GLShader(this->shared_from_this()); diff --git a/libraries/gpu-gl/src/gpu/gl/GLShader.cpp b/libraries/gpu-gl/src/gpu/gl/GLShader.cpp index 7ed9121978..a626376e27 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLShader.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLShader.cpp @@ -30,7 +30,7 @@ GLShader::~GLShader() { } } -GLShader* GLShader::sync(GLBackend& backend, const Shader& shader) { +GLShader* GLShader::sync(GLBackend& backend, const Shader& shader, Shader::CompilationHandler handler) { GLShader* object = Backend::getGPUObject(shader); // If GPU object already created then good @@ -45,7 +45,7 @@ GLShader* GLShader::sync(GLBackend& backend, const Shader& shader) { Backend::setGPUObject(shader, object); } } else if (shader.isDomain()) { - GLShader* tempObject = backend.compileBackendShader(shader); + GLShader* tempObject = backend.compileBackendShader(shader, handler); if (tempObject) { object = tempObject; Backend::setGPUObject(shader, object); @@ -56,10 +56,10 @@ GLShader* GLShader::sync(GLBackend& backend, const Shader& shader) { return object; } -bool GLShader::makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings) { +bool GLShader::makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings, Shader::CompilationHandler handler) { // First make sure the Shader has been compiled - GLShader* object = sync(backend, shader); + GLShader* object = sync(backend, shader, handler); if (!object) { return false; } diff --git a/libraries/gpu-gl/src/gpu/gl/GLShader.h b/libraries/gpu-gl/src/gpu/gl/GLShader.h index dcf2dc330d..42d63f8dfb 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLShader.h +++ b/libraries/gpu-gl/src/gpu/gl/GLShader.h @@ -21,8 +21,8 @@ struct ShaderObject { class GLShader : public GPUObject { public: - static GLShader* sync(GLBackend& backend, const Shader& shader); - static bool makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings); + static GLShader* sync(GLBackend& backend, const Shader& shader, Shader::CompilationHandler handler = nullptr); + static bool makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings, Shader::CompilationHandler handler = nullptr); enum Version { Mono = 0, diff --git a/libraries/gpu-gles/src/gpu/gl/GLBackend.h b/libraries/gpu-gles/src/gpu/gl/GLBackend.h index ea06b6b672..bb8e15bad3 100644 --- a/libraries/gpu-gles/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gles/src/gpu/gl/GLBackend.h @@ -61,7 +61,7 @@ protected: explicit GLBackend(bool syncCache); GLBackend(); public: - static bool makeProgram(Shader& shader, const Shader::BindingSet& slotBindings = Shader::BindingSet()); + static bool makeProgram(Shader& shader, const Shader::BindingSet& slotBindings = Shader::BindingSet(), Shader::CompilationHandler handler = nullptr); virtual ~GLBackend(); @@ -421,7 +421,7 @@ protected: // Backend dependant compilation of the shader virtual GLShader* compileBackendProgram(const Shader& program); - virtual GLShader* compileBackendShader(const Shader& shader); + virtual GLShader* compileBackendShader(const Shader& shader, Shader::CompilationHandler handler); virtual std::string getBackendShaderHeader() const; virtual void makeProgramBindings(ShaderObject& shaderObject); class ElementResource { diff --git a/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp b/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp index fd44ad462f..26dbb12cf7 100644 --- a/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp +++ b/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp @@ -56,11 +56,12 @@ static const std::array VERSION_DEFINES { { stereoVersion } }; -GLShader* GLBackend::compileBackendShader(const Shader& shader) { +GLShader* GLBackend::compileBackendShader(const Shader& shader, Shader::CompilationHandler handler) { // Any GLSLprogram ? normally yes... const std::string& shaderSource = shader.getSource().getCode(); GLenum shaderDomain = SHADER_DOMAINS[shader.getType()]; GLShader::ShaderObjects shaderObjects; + Shader::CompilationLogs compilationLogs(GLShader::NumVersions); for (int version = 0; version < GLShader::NumVersions; version++) { auto& shaderObject = shaderObjects[version]; @@ -90,6 +91,55 @@ GLShader* GLBackend::compileBackendShader(const Shader& shader) { return object; } +GLShader* GLBackend::compileBackendShader(const Shader& shader, Shader::CompilationHandler handler) { + // Any GLSLprogram ? normally yes... + const std::string& shaderSource = shader.getSource().getCode(); + GLenum shaderDomain = SHADER_DOMAINS[shader.getType()]; + GLShader::ShaderObjects shaderObjects; + Shader::CompilationLogs compilationLogs(GLShader::NumVersions); + + for (int version = 0; version < GLShader::NumVersions; version++) { + auto& shaderObject = shaderObjects[version]; + + std::string shaderDefines = getBackendShaderHeader() + "\n" + DOMAIN_DEFINES[shader.getType()] + "\n" + VERSION_DEFINES[version] + + "\n#extension GL_EXT_texture_buffer : enable" + + "\nprecision lowp float; // check precision 2" + + "\nprecision lowp samplerBuffer;" + + "\nprecision lowp sampler2DShadow;"; + if (handler) { + bool retest = true; + std::string currentSrc = shaderSource; + while (retest) { + bool result = ::gl::compileShader(shaderDomain, currentSrc, shaderDefines, shaderObject.glshader, compilationLogs[version].message); + compilationLogs[version].compiled = result; + if (!result) { + std::string newSrc; + retest = handler(shader, currentSrc, compilationLogs[version], newSrc); + currentSrc = newSrc; + } else { + retest = false; + } + } + } else { + compilationLogs[version].compiled = ::gl::compileShader(shaderDomain, shaderSource, shaderDefines, shaderObject.glshader, compilationLogs[version].message); + } + + if (!compilationLogs[version].compiled) { + qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - Shader didn't compile:\n" << compilationLogs[version].message.c_str(); + shader.setCompilationLogs(compilationLogs); + return nullptr; + } + } + // Compilation feedback + shader.setCompilationLogs(compilationLogs); + + // So far so good, the shader is created successfully + GLShader* object = new GLShader(this->shared_from_this()); + object->_shaderObjects = shaderObjects; + + return object; +} + GLShader* GLBackend::compileBackendProgram(const Shader& program) { if (!program.isProgram()) { return nullptr; @@ -97,25 +147,28 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program) { GLShader::ShaderObjects programObjects; + Shader::CompilationLogs compilationLogs(GLShader::NumVersions); + for (int version = 0; version < GLShader::NumVersions; version++) { auto& programObject = programObjects[version]; // Let's go through every shaders and make sure they are ready to go - std::vector shaderGLObjects; + std::vector< GLuint > shaderGLObjects; for (auto subShader : program.getShaders()) { auto object = GLShader::sync((*this), *subShader); if (object) { shaderGLObjects.push_back(object->_shaderObjects[version].glshader); } else { qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - One of the shaders of the program is not compiled?"; + program.setCompilationLogs(compilationLogs); return nullptr; } } - std::string error; - GLuint glprogram = ::gl::compileProgram(shaderGLObjects, error); + GLuint glprogram = ::gl::compileProgram(shaderGLObjects, compilationLogs[version].message, compilationLogs[version].binary); if (glprogram == 0) { - qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - Program didn't link:\n" << error.c_str(); + qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - Program didn't link:\n" << compilationLogs[version].message.c_str(); + program.setCompilationLogs(compilationLogs); return nullptr; } @@ -123,6 +176,8 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program) { makeProgramBindings(programObject); } + // Compilation feedback + program.setCompilationLogs(compilationLogs); // So far so good, the program versions have all been created successfully GLShader* object = new GLShader(this->shared_from_this()); diff --git a/libraries/gpu-gles/src/gpu/gl/GLShader.cpp b/libraries/gpu-gles/src/gpu/gl/GLShader.cpp index 7ed9121978..a626376e27 100644 --- a/libraries/gpu-gles/src/gpu/gl/GLShader.cpp +++ b/libraries/gpu-gles/src/gpu/gl/GLShader.cpp @@ -30,7 +30,7 @@ GLShader::~GLShader() { } } -GLShader* GLShader::sync(GLBackend& backend, const Shader& shader) { +GLShader* GLShader::sync(GLBackend& backend, const Shader& shader, Shader::CompilationHandler handler) { GLShader* object = Backend::getGPUObject(shader); // If GPU object already created then good @@ -45,7 +45,7 @@ GLShader* GLShader::sync(GLBackend& backend, const Shader& shader) { Backend::setGPUObject(shader, object); } } else if (shader.isDomain()) { - GLShader* tempObject = backend.compileBackendShader(shader); + GLShader* tempObject = backend.compileBackendShader(shader, handler); if (tempObject) { object = tempObject; Backend::setGPUObject(shader, object); @@ -56,10 +56,10 @@ GLShader* GLShader::sync(GLBackend& backend, const Shader& shader) { return object; } -bool GLShader::makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings) { +bool GLShader::makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings, Shader::CompilationHandler handler) { // First make sure the Shader has been compiled - GLShader* object = sync(backend, shader); + GLShader* object = sync(backend, shader, handler); if (!object) { return false; } diff --git a/libraries/gpu-gles/src/gpu/gl/GLShader.h b/libraries/gpu-gles/src/gpu/gl/GLShader.h index dcf2dc330d..42d63f8dfb 100644 --- a/libraries/gpu-gles/src/gpu/gl/GLShader.h +++ b/libraries/gpu-gles/src/gpu/gl/GLShader.h @@ -21,8 +21,8 @@ struct ShaderObject { class GLShader : public GPUObject { public: - static GLShader* sync(GLBackend& backend, const Shader& shader); - static bool makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings); + static GLShader* sync(GLBackend& backend, const Shader& shader, Shader::CompilationHandler handler = nullptr); + static bool makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings, Shader::CompilationHandler handler = nullptr); enum Version { Mono = 0, diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index 24128524da..2399d3ddc3 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -127,7 +127,7 @@ void Context::executeFrame(const FramePointer& frame) const { _frameStats.evalDelta(beginStats, endStats); } -bool Context::makeProgram(Shader& shader, const Shader::BindingSet& bindings) { +bool Context::makeProgram(Shader& shader, const Shader::BindingSet& bindings, Shader::CompilationHandler handler) { // If we're running in another DLL context, we need to fetch the program callback out of the application // FIXME find a way to do this without reliance on Qt app properties if (!_makeProgramCallback) { @@ -135,7 +135,7 @@ bool Context::makeProgram(Shader& shader, const Shader::BindingSet& bindings) { _makeProgramCallback = reinterpret_cast(rawCallback); } if (shader.isProgram() && _makeProgramCallback) { - return _makeProgramCallback(shader, bindings); + return _makeProgramCallback(shader, bindings, handler); } return false; } diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 7b7575e9ed..7d04463609 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -143,7 +143,7 @@ class Context { public: using Size = Resource::Size; typedef BackendPointer (*CreateBackend)(); - typedef bool (*MakeProgram)(Shader& shader, const Shader::BindingSet& bindings); + typedef bool (*MakeProgram)(Shader& shader, const Shader::BindingSet& bindings, Shader::CompilationHandler handler); // This one call must happen before any context is created or used (Shader::MakeProgram) in order to setup the Backend and any singleton data needed @@ -262,7 +262,7 @@ protected: // makeProgramShader(...) make a program shader ready to be used in a Batch. // It compiles the sub shaders, link them and defines the Slots and their bindings. // If the shader passed is not a program, nothing happens. - static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings); + static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings, Shader::CompilationHandler handler = nullptr); static CreateBackend _createBackendCallback; static MakeProgram _makeProgramCallback; diff --git a/libraries/gpu/src/gpu/Shader.cpp b/libraries/gpu/src/gpu/Shader.cpp index 398a269f3f..35c9ad8ae2 100755 --- a/libraries/gpu/src/gpu/Shader.cpp +++ b/libraries/gpu/src/gpu/Shader.cpp @@ -82,9 +82,16 @@ void Shader::defineSlots(const SlotSet& uniforms, const SlotSet& uniformBuffers, _outputs = outputs; } -bool Shader::makeProgram(Shader& shader, const Shader::BindingSet& bindings) { +bool Shader::makeProgram(Shader& shader, const Shader::BindingSet& bindings, CompilationHandler handler) { if (shader.isProgram()) { - return Context::makeProgram(shader, bindings); + return Context::makeProgram(shader, bindings, handler); } return false; } + +void Shader::setCompilationLogs(const CompilationLogs& logs) const { + _compilationLogs.clear(); + for (const auto& log : logs) { + _compilationLogs.emplace_back(CompilationLog(log)); + } +} diff --git a/libraries/gpu/src/gpu/Shader.h b/libraries/gpu/src/gpu/Shader.h index 181c9b5e78..33449fe656 100755 --- a/libraries/gpu/src/gpu/Shader.h +++ b/libraries/gpu/src/gpu/Shader.h @@ -44,6 +44,19 @@ public: Language _lang = GLSL; }; + struct CompilationLog { + std::string message; + std::vector binary; + bool compiled{ false }; + + CompilationLog() {} + CompilationLog(const CompilationLog& src) : + message(src.message), + binary(src.binary), + compiled(src.compiled) {} + }; + using CompilationLogs = std::vector; + static const int32 INVALID_LOCATION = -1; class Slot { @@ -155,6 +168,8 @@ public: const SlotSet& inputs, const SlotSet& outputs); + typedef bool(*CompilationHandler)(const Shader& shader, const std::string& src, CompilationLog& log, std::string& newSrc); + // makeProgram(...) make a program shader ready to be used in a Batch. // It compiles the sub shaders, link them and defines the Slots and their bindings. // If the shader passed is not a program, nothing happens. @@ -168,7 +183,16 @@ public: // on a gl Context and the driver to compile the glsl shader. // Hoppefully in a few years the shader compilation will be completely abstracted in a separate shader compiler library // independant of the graphics api in use underneath (looking at you opengl & vulkan). - static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings = Shader::BindingSet()); + static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings = Shader::BindingSet(), CompilationHandler handler = nullptr); + + // Check the compilation state + bool compilationHasFailed() const { return _compilationHasFailed; } + const CompilationLogs& getCompilationLogs() const { return _compilationLogs; } + + // Set COmpilation logs can only be called by the Backend layers + void setCompilationHasFailed(bool compilationHasFailed) { _compilationHasFailed = compilationHasFailed; } + void setCompilationLogs(const CompilationLogs& logs) const; + const GPUObjectPointer gpuObject {}; @@ -198,6 +222,9 @@ protected: // The type of the shader, the master key Type _type; + // Compilation logs (one for each versions generated) + mutable CompilationLogs _compilationLogs; + // Whether or not the shader compilation failed bool _compilationHasFailed { false }; }; diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index fb58c21dde..597a6a0fab 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -72,34 +72,36 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p BatchSetter batchSetter, ItemSetter itemSetter) { ShapeKey key{ filter._flags }; - gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("lightingModelBuffer"), Slot::BUFFER::LIGHTING_MODEL)); - slotBindings.insert(gpu::Shader::Binding(std::string("skinClusterBuffer"), Slot::BUFFER::SKINNING)); - slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), Slot::BUFFER::MATERIAL)); - slotBindings.insert(gpu::Shader::Binding(std::string("texMapArrayBuffer"), Slot::BUFFER::TEXMAPARRAY)); - slotBindings.insert(gpu::Shader::Binding(std::string("albedoMap"), Slot::MAP::ALBEDO)); - slotBindings.insert(gpu::Shader::Binding(std::string("roughnessMap"), Slot::MAP::ROUGHNESS)); - slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), Slot::MAP::NORMAL)); - slotBindings.insert(gpu::Shader::Binding(std::string("metallicMap"), Slot::MAP::METALLIC)); - slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), Slot::MAP::EMISSIVE_LIGHTMAP)); - slotBindings.insert(gpu::Shader::Binding(std::string("occlusionMap"), Slot::MAP::OCCLUSION)); - slotBindings.insert(gpu::Shader::Binding(std::string("scatteringMap"), Slot::MAP::SCATTERING)); - slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), Slot::BUFFER::KEY_LIGHT)); - slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), Slot::BUFFER::LIGHT)); - slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), Slot::BUFFER::LIGHT_AMBIENT_BUFFER)); - slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), Slot::MAP::LIGHT_AMBIENT)); - slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), Slot::MAP::FADE_MASK)); - slotBindings.insert(gpu::Shader::Binding(std::string("fadeParametersBuffer"), Slot::BUFFER::FADE_PARAMETERS)); - slotBindings.insert(gpu::Shader::Binding(std::string("hazeBuffer"), Slot::BUFFER::HAZE_MODEL)); + if (program->getInputs().empty()) { + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("lightingModelBuffer"), Slot::BUFFER::LIGHTING_MODEL)); + slotBindings.insert(gpu::Shader::Binding(std::string("skinClusterBuffer"), Slot::BUFFER::SKINNING)); + slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), Slot::BUFFER::MATERIAL)); + slotBindings.insert(gpu::Shader::Binding(std::string("texMapArrayBuffer"), Slot::BUFFER::TEXMAPARRAY)); + slotBindings.insert(gpu::Shader::Binding(std::string("albedoMap"), Slot::MAP::ALBEDO)); + slotBindings.insert(gpu::Shader::Binding(std::string("roughnessMap"), Slot::MAP::ROUGHNESS)); + slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), Slot::MAP::NORMAL)); + slotBindings.insert(gpu::Shader::Binding(std::string("metallicMap"), Slot::MAP::METALLIC)); + slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), Slot::MAP::EMISSIVE_LIGHTMAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("occlusionMap"), Slot::MAP::OCCLUSION)); + slotBindings.insert(gpu::Shader::Binding(std::string("scatteringMap"), Slot::MAP::SCATTERING)); + slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), Slot::BUFFER::KEY_LIGHT)); + slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), Slot::BUFFER::LIGHT)); + slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), Slot::BUFFER::LIGHT_AMBIENT_BUFFER)); + slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), Slot::MAP::LIGHT_AMBIENT)); + slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), Slot::MAP::FADE_MASK)); + slotBindings.insert(gpu::Shader::Binding(std::string("fadeParametersBuffer"), Slot::BUFFER::FADE_PARAMETERS)); + slotBindings.insert(gpu::Shader::Binding(std::string("hazeBuffer"), Slot::BUFFER::HAZE_MODEL)); - if (key.isTranslucent()) { - slotBindings.insert(gpu::Shader::Binding(std::string("clusterGridBuffer"), Slot::BUFFER::LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT)); - slotBindings.insert(gpu::Shader::Binding(std::string("clusterContentBuffer"), Slot::BUFFER::LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT)); - slotBindings.insert(gpu::Shader::Binding(std::string("frustumGridBuffer"), Slot::BUFFER::LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT)); + if (key.isTranslucent()) { + slotBindings.insert(gpu::Shader::Binding(std::string("clusterGridBuffer"), Slot::BUFFER::LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("clusterContentBuffer"), Slot::BUFFER::LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("frustumGridBuffer"), Slot::BUFFER::LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT)); + } + + gpu::Shader::makeProgram(*program, slotBindings); } - gpu::Shader::makeProgram(*program, slotBindings); - auto locations = std::make_shared(); locations->albedoTextureUnit = program->getTextures().findLocation("albedoMap"); From d5e52834ef7873270e28d0b86785d34a0679a642 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 30 Jan 2018 13:07:20 -0800 Subject: [PATCH 26/57] cherry picking Tony's fix for shader compilation time not taking soo long and adding better feedback from shader compilation --- libraries/gl/src/gl/GLShaders.h | 2 +- libraries/gpu-gl/src/gpu/gl/GLBackend.cpp | 4 ++-- libraries/gpu-gles/src/gpu/gl/GLBackend.cpp | 4 ++-- libraries/gpu/src/gpu/Shader.h | 3 --- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/libraries/gl/src/gl/GLShaders.h b/libraries/gl/src/gl/GLShaders.h index c5262b6b61..fc070d7659 100644 --- a/libraries/gl/src/gl/GLShaders.h +++ b/libraries/gl/src/gl/GLShaders.h @@ -22,7 +22,7 @@ namespace gl { bool compileShader(GLenum shaderDomain, const std::string& shaderSource, const std::string& defines, GLuint &shaderObject, std::string& message); #endif - GLuint compileProgram(const std::vector& glshaders, std::string& message, , std::vector& binary); + GLuint compileProgram(const std::vector& glshaders, std::string& message, std::vector& binary); } diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp index eb6de5df13..2a052c5210 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp @@ -68,8 +68,8 @@ GLBackend& getBackend() { return *INSTANCE; } -bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindings) { - return GLShader::makeProgram(getBackend(), shader, slotBindings); +bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindings, Shader::CompilationHandler handler) { + return GLShader::makeProgram(getBackend(), shader, slotBindings, handler); } GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = diff --git a/libraries/gpu-gles/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gles/src/gpu/gl/GLBackend.cpp index 6fd5df6f81..8a118b7b71 100644 --- a/libraries/gpu-gles/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gles/src/gpu/gl/GLBackend.cpp @@ -61,8 +61,8 @@ GLBackend& getBackend() { return *INSTANCE; } -bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindings) { - return GLShader::makeProgram(getBackend(), shader, slotBindings); +bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindings, Shader::CompilationHandler handler) { + return GLShader::makeProgram(getBackend(), shader, slotBindings, handler); } diff --git a/libraries/gpu/src/gpu/Shader.h b/libraries/gpu/src/gpu/Shader.h index 33449fe656..d78077a396 100755 --- a/libraries/gpu/src/gpu/Shader.h +++ b/libraries/gpu/src/gpu/Shader.h @@ -138,9 +138,6 @@ public: bool isProgram() const { return getType() > NUM_DOMAINS; } bool isDomain() const { return getType() < NUM_DOMAINS; } - void setCompilationHasFailed(bool compilationHasFailed) { _compilationHasFailed = compilationHasFailed; } - bool compilationHasFailed() const { return _compilationHasFailed; } - const Source& getSource() const { return _source; } const Shaders& getShaders() const { return _shaders; } From f078ff611a4b19ac779d6e3926b09db4ec3ad4fc Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 30 Jan 2018 15:10:52 -0800 Subject: [PATCH 27/57] Refining the declaraion signatures and adding the binary capture --- .../src/display-plugins/hmd/HmdDisplayPlugin.cpp | 3 ++- libraries/gpu-gl/src/gpu/gl/GLBackend.h | 4 ++-- libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp | 8 +++++--- libraries/gpu-gl/src/gpu/gl/GLShader.cpp | 2 +- libraries/gpu-gl/src/gpu/gl/GLShader.h | 2 +- libraries/gpu-gles/src/gpu/gl/GLBackend.h | 2 +- libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp | 4 ++-- libraries/gpu/src/gpu/Context.h | 2 +- libraries/gpu/src/gpu/null/NullBackend.h | 2 +- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 3 ++- tests/shaders/src/main.cpp | 3 ++- 11 files changed, 20 insertions(+), 15 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index 90bb83a663..b64836627c 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -398,7 +398,8 @@ void HmdDisplayPlugin::HUDRenderer::updatePipeline() { 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()); + // gpu::gl::GLBackend::makeProgram(*program, gpu::Shader::BindingSet()); + gpu::Shader::makeProgram(*program, gpu::Shader::BindingSet()); uniformsLocation = program->getUniformBuffers().findLocation("hudBuffer"); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.h b/libraries/gpu-gl/src/gpu/gl/GLBackend.h index 004bfe1c85..f0b74803e4 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.h @@ -64,7 +64,7 @@ protected: explicit GLBackend(bool syncCache); GLBackend(); public: - static bool makeProgram(Shader& shader, const Shader::BindingSet& slotBindings = Shader::BindingSet(), Shader::CompilationHandler handler = nullptr); + static bool makeProgram(Shader& shader, const Shader::BindingSet& slotBindings, Shader::CompilationHandler handler); virtual ~GLBackend(); @@ -423,7 +423,7 @@ protected: } _pipeline; // Backend dependant compilation of the shader - virtual GLShader* compileBackendProgram(const Shader& program); + virtual GLShader* compileBackendProgram(const Shader& program, Shader::CompilationHandler handler); virtual GLShader* compileBackendShader(const Shader& shader, Shader::CompilationHandler handler); virtual std::string getBackendShaderHeader() const; virtual void makeProgramBindings(ShaderObject& shaderObject); diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp index 84170dbffd..40b9c94610 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp @@ -101,7 +101,7 @@ GLShader* GLBackend::compileBackendShader(const Shader& shader, Shader::Compilat return object; } -GLShader* GLBackend::compileBackendProgram(const Shader& program) { +GLShader* GLBackend::compileBackendProgram(const Shader& program, Shader::CompilationHandler handler) { if (!program.isProgram()) { return nullptr; } @@ -116,11 +116,13 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program) { // Let's go through every shaders and make sure they are ready to go std::vector< GLuint > shaderGLObjects; for (auto subShader : program.getShaders()) { - auto object = GLShader::sync((*this), *subShader); + auto object = GLShader::sync((*this), *subShader, handler); if (object) { shaderGLObjects.push_back(object->_shaderObjects[version].glshader); } else { qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - One of the shaders of the program is not compiled?"; + compilationLogs[version].compiled = false; + compilationLogs[version].message = std::string("Failed to compile, one of the shaders of the program is not compiled ?"); program.setCompilationLogs(compilationLogs); return nullptr; } @@ -132,7 +134,7 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program) { program.setCompilationLogs(compilationLogs); return nullptr; } - + compilationLogs[version].compiled = true; programObject.glprogram = glprogram; makeProgramBindings(programObject); diff --git a/libraries/gpu-gl/src/gpu/gl/GLShader.cpp b/libraries/gpu-gl/src/gpu/gl/GLShader.cpp index a626376e27..42d4fe3845 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLShader.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLShader.cpp @@ -39,7 +39,7 @@ GLShader* GLShader::sync(GLBackend& backend, const Shader& shader, Shader::Compi } // need to have a gpu object? if (shader.isProgram()) { - GLShader* tempObject = backend.compileBackendProgram(shader); + GLShader* tempObject = backend.compileBackendProgram(shader, handler); if (tempObject) { object = tempObject; Backend::setGPUObject(shader, object); diff --git a/libraries/gpu-gl/src/gpu/gl/GLShader.h b/libraries/gpu-gl/src/gpu/gl/GLShader.h index 42d63f8dfb..8625b3e64a 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLShader.h +++ b/libraries/gpu-gl/src/gpu/gl/GLShader.h @@ -22,7 +22,7 @@ struct ShaderObject { class GLShader : public GPUObject { public: static GLShader* sync(GLBackend& backend, const Shader& shader, Shader::CompilationHandler handler = nullptr); - static bool makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings, Shader::CompilationHandler handler = nullptr); + static bool makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings, Shader::CompilationHandler handler); enum Version { Mono = 0, diff --git a/libraries/gpu-gles/src/gpu/gl/GLBackend.h b/libraries/gpu-gles/src/gpu/gl/GLBackend.h index bb8e15bad3..0db46985f7 100644 --- a/libraries/gpu-gles/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gles/src/gpu/gl/GLBackend.h @@ -420,7 +420,7 @@ protected: } _pipeline; // Backend dependant compilation of the shader - virtual GLShader* compileBackendProgram(const Shader& program); + virtual GLShader* compileBackendProgram(const Shader& program, Shader::CompilationHandler handler); virtual GLShader* compileBackendShader(const Shader& shader, Shader::CompilationHandler handler); virtual std::string getBackendShaderHeader() const; virtual void makeProgramBindings(ShaderObject& shaderObject); diff --git a/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp b/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp index 26dbb12cf7..1d7636c159 100644 --- a/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp +++ b/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp @@ -140,7 +140,7 @@ GLShader* GLBackend::compileBackendShader(const Shader& shader, Shader::Compilat return object; } -GLShader* GLBackend::compileBackendProgram(const Shader& program) { +GLShader* GLBackend::compileBackendProgram(const Shader& program, Shader::CompilationHandler handler) { if (!program.isProgram()) { return nullptr; } @@ -155,7 +155,7 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program) { // Let's go through every shaders and make sure they are ready to go std::vector< GLuint > shaderGLObjects; for (auto subShader : program.getShaders()) { - auto object = GLShader::sync((*this), *subShader); + auto object = GLShader::sync((*this), *subShader, handler); if (object) { shaderGLObjects.push_back(object->_shaderObjects[version].glshader); } else { diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 7d04463609..e22cc57570 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -262,7 +262,7 @@ protected: // makeProgramShader(...) make a program shader ready to be used in a Batch. // It compiles the sub shaders, link them and defines the Slots and their bindings. // If the shader passed is not a program, nothing happens. - static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings, Shader::CompilationHandler handler = nullptr); + static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings, Shader::CompilationHandler handler); static CreateBackend _createBackendCallback; static MakeProgram _makeProgramCallback; diff --git a/libraries/gpu/src/gpu/null/NullBackend.h b/libraries/gpu/src/gpu/null/NullBackend.h index c9d249aec7..abaa24812f 100644 --- a/libraries/gpu/src/gpu/null/NullBackend.h +++ b/libraries/gpu/src/gpu/null/NullBackend.h @@ -28,7 +28,7 @@ class Backend : public gpu::Backend { friend class gpu::Context; static void init() {} static gpu::Backend* createBackend() { return new Backend(); } - static bool makeProgram(Shader& shader, const Shader::BindingSet& slotBindings) { return true; } + static bool makeProgram(Shader& shader, const Shader::BindingSet& slotBindings, Shader::CompilationHandler handler) { return true; } protected: explicit Backend(bool syncCache) : Parent() { } diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 4403eaeff7..4b5f0e6517 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -200,9 +200,10 @@ public: std::string fsSource = HMD_REPROJECTION_FRAG; GLuint vertexShader { 0 }, fragmentShader { 0 }; std::string error; + std::vector binary; ::gl::compileShader(GL_VERTEX_SHADER, vsSource, "", vertexShader, error); ::gl::compileShader(GL_FRAGMENT_SHADER, fsSource, "", fragmentShader, error); - _program = ::gl::compileProgram({ { vertexShader, fragmentShader } }, error); + _program = ::gl::compileProgram({ { vertexShader, fragmentShader } }, error, binary); glDeleteShader(vertexShader); glDeleteShader(fragmentShader); qDebug() << "Rebuild proigram"; diff --git a/tests/shaders/src/main.cpp b/tests/shaders/src/main.cpp index cd307ba362..3f48e37a76 100644 --- a/tests/shaders/src/main.cpp +++ b/tests/shaders/src/main.cpp @@ -137,12 +137,13 @@ const std::string PIXEL_SHADER_DEFINES{ R"GLSL( void testShaderBuild(const char* vs_src, const char * fs_src) { std::string error; + std::vector binary; GLuint vs, fs; if (!gl::compileShader(GL_VERTEX_SHADER, vs_src, VERTEX_SHADER_DEFINES, vs, error) || !gl::compileShader(GL_FRAGMENT_SHADER, fs_src, PIXEL_SHADER_DEFINES, fs, error)) { throw std::runtime_error("Failed to compile shader"); } - auto pr = gl::compileProgram({ vs, fs }, error); + auto pr = gl::compileProgram({ vs, fs }, error, binary); if (!pr) { throw std::runtime_error("Failed to link shader"); } From 9ea6c78ac2526faea3035cb52b18a6e9c1993b86 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 30 Jan 2018 15:31:34 -0800 Subject: [PATCH 28/57] fix stupid copy paste --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f1d0378792..3390e71b07 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2283,7 +2283,7 @@ void Application::initializeGL() { #ifdef Q_OS_OSX // FIXME: on mac os the shaders take up to 1 minute to compile, so we pause the deadlock watchdog thread. - +DeadlockWatchdogThread::pause(); + DeadlockWatchdogThread::pause(); #endif // Set up the render engine From 9c81909be55ef6f60da6b5ab6c53c829322c38a7 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 30 Jan 2018 16:42:08 -0800 Subject: [PATCH 29/57] restructures _dirtyFlags name and bits --- .../src/RenderableModelEntityItem.cpp | 2 +- .../src/RenderablePolyVoxEntityItem.cpp | 4 +- libraries/entities/src/EntityItem.cpp | 123 +++++++++++------- libraries/entities/src/EntityItem.h | 10 +- libraries/entities/src/ModelEntityItem.cpp | 20 +-- .../entities/src/ParticleEffectEntityItem.cpp | 2 +- libraries/entities/src/SimulationFlags.h | 4 +- 7 files changed, 97 insertions(+), 68 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 9fcb7640ef..1134c385f2 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1,4 +1,4 @@ -// + // // RenderableModelEntityItem.cpp // interface/src // diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index ade3790df6..abd14d017e 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -99,7 +99,7 @@ const float MARCHING_CUBE_COLLISION_HULL_OFFSET = 0.5; In RenderablePolyVoxEntityItem::render, these flags are checked and changes are propagated along the chain. decompressVolumeData() is called to decompress _voxelData into _volData. recomputeMesh() is called to invoke the - polyVox surface extractor to create _mesh (as well as set Simulation _dirtyFlags). Because Simulation::DIRTY_SHAPE + polyVox surface extractor to create _mesh (as well as set Simulation _flags). Because Simulation::DIRTY_SHAPE is set, isReadyToComputeShape() gets called and _shape is created either from _volData or _shape, depending on the surface style. @@ -1138,7 +1138,7 @@ void RenderablePolyVoxEntityItem::setMesh(graphics::MeshPointer mesh) { bool neighborsNeedUpdate; withWriteLock([&] { if (!_collisionless) { - _dirtyFlags |= Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS; + _flags |= Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS; } _mesh = mesh; _meshDirty = true; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index fe5213baa8..7e227c90d6 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -933,7 +933,7 @@ void EntityItem::setDensity(float density) { withWriteLock([&] { if (_density != clampedDensity) { _density = clampedDensity; - _dirtyFlags |= Simulation::DIRTY_MASS; + _flags |= Simulation::DIRTY_MASS; } }); } @@ -958,7 +958,7 @@ void EntityItem::setMass(float mass) { withWriteLock([&] { if (_density != newDensity) { _density = newDensity; - _dirtyFlags |= Simulation::DIRTY_MASS; + _flags |= Simulation::DIRTY_MASS; } }); } @@ -1623,41 +1623,43 @@ void EntityItem::setParentID(const QUuid& value) { if (!value.isNull() && tree) { EntityItemPointer entity = tree->findEntityByEntityItemID(value); if (entity) { - newParentNoBootstrapping = entity->getDirtyFlags() & Simulation::NO_BOOTSTRAPPING; + newParentNoBootstrapping = entity->getSpecialFlags() & Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING; } } if (!oldParentID.isNull() && tree) { EntityItemPointer entity = tree->findEntityByEntityItemID(oldParentID); if (entity) { - oldParentNoBootstrapping = entity->getDirtyFlags() & Simulation::NO_BOOTSTRAPPING; + oldParentNoBootstrapping = entity->getDirtyFlags() & Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING; } } if (!value.isNull() && (value == Physics::getSessionUUID() || value == AVATAR_SELF_ID)) { - newParentNoBootstrapping |= Simulation::NO_BOOTSTRAPPING; + newParentNoBootstrapping |= Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING; } if (!oldParentID.isNull() && (oldParentID == Physics::getSessionUUID() || oldParentID == AVATAR_SELF_ID)) { - oldParentNoBootstrapping |= Simulation::NO_BOOTSTRAPPING; + oldParentNoBootstrapping |= Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING; } if ((bool)(oldParentNoBootstrapping ^ newParentNoBootstrapping)) { - if ((bool)(newParentNoBootstrapping & Simulation::NO_BOOTSTRAPPING)) { - markDirtyFlags(Simulation::NO_BOOTSTRAPPING); - forEachDescendant([&](SpatiallyNestablePointer object) { - if (object->getNestableType() == NestableType::Entity) { - EntityItemPointer entity = std::static_pointer_cast(object); - entity->markDirtyFlags(Simulation::DIRTY_COLLISION_GROUP | Simulation::NO_BOOTSTRAPPING); - } - }); - } else { - clearDirtyFlags(Simulation::NO_BOOTSTRAPPING); + if ((bool)(newParentNoBootstrapping & Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING)) { + markSpecialFlags(Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING); + qDebug() << "setParentID" << QString::fromStdString(std::bitset<32>(_flags).to_string()) << " <--------"; forEachDescendant([&](SpatiallyNestablePointer object) { if (object->getNestableType() == NestableType::Entity) { EntityItemPointer entity = std::static_pointer_cast(object); entity->markDirtyFlags(Simulation::DIRTY_COLLISION_GROUP); - entity->clearDirtyFlags(Simulation::NO_BOOTSTRAPPING); + entity->markSpecialFlags(Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING); + } + }); + } else { + clearSpecialFlags(Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING); + forEachDescendant([&](SpatiallyNestablePointer object) { + if (object->getNestableType() == NestableType::Entity) { + EntityItemPointer entity = std::static_pointer_cast(object); + entity->markDirtyFlags(Simulation::DIRTY_COLLISION_GROUP); + entity->clearSpecialFlags(Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING); } }); } @@ -1694,7 +1696,7 @@ void EntityItem::setUnscaledDimensions(const glm::vec3& value) { locationChanged(); dimensionsChanged(); withWriteLock([&] { - _dirtyFlags |= (Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS); + _flags |= (Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS); _queryAACubeSet = false; }); } @@ -1703,7 +1705,7 @@ void EntityItem::setUnscaledDimensions(const glm::vec3& value) { void EntityItem::setRotation(glm::quat rotation) { if (getLocalOrientation() != rotation) { setLocalOrientation(rotation); - _dirtyFlags |= Simulation::DIRTY_ROTATION; + _flags |= Simulation::DIRTY_ROTATION; forEachDescendant([&](SpatiallyNestablePointer object) { if (object->getNestableType() == NestableType::Entity) { EntityItemPointer entity = std::static_pointer_cast(object); @@ -1733,7 +1735,7 @@ void EntityItem::setVelocity(const glm::vec3& value) { velocity = value; } setLocalVelocity(velocity); - _dirtyFlags |= Simulation::DIRTY_LINEAR_VELOCITY; + _flags |= Simulation::DIRTY_LINEAR_VELOCITY; } } } @@ -1744,7 +1746,7 @@ void EntityItem::setDamping(float value) { withWriteLock([&] { if (_damping != clampedDamping) { _damping = clampedDamping; - _dirtyFlags |= Simulation::DIRTY_MATERIAL; + _flags |= Simulation::DIRTY_MATERIAL; } }); } @@ -1763,7 +1765,7 @@ void EntityItem::setGravity(const glm::vec3& value) { } else { _gravity = value; } - _dirtyFlags |= Simulation::DIRTY_LINEAR_VELOCITY; + _flags |= Simulation::DIRTY_LINEAR_VELOCITY; } } } @@ -1788,7 +1790,7 @@ void EntityItem::setAngularVelocity(const glm::vec3& value) { angularVelocity = value; } setLocalAngularVelocity(angularVelocity); - _dirtyFlags |= Simulation::DIRTY_ANGULAR_VELOCITY; + _flags |= Simulation::DIRTY_ANGULAR_VELOCITY; } } } @@ -1799,7 +1801,7 @@ void EntityItem::setAngularDamping(float value) { withWriteLock([&] { if (_angularDamping != clampedDamping) { _angularDamping = clampedDamping; - _dirtyFlags |= Simulation::DIRTY_MATERIAL; + _flags |= Simulation::DIRTY_MATERIAL; } }); } @@ -1808,7 +1810,7 @@ void EntityItem::setCollisionless(bool value) { withWriteLock([&] { if (_collisionless != value) { _collisionless = value; - _dirtyFlags |= Simulation::DIRTY_COLLISION_GROUP; + _flags |= Simulation::DIRTY_COLLISION_GROUP; } }); } @@ -1817,7 +1819,7 @@ void EntityItem::setCollisionMask(uint8_t value) { withWriteLock([&] { if ((_collisionMask & ENTITY_COLLISION_MASK_DEFAULT) != (value & ENTITY_COLLISION_MASK_DEFAULT)) { _collisionMask = (value & ENTITY_COLLISION_MASK_DEFAULT); - _dirtyFlags |= Simulation::DIRTY_COLLISION_GROUP; + _flags |= Simulation::DIRTY_COLLISION_GROUP; } }); } @@ -1829,11 +1831,11 @@ void EntityItem::setDynamic(bool value) { if (value && getShapeType() == SHAPE_TYPE_STATIC_MESH) { if (_dynamic) { _dynamic = false; - _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; + _flags |= Simulation::DIRTY_MOTION_TYPE; } } else { _dynamic = value; - _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; + _flags |= Simulation::DIRTY_MOTION_TYPE; } }); } @@ -1844,7 +1846,7 @@ void EntityItem::setRestitution(float value) { withWriteLock([&] { if (_restitution != clampedValue) { _restitution = clampedValue; - _dirtyFlags |= Simulation::DIRTY_MATERIAL; + _flags |= Simulation::DIRTY_MATERIAL; } }); @@ -1855,7 +1857,7 @@ void EntityItem::setFriction(float value) { withWriteLock([&] { if (_friction != clampedValue) { _friction = clampedValue; - _dirtyFlags |= Simulation::DIRTY_MATERIAL; + _flags |= Simulation::DIRTY_MATERIAL; } }); } @@ -1864,7 +1866,7 @@ void EntityItem::setLifetime(float value) { withWriteLock([&] { if (_lifetime != value) { _lifetime = value; - _dirtyFlags |= Simulation::DIRTY_LIFETIME; + _flags |= Simulation::DIRTY_LIFETIME; } }); } @@ -1873,7 +1875,7 @@ void EntityItem::setCreated(quint64 value) { withWriteLock([&] { if (_created != value) { _created = value; - _dirtyFlags |= Simulation::DIRTY_LIFETIME; + _flags |= Simulation::DIRTY_LIFETIME; } }); } @@ -1902,7 +1904,7 @@ void EntityItem::computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask } } - if ((bool)(_dirtyFlags & Simulation::NO_BOOTSTRAPPING)) { + if ((bool)(_flags & Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING)) { userMask &= ~USER_COLLISION_GROUP_MY_AVATAR; } mask = Physics::getDefaultCollisionMask(group) & (int16_t)(userMask); @@ -1997,17 +1999,18 @@ bool EntityItem::addActionInternal(EntitySimulationPointer simulation, EntityDyn serializeActions(success, newDataCache); if (success) { _allActionsDataCache = newDataCache; - _dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION; + _flags |= Simulation::DIRTY_PHYSICS_ACTIVATION; auto actionType = action->getType(); if (actionType == DYNAMIC_TYPE_HOLD || actionType == DYNAMIC_TYPE_FAR_GRAB) { - if (!(bool)(_dirtyFlags & Simulation::NO_BOOTSTRAPPING)) { - _dirtyFlags |= Simulation::NO_BOOTSTRAPPING; - _dirtyFlags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar + if (!(bool)(_flags & Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING)) { + _flags |= Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING; + _flags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar forEachDescendant([&](SpatiallyNestablePointer child) { if (child->getNestableType() == NestableType::Entity) { EntityItemPointer entity = std::static_pointer_cast(child); - entity->markDirtyFlags(Simulation::NO_BOOTSTRAPPING | Simulation::DIRTY_COLLISION_GROUP); + entity->markDirtyFlags(Simulation::DIRTY_COLLISION_GROUP); + entity->markSpecialFlags(Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING); } }); } @@ -2033,7 +2036,7 @@ bool EntityItem::updateAction(EntitySimulationPointer simulation, const QUuid& a if (success) { action->setIsMine(true); serializeActions(success, _allActionsDataCache); - _dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION; + _flags |= Simulation::DIRTY_PHYSICS_ACTIVATION; } else { qCDebug(entities) << "EntityItem::updateAction failed"; } @@ -2091,17 +2094,17 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulationPoi _objectActions.remove(actionID); if ((removedActionType == DYNAMIC_TYPE_HOLD || removedActionType == DYNAMIC_TYPE_FAR_GRAB) && !stillHasGrabActions()) { - _dirtyFlags &= ~Simulation::NO_BOOTSTRAPPING; - _dirtyFlags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar + _flags &= ~Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING; + _flags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar forEachDescendant([&](SpatiallyNestablePointer child) { if (child->getNestableType() == NestableType::Entity) { EntityItemPointer entity = std::static_pointer_cast(child); entity->markDirtyFlags(Simulation::DIRTY_COLLISION_GROUP); - entity->clearDirtyFlags(Simulation::NO_BOOTSTRAPPING); + entity->clearSpecialFlags(Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING); } }); } else { - // NO-OP: we assume NO_BOOTSTRAPPING bits and collision group are correct + // NO-OP: we assume SPECIAL_FLAGS_NO_BOOTSTRAPPING bits and collision group are correct // because they should have been set correctly when the action was added // and/or when children were linked } @@ -2112,7 +2115,7 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulationPoi bool success = true; serializeActions(success, _allActionsDataCache); - _dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION; + _flags |= Simulation::DIRTY_PHYSICS_ACTIVATION; setDynamicDataNeedsTransmit(true); return success; } @@ -2132,8 +2135,8 @@ bool EntityItem::clearActions(EntitySimulationPointer simulation) { // empty _serializedActions means no actions for the EntityItem _actionsToRemove.clear(); _allActionsDataCache.clear(); - _dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION; - _dirtyFlags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar + _flags |= Simulation::DIRTY_PHYSICS_ACTIVATION; + _flags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar }); return true; } @@ -2364,7 +2367,7 @@ QList EntityItem::getActionsOfType(EntityDynamicType typeT void EntityItem::locationChanged(bool tellPhysics) { requiresRecalcBoxes(); if (tellPhysics) { - _dirtyFlags |= Simulation::DIRTY_TRANSFORM; + _flags |= Simulation::DIRTY_TRANSFORM; EntityTreePointer tree = getTree(); if (tree) { tree->entityChanged(getThisPointer()); @@ -2832,7 +2835,7 @@ DEFINE_PROPERTY_ACCESSOR(quint32, StaticCertificateVersion, staticCertificateVer uint32_t EntityItem::getDirtyFlags() const { uint32_t result; withReadLock([&] { - result = _dirtyFlags; + result = _flags; }); return result; } @@ -2840,13 +2843,33 @@ uint32_t EntityItem::getDirtyFlags() const { void EntityItem::markDirtyFlags(uint32_t mask) { withWriteLock([&] { - _dirtyFlags |= mask; + _flags |= mask; }); } void EntityItem::clearDirtyFlags(uint32_t mask) { withWriteLock([&] { - _dirtyFlags &= ~mask; + _flags &= ~mask; + }); +} + +uint32_t EntityItem::getSpecialFlags() const { + uint32_t result; + withReadLock([&] { + result = _flags; + }); + return result; +} + +void EntityItem::markSpecialFlags(uint32_t mask) { + withWriteLock([&] { + _flags |= mask; + }); +} + +void EntityItem::clearSpecialFlags(uint32_t mask) { + withWriteLock([&] { + _flags &= ~mask; }); } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 4c398b8a29..fb0f36c4d6 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -358,7 +358,11 @@ public: uint32_t getDirtyFlags() const; void markDirtyFlags(uint32_t mask); - void clearDirtyFlags(uint32_t mask = 0xffffffff); + void clearDirtyFlags(uint32_t mask = 0x0000ffff); + + uint32_t getSpecialFlags() const; + void markSpecialFlags(uint32_t mask); + void clearSpecialFlags(uint32_t mask = 0xffff0000); bool isMoving() const; bool isMovingRelativeToParent() const; @@ -385,7 +389,7 @@ public: void getAllTerseUpdateProperties(EntityItemProperties& properties) const; void flagForOwnershipBid(uint8_t priority); - void flagForMotionStateChange() { _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; } + void flagForMotionStateChange() { _flags |= Simulation::DIRTY_MOTION_TYPE; } QString actionsToDebugString(); bool addAction(EntitySimulationPointer simulation, EntityDynamicPointer action); @@ -572,7 +576,7 @@ protected: // // DirtyFlags are set whenever a property changes that the EntitySimulation needs to know about. - uint32_t _dirtyFlags { 0 }; // things that have changed from EXTERNAL changes (via script or packet) but NOT from simulation + uint32_t _flags { 0 }; // things that have changed from EXTERNAL changes (via script or packet) but NOT from simulation // these backpointers are only ever set/cleared by friends: EntityTreeElementPointer _element; // set by EntityTreeElement diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index a615beefa9..5d33e4c047 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -85,7 +85,7 @@ bool ModelEntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChangedInAnimations = _animationProperties.setProperties(properties); if (somethingChangedInAnimations) { - _dirtyFlags |= Simulation::DIRTY_UPDATEABLE; + _flags |= Simulation::DIRTY_UPDATEABLE; } somethingChanged = somethingChanged || somethingChangedInAnimations; @@ -132,7 +132,7 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, setShapeType); if (animationPropertiesChanged) { - _dirtyFlags |= Simulation::DIRTY_UPDATEABLE; + _flags |= Simulation::DIRTY_UPDATEABLE; somethingChanged = true; } @@ -305,10 +305,10 @@ void ModelEntityItem::setShapeType(ShapeType type) { // dynamic and STATIC_MESH are incompatible // since the shape is being set here we clear the dynamic bit _dynamic = false; - _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; + _flags |= Simulation::DIRTY_MOTION_TYPE; } _shapeType = type; - _dirtyFlags |= Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS; + _flags |= Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS; } }); } @@ -336,7 +336,7 @@ void ModelEntityItem::setModelURL(const QString& url) { if (_modelURL != url) { _modelURL = url; if (_shapeType == SHAPE_TYPE_STATIC_MESH) { - _dirtyFlags |= Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS; + _flags |= Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS; } } }); @@ -348,14 +348,14 @@ void ModelEntityItem::setCompoundShapeURL(const QString& url) { ShapeType oldType = computeTrueShapeType(); _compoundShapeURL.set(url); if (oldType != computeTrueShapeType()) { - _dirtyFlags |= Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS; + _flags |= Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS; } } }); } void ModelEntityItem::setAnimationURL(const QString& url) { - _dirtyFlags |= Simulation::DIRTY_UPDATEABLE; + _flags |= Simulation::DIRTY_UPDATEABLE; withWriteLock([&] { _animationProperties.setURL(url); }); @@ -422,16 +422,16 @@ void ModelEntityItem::setAnimationSettings(const QString& value) { bool allowTranslation = settingsMap["allowTranslation"].toBool(); setAnimationAllowTranslation(allowTranslation); } - _dirtyFlags |= Simulation::DIRTY_UPDATEABLE; + _flags |= Simulation::DIRTY_UPDATEABLE; } void ModelEntityItem::setAnimationIsPlaying(bool value) { - _dirtyFlags |= Simulation::DIRTY_UPDATEABLE; + _flags |= Simulation::DIRTY_UPDATEABLE; _animationProperties.setRunning(value); } void ModelEntityItem::setAnimationFPS(float value) { - _dirtyFlags |= Simulation::DIRTY_UPDATEABLE; + _flags |= Simulation::DIRTY_UPDATEABLE; _animationProperties.setFPS(value); } diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index c20572a491..7d27011c56 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -601,7 +601,7 @@ void ParticleEffectEntityItem::setShapeType(ShapeType type) { withWriteLock([&] { if (type != _shapeType) { _shapeType = type; - _dirtyFlags |= Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS; + _flags |= Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS; } }); } diff --git a/libraries/entities/src/SimulationFlags.h b/libraries/entities/src/SimulationFlags.h index aaa92000e7..6f305ef1ff 100644 --- a/libraries/entities/src/SimulationFlags.h +++ b/libraries/entities/src/SimulationFlags.h @@ -27,7 +27,9 @@ namespace Simulation { const uint32_t DIRTY_PHYSICS_ACTIVATION = 0x0800; // should activate object in physics engine const uint32_t DIRTY_SIMULATOR_ID = 0x1000; // the simulatorID has changed const uint32_t DIRTY_SIMULATION_OWNERSHIP_PRIORITY = 0x2000; // our own bid priority has changed - const uint32_t NO_BOOTSTRAPPING = 0x4000; + + + const uint32_t SPECIAL_FLAGS_NO_BOOTSTRAPPING = 0x10000; const uint32_t DIRTY_TRANSFORM = DIRTY_POSITION | DIRTY_ROTATION; const uint32_t DIRTY_VELOCITIES = DIRTY_LINEAR_VELOCITY | DIRTY_ANGULAR_VELOCITY; From 63371ff59c129184970435255ab2cc003bf85331 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 30 Jan 2018 17:17:22 -0800 Subject: [PATCH 30/57] Fix the android build --- .../gpu-gles/src/gpu/gl/GLBackendShader.cpp | 35 ------------------- 1 file changed, 35 deletions(-) diff --git a/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp b/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp index 1d7636c159..350e95b46a 100644 --- a/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp +++ b/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp @@ -56,41 +56,6 @@ static const std::array VERSION_DEFINES { { stereoVersion } }; -GLShader* GLBackend::compileBackendShader(const Shader& shader, Shader::CompilationHandler handler) { - // Any GLSLprogram ? normally yes... - const std::string& shaderSource = shader.getSource().getCode(); - GLenum shaderDomain = SHADER_DOMAINS[shader.getType()]; - GLShader::ShaderObjects shaderObjects; - Shader::CompilationLogs compilationLogs(GLShader::NumVersions); - - for (int version = 0; version < GLShader::NumVersions; version++) { - auto& shaderObject = shaderObjects[version]; - - std::string shaderDefines = getBackendShaderHeader() + "\n" + DOMAIN_DEFINES[shader.getType()] + "\n" + VERSION_DEFINES[version] - + "\n#extension GL_EXT_texture_buffer : enable" - + "\nprecision lowp float; // check precision 2" - + "\nprecision lowp samplerBuffer;" - + "\nprecision lowp sampler2DShadow;"; - std::string error; - -#ifdef SEPARATE_PROGRAM - bool result = ::gl::compileShader(shaderDomain, shaderSource, shaderDefines, shaderObject.glshader, shaderObject.glprogram, error); -#else - bool result = ::gl::compileShader(shaderDomain, shaderSource, shaderDefines, shaderObject.glshader, error); -#endif - if (!result) { - qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - Shader didn't compile:\n" << error.c_str(); - return nullptr; - } - } - - // So far so good, the shader is created successfully - GLShader* object = new GLShader(this->shared_from_this()); - object->_shaderObjects = shaderObjects; - - return object; -} - GLShader* GLBackend::compileBackendShader(const Shader& shader, Shader::CompilationHandler handler) { // Any GLSLprogram ? normally yes... const std::string& shaderSource = shader.getSource().getCode(); From 05fe33e417b6d2c9097ec6902305ae90404ea59c Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 30 Jan 2018 18:01:46 -0800 Subject: [PATCH 31/57] Initial work --- .../commerce/wallet/sendMoney/SendMoney.qml | 25 +++++- scripts/system/commerce/wallet.js | 81 +++++++++++++++++++ 2 files changed, 104 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml index f66781c919..ea1c6670e9 100644 --- a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml +++ b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml @@ -308,6 +308,22 @@ Item { } } } + + // "Particle" button + HifiControlsUit.Button { + id: particle; + color: hifi.buttons.blue; + colorScheme: hifi.colorSchemes.dark; + anchors.horizontalCenter: parent.horizontalCenter; + anchors.top: nearbyButton.bottom; + anchors.topMargin: 24; + height: 50; + width: 160; + text: "Try Particles"; + onClicked: { + sendSignalToWallet({method: 'sendMoney_sendPublicly', recipient: "{d90f0952-20c0-46b7-8851-92184db83e1f}", amount: 2}); + } + } } } // Send Money Home END @@ -967,7 +983,7 @@ Item { HifiControlsUit.CheckBox { id: sendPubliclyCheckbox; - visible: false; // FIXME ONCE PARTICLE EFFECTS ARE IN + visible: true; text: "Send Publicly" // Anchors anchors.top: messageContainer.bottom; @@ -1035,7 +1051,11 @@ Item { if (sendMoneyStep.referrer === "connections") { Commerce.transferHfcToUsername(sendMoneyStep.selectedRecipientUserName, parseInt(amountTextField.text), optionalMessage.text); } else if (sendMoneyStep.referrer === "nearby") { - Commerce.transferHfcToNode(sendMoneyStep.selectedRecipientNodeID, parseInt(amountTextField.text), optionalMessage.text); + var transferAmount = parseInt(amountTextField.text); + Commerce.transferHfcToNode(sendMoneyStep.selectedRecipientNodeID, transferAmount, optionalMessage.text); + if (sendPubliclyCheckbox.checked) { + sendSignalToWallet({method: 'sendMoney_sendPublicly', recipient: sendMoneyStep.selectedRecipientNodeID, amount: transferAmount}); + } } } } @@ -1533,6 +1553,7 @@ Item { sendMoneyStep.selectedRecipientProfilePic = ""; amountTextField.text = ""; optionalMessage.text = ""; + sendPubliclyCheckbox.checked = false; } // diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index ad864622ed..c1fae4715d 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -527,6 +527,69 @@ // //*********************************************** + var sendMoneyParticleEffectUpdateTimer; + var sendMoneyParticleEffectDeleteTimer; + var sendMoneyParticleEffect; + var SEND_MONEY_PARTICLE_TIMER_UPDATE = 250; + var SEND_MONEY_PARTICLE_TIMER_TIMEOUT = 4000; + var SEND_MONEY_PARTICLE_PROPERTIES = { + accelerationSpread: { x: 0, y: 0, z: 0 }, + alpha: 1, + alphaFinish: 1, + alphaSpread: 0, + alphaStart: 1, + azimuthFinish: 0, + azimuthStart: -6, + color: { red: 143, green: 5, blue: 255 }, + colorFinish: { red: 255, green: 0, blue: 204 }, + colorSpread: { red: 0, green: 0, blue: 0 }, + colorStart: { red: 0, green: 136, blue: 255 }, + emitAcceleration: { x: 0, y: -3, z: 0 }, + emitDimensions: { x: 0, y: 0, z: 0 }, + emitOrientation: { x: 0, y: 0, z: 0 }, + emitRate: 4.5, + emitSpeed: 2.1, + emitterShouldTrail: true, + isEmitting: 1, + lifespan: 3, + lifetime: 15, + maxParticles: 10, + name: 'hfc-particles', + particleRadius: 0.2, + polarFinish: 0, + polarStart: 0, + radiusFinish: 0, + radiusSpread: 0, + radiusStart: 0, + speedSpread: 0, + textures: "http://hifi-content.s3.amazonaws.com/alan/dev/Particles/Bokeh-Particle-HFC.png", + type: 'ParticleEffect' + }; + + function updateSendMoneyParticleEffect() { + if (sendMoneyParticleEffect) { + var accel = Vec3.subtract(AvatarList.getAvatar(recipient).position, MyAvatar.position); + accel.y -= 3.0; + Entities.editEntity(sendMoneyParticleEffect, { + emitAcceleration: accel + }); + } + } + + function deleteSendMoneyParticleEffect() { + if (sendMoneyParticleEffectDeleteTimer) { + Script.clearTimeout(sendMoneyParticleEffectDeleteTimer); + sendMoneyParticleEffectDeleteTimer = null; + } + if (sendMoneyParticleEffectUpdateTimer) { + Script.clearInterval(sendMoneyParticleEffectUpdateTimer); + sendMoneyParticleEffectUpdateTimer = null; + } + if (sendMoneyParticleEffect) { + sendMoneyParticleEffect = Entities.deleteEntity(sendMoneyParticleEffect); + } + } + // Function Name: fromQml() // // Description: @@ -534,6 +597,7 @@ // in the format "{method, params}", like json-rpc. See also sendToQml(). var isHmdPreviewDisabled = true; var MARKETPLACES_INJECT_SCRIPT_URL = Script.resolvePath("../html/js/marketplacesInject.js"); + function fromQml(message) { switch (message.method) { case 'passphrasePopup_cancelClicked': @@ -605,6 +669,22 @@ } removeOverlays(); break; + case 'sendMoney_sendPublicly': + var recipient = message.recipient; + var amount = message.amount; + var props = SEND_MONEY_PARTICLE_PROPERTIES; + if (sendMoneyParticleEffect) { + deleteSendMoneyParticleEffect(); + } + props.parentID = MyAvatar.sessionUUID; + props.emitAcceleration = Vec3.subtract(AvatarList.getAvatar(recipient).position, MyAvatar.position); + props.emitAcceleration.y -= 3.0; + props.position = MyAvatar.position; + props.position.y += 0.2; + sendMoneyParticleEffect = Entities.addEntity(props, true); + sendMoneyParticleEffectUpdateTimer = Script.setInterval(updateSendMoneyParticleEffect, SEND_MONEY_PARTICLE_TIMER_UPDATE); + sendMoneyParticleEffectDeleteTimer = Script.setTimeout(deleteSendMoneyParticleEffect, SEND_MONEY_PARTICLE_TIMER_TIMEOUT); + break; default: print('Unrecognized message from QML:', JSON.stringify(message)); } @@ -706,6 +786,7 @@ function shutdown() { button.clicked.disconnect(onButtonClicked); tablet.removeButton(button); + deleteSendMoneyParticleEffect(); if (tablet) { tablet.screenChanged.disconnect(onTabletScreenChanged); if (onWalletScreen) { From f044cf76d6a35b65733fc20c54810042d6f6c8a5 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 30 Jan 2018 18:31:30 -0800 Subject: [PATCH 32/57] add the count of compilations of shaders to avoid recompiling them if ot needed --- .../src/display-plugins/hmd/HmdDisplayPlugin.cpp | 1 - libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp | 2 ++ libraries/gpu/src/gpu/Shader.cpp | 4 ++++ libraries/gpu/src/gpu/Shader.h | 4 ++++ libraries/render/src/render/ShapePipeline.cpp | 2 +- 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index b64836627c..d35d5c5317 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -398,7 +398,6 @@ void HmdDisplayPlugin::HUDRenderer::updatePipeline() { 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()); gpu::Shader::makeProgram(*program, gpu::Shader::BindingSet()); uniformsLocation = program->getUniformBuffers().findLocation("hudBuffer"); diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp index 40b9c94610..e9d23b543f 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp @@ -62,6 +62,7 @@ GLShader* GLBackend::compileBackendShader(const Shader& shader, Shader::Compilat GLenum shaderDomain = SHADER_DOMAINS[shader.getType()]; GLShader::ShaderObjects shaderObjects; Shader::CompilationLogs compilationLogs(GLShader::NumVersions); + shader.incrementCompilationAttempt(); for (int version = 0; version < GLShader::NumVersions; version++) { auto& shaderObject = shaderObjects[version]; @@ -108,6 +109,7 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program, Shader::Compil GLShader::ShaderObjects programObjects; + program.incrementCompilationAttempt(); Shader::CompilationLogs compilationLogs(GLShader::NumVersions); for (int version = 0; version < GLShader::NumVersions; version++) { diff --git a/libraries/gpu/src/gpu/Shader.cpp b/libraries/gpu/src/gpu/Shader.cpp index 35c9ad8ae2..b6b90e98fa 100755 --- a/libraries/gpu/src/gpu/Shader.cpp +++ b/libraries/gpu/src/gpu/Shader.cpp @@ -95,3 +95,7 @@ void Shader::setCompilationLogs(const CompilationLogs& logs) const { _compilationLogs.emplace_back(CompilationLog(log)); } } + +void Shader::incrementCompilationAttempt() const { + _numCompilationAttempts++; +} \ No newline at end of file diff --git a/libraries/gpu/src/gpu/Shader.h b/libraries/gpu/src/gpu/Shader.h index d78077a396..a489146e36 100755 --- a/libraries/gpu/src/gpu/Shader.h +++ b/libraries/gpu/src/gpu/Shader.h @@ -185,10 +185,12 @@ public: // Check the compilation state bool compilationHasFailed() const { return _compilationHasFailed; } const CompilationLogs& getCompilationLogs() const { return _compilationLogs; } + uint32_t getNumCompilationAttempts() const { return _numCompilationAttempts; } // Set COmpilation logs can only be called by the Backend layers void setCompilationHasFailed(bool compilationHasFailed) { _compilationHasFailed = compilationHasFailed; } void setCompilationLogs(const CompilationLogs& logs) const; + void incrementCompilationAttempt() const; const GPUObjectPointer gpuObject {}; @@ -219,6 +221,8 @@ protected: // The type of the shader, the master key Type _type; + // Number of attempts to compile the shader + mutable uint32_t _numCompilationAttempts{ 0 }; // Compilation logs (one for each versions generated) mutable CompilationLogs _compilationLogs; diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index 597a6a0fab..a6d73897ae 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -72,7 +72,7 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p BatchSetter batchSetter, ItemSetter itemSetter) { ShapeKey key{ filter._flags }; - if (program->getInputs().empty()) { + if (program->getNumCompilationAttempts() < 1) { gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("lightingModelBuffer"), Slot::BUFFER::LIGHTING_MODEL)); slotBindings.insert(gpu::Shader::Binding(std::string("skinClusterBuffer"), Slot::BUFFER::SKINNING)); From 4429be23c0ca70e368d037d9e7f068c7f306003d Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 31 Jan 2018 09:13:11 -0800 Subject: [PATCH 33/57] add comment --- libraries/entities/src/SimulationFlags.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/SimulationFlags.h b/libraries/entities/src/SimulationFlags.h index 6f305ef1ff..da82916fe3 100644 --- a/libraries/entities/src/SimulationFlags.h +++ b/libraries/entities/src/SimulationFlags.h @@ -28,7 +28,7 @@ namespace Simulation { const uint32_t DIRTY_SIMULATOR_ID = 0x1000; // the simulatorID has changed const uint32_t DIRTY_SIMULATION_OWNERSHIP_PRIORITY = 0x2000; // our own bid priority has changed - + // bits 17-32 are reservied for special flags const uint32_t SPECIAL_FLAGS_NO_BOOTSTRAPPING = 0x10000; const uint32_t DIRTY_TRANSFORM = DIRTY_POSITION | DIRTY_ROTATION; From c3b8565dea5f26035f0a98ac4fe049715fa1dc78 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 31 Jan 2018 09:23:00 -0800 Subject: [PATCH 34/57] min diff --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 1134c385f2..9fcb7640ef 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1,4 +1,4 @@ - // +// // RenderableModelEntityItem.cpp // interface/src // From 9ff6e079ee7d4bcf2fab2261bd557140dfad4a4d Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 31 Jan 2018 10:09:23 -0800 Subject: [PATCH 35/57] fix functions --- libraries/entities/src/EntityItem.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 7e227c90d6..79f9f97aa4 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2835,7 +2835,7 @@ DEFINE_PROPERTY_ACCESSOR(quint32, StaticCertificateVersion, staticCertificateVer uint32_t EntityItem::getDirtyFlags() const { uint32_t result; withReadLock([&] { - result = _flags; + result = _flags & 0x0000ffff; }); return result; } @@ -2843,12 +2843,14 @@ uint32_t EntityItem::getDirtyFlags() const { void EntityItem::markDirtyFlags(uint32_t mask) { withWriteLock([&] { + mask &= 0x0000ffff; _flags |= mask; }); } void EntityItem::clearDirtyFlags(uint32_t mask) { withWriteLock([&] { + mask &= 0x0000ffff; _flags &= ~mask; }); } @@ -2856,19 +2858,21 @@ void EntityItem::clearDirtyFlags(uint32_t mask) { uint32_t EntityItem::getSpecialFlags() const { uint32_t result; withReadLock([&] { - result = _flags; + result = _flags & 0xffff0000; }); return result; } void EntityItem::markSpecialFlags(uint32_t mask) { withWriteLock([&] { + mask &= 0xffff0000; _flags |= mask; }); } void EntityItem::clearSpecialFlags(uint32_t mask) { withWriteLock([&] { + mask &= 0xffff0000; _flags &= ~mask; }); } From 01f8227fa25cc2cddd49dcf11e940a475223d17b Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 31 Jan 2018 10:41:08 -0800 Subject: [PATCH 36/57] remove stray prints --- libraries/entities/src/EntityItem.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 79f9f97aa4..ac349ad74d 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1645,7 +1645,6 @@ void EntityItem::setParentID(const QUuid& value) { if ((bool)(oldParentNoBootstrapping ^ newParentNoBootstrapping)) { if ((bool)(newParentNoBootstrapping & Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING)) { markSpecialFlags(Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING); - qDebug() << "setParentID" << QString::fromStdString(std::bitset<32>(_flags).to_string()) << " <--------"; forEachDescendant([&](SpatiallyNestablePointer object) { if (object->getNestableType() == NestableType::Entity) { EntityItemPointer entity = std::static_pointer_cast(object); From 90c2371f0c7086b03c74e02d38919fb66b302218 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 31 Jan 2018 12:09:23 -0800 Subject: [PATCH 37/57] It's working! --- .../commerce/wallet/sendMoney/SendMoney.qml | 2 +- scripts/system/commerce/wallet.js | 52 +++++++++++-------- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml index ea1c6670e9..63acf6bac8 100644 --- a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml +++ b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml @@ -321,7 +321,7 @@ Item { width: 160; text: "Try Particles"; onClicked: { - sendSignalToWallet({method: 'sendMoney_sendPublicly', recipient: "{d90f0952-20c0-46b7-8851-92184db83e1f}", amount: 2}); + sendSignalToWallet({method: 'sendMoney_sendPublicly', recipient: "{09f76bc2-c108-41e9-9a94-18bbda228ed2}", amount: 2}); } } } diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index 939034ec6c..4e49ee324f 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -527,11 +527,13 @@ // //*********************************************** + var sendMoneyRecipient; var sendMoneyParticleEffectUpdateTimer; - var sendMoneyParticleEffectDeleteTimer; + var particleEffectTimestamp; var sendMoneyParticleEffect; var SEND_MONEY_PARTICLE_TIMER_UPDATE = 250; - var SEND_MONEY_PARTICLE_TIMER_TIMEOUT = 4000; + var SEND_MONEY_PARTICLE_EMITTING_DURATION = 3000; + var SEND_MONEY_PARTICLE_LIFETIME_SECONDS = 8; var SEND_MONEY_PARTICLE_PROPERTIES = { accelerationSpread: { x: 0, y: 0, z: 0 }, alpha: 1, @@ -544,43 +546,51 @@ colorFinish: { red: 255, green: 0, blue: 204 }, colorSpread: { red: 0, green: 0, blue: 0 }, colorStart: { red: 0, green: 136, blue: 255 }, - emitAcceleration: { x: 0, y: -3, z: 0 }, + emitAcceleration: { x: 0, y: 0, z: 0 }, // Immediately gets updated to be accurate emitDimensions: { x: 0, y: 0, z: 0 }, emitOrientation: { x: 0, y: 0, z: 0 }, - emitRate: 4.5, + emitRate: 4, emitSpeed: 2.1, emitterShouldTrail: true, isEmitting: 1, - lifespan: 3, - lifetime: 15, - maxParticles: 10, + lifespan: SEND_MONEY_PARTICLE_LIFETIME_SECONDS + 1, // Immediately gets updated to be accurate + lifetime: SEND_MONEY_PARTICLE_LIFETIME_SECONDS + 1, + maxParticles: 20, name: 'hfc-particles', particleRadius: 0.2, polarFinish: 0, polarStart: 0, - radiusFinish: 0, + radiusFinish: 0.05, radiusSpread: 0, - radiusStart: 0, + radiusStart: 0.2, speedSpread: 0, textures: "http://hifi-content.s3.amazonaws.com/alan/dev/Particles/Bokeh-Particle-HFC.png", type: 'ParticleEffect' }; function updateSendMoneyParticleEffect() { - if (sendMoneyParticleEffect) { - var accel = Vec3.subtract(AvatarList.getAvatar(recipient).position, MyAvatar.position); - accel.y -= 3.0; + var timestampNow = Date.now(); + if ((timestampNow - particleEffectTimestamp) > (SEND_MONEY_PARTICLE_LIFETIME_SECONDS * 1000)) { + deleteSendMoneyParticleEffect(); + return; + } else if ((timestampNow - particleEffectTimestamp) > SEND_MONEY_PARTICLE_EMITTING_DURATION) { Entities.editEntity(sendMoneyParticleEffect, { - emitAcceleration: accel + isEmitting: 0 + }); + } else if (sendMoneyParticleEffect) { + var recipientPosition = AvatarList.getAvatar(sendMoneyRecipient).position; + var distance = Vec3.distance(recipientPosition, MyAvatar.position); + var accel = Vec3.subtract(recipientPosition, MyAvatar.position); + accel.y -= 3.0; + var life = Math.sqrt(2 * distance / Vec3.length(accel)); + Entities.editEntity(sendMoneyParticleEffect, { + emitAcceleration: accel, + lifespan: life }); } } function deleteSendMoneyParticleEffect() { - if (sendMoneyParticleEffectDeleteTimer) { - Script.clearTimeout(sendMoneyParticleEffectDeleteTimer); - sendMoneyParticleEffectDeleteTimer = null; - } if (sendMoneyParticleEffectUpdateTimer) { Script.clearInterval(sendMoneyParticleEffectUpdateTimer); sendMoneyParticleEffectUpdateTimer = null; @@ -588,6 +598,7 @@ if (sendMoneyParticleEffect) { sendMoneyParticleEffect = Entities.deleteEntity(sendMoneyParticleEffect); } + sendMoneyRecipient = null; } // Function Name: fromQml() @@ -670,20 +681,19 @@ removeOverlays(); break; case 'sendMoney_sendPublicly': - var recipient = message.recipient; + sendMoneyRecipient = message.recipient; var amount = message.amount; var props = SEND_MONEY_PARTICLE_PROPERTIES; if (sendMoneyParticleEffect) { deleteSendMoneyParticleEffect(); } props.parentID = MyAvatar.sessionUUID; - props.emitAcceleration = Vec3.subtract(AvatarList.getAvatar(recipient).position, MyAvatar.position); - props.emitAcceleration.y -= 3.0; props.position = MyAvatar.position; props.position.y += 0.2; sendMoneyParticleEffect = Entities.addEntity(props, true); + particleEffectTimestamp = Date.now(); + updateSendMoneyParticleEffect(); sendMoneyParticleEffectUpdateTimer = Script.setInterval(updateSendMoneyParticleEffect, SEND_MONEY_PARTICLE_TIMER_UPDATE); - sendMoneyParticleEffectDeleteTimer = Script.setTimeout(deleteSendMoneyParticleEffect, SEND_MONEY_PARTICLE_TIMER_TIMEOUT); break; default: print('Unrecognized message from QML:', JSON.stringify(message)); From 96b6e85745fff6e3bc31363bb07d5164fda91728 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 31 Jan 2018 12:24:23 -0800 Subject: [PATCH 38/57] formatting --- libraries/render/src/render/Item.cpp | 16 ++++++++-------- libraries/render/src/render/Item.h | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index 1bf20ab510..612dba076b 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -34,15 +34,15 @@ const int Item::LAYER_3D = 1; const int Item::LAYER_3D_FRONT = 2; const int Item::LAYER_3D_HUD = 3; -const uint8_t ItemKey::TAG_BITS_ALL{ 0xFF }; -const uint8_t ItemKey::TAG_BITS_NONE{ 0x00 }; -const uint8_t ItemKey::TAG_BITS_0{ 0x01 }; -const uint8_t ItemKey::TAG_BITS_1{ 0x02 }; -const uint8_t ItemKey::TAG_BITS_2{ 0x04 }; -const uint8_t ItemKey::TAG_BITS_3{ 0x08 }; +const uint8_t ItemKey::TAG_BITS_ALL { 0xFF }; +const uint8_t ItemKey::TAG_BITS_NONE { 0x00 }; +const uint8_t ItemKey::TAG_BITS_0 { 0x01 }; +const uint8_t ItemKey::TAG_BITS_1 { 0x02 }; +const uint8_t ItemKey::TAG_BITS_2 { 0x04 }; +const uint8_t ItemKey::TAG_BITS_3 { 0x08 }; const uint8_t ItemKey::TAG_BITS_4 { 0x10 }; -const uint8_t ItemKey::TAG_BITS_5{ 0x20 }; -const uint8_t ItemKey::TAG_BITS_6{ 0x40 }; +const uint8_t ItemKey::TAG_BITS_5 { 0x20 }; +const uint8_t ItemKey::TAG_BITS_6 { 0x40 }; const uint8_t ItemKey::TAG_BITS_7 { 0x80 }; const uint32_t ItemKey::KEY_TAG_BITS_MASK = ((uint32_t) ItemKey::TAG_BITS_ALL) << FIRST_TAG_BIT; diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 4833bd2f42..ff4b3a0458 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -43,7 +43,7 @@ public: // An Item can be tagged and filtering can rely on the tags to keep or exclude items // ItemKey are not taged by default enum Tag : uint8_t { - TAG_0 = 0, // 8 Tags + TAG_0 = 0, // 8 Tags TAG_1, TAG_2, TAG_3, @@ -52,7 +52,7 @@ public: TAG_6, TAG_7, - NUM_TAGS, + NUM_TAGS }; // Tag bits are derived from the Tag enum const static uint8_t TAG_BITS_ALL; From 87ab8a5840dc5d55d7755afe7488eab230313a3d Mon Sep 17 00:00:00 2001 From: vladest Date: Wed, 31 Jan 2018 21:46:05 +0100 Subject: [PATCH 39/57] Image overlay uses bounds property --- scripts/system/progress.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/system/progress.js b/scripts/system/progress.js index f4741c5b6a..db09d40608 100644 --- a/scripts/system/progress.js +++ b/scripts/system/progress.js @@ -300,7 +300,7 @@ if (visible) { x = ((Date.now() / 1000) % ANIMATION_SECONDS_PER_REPEAT) / ANIMATION_SECONDS_PER_REPEAT; - if (isHMD) { + if (!isHMD) { x = x * barDesktop.repeat; } else { x = x * BAR_HMD_REPEAT; @@ -309,9 +309,9 @@ // Update progress bar Overlays.editOverlay(barDesktop.overlay, { visible: !isHMD, - subImage: { + bounds: { x: barDesktop.repeat - x, - y: 0, + y: windowHeight - barDesktop.height, width: barDesktop.width - barDesktop.repeat, height: barDesktop.height } @@ -319,9 +319,9 @@ Overlays.editOverlay(barHMD.overlay, { visible: isHMD, - subImage: { + bounds: { x: BAR_HMD_REPEAT - x, - y: 0, + y: windowHeight - BAR_HMD_HEIGHT, width: BAR_HMD_WIDTH - BAR_HMD_REPEAT, height: BAR_HMD_HEIGHT } From f6029ed9dcabdf0634efdcb77ab8a5d4bebe839f Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 31 Jan 2018 15:21:22 -0800 Subject: [PATCH 40/57] made requested changes --- libraries/entities/src/EntityItem.cpp | 12 ++++++------ libraries/entities/src/SimulationFlags.h | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index ac349ad74d..9ac24b4324 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2834,7 +2834,7 @@ DEFINE_PROPERTY_ACCESSOR(quint32, StaticCertificateVersion, staticCertificateVer uint32_t EntityItem::getDirtyFlags() const { uint32_t result; withReadLock([&] { - result = _flags & 0x0000ffff; + result = _flags & ~Simulation::SPECIAL_FLAGS; }); return result; } @@ -2842,14 +2842,14 @@ uint32_t EntityItem::getDirtyFlags() const { void EntityItem::markDirtyFlags(uint32_t mask) { withWriteLock([&] { - mask &= 0x0000ffff; + mask &= ~Simulation::SPECIAL_FLAGS; _flags |= mask; }); } void EntityItem::clearDirtyFlags(uint32_t mask) { withWriteLock([&] { - mask &= 0x0000ffff; + mask &= ~Simulation::SPECIAL_FLAGS; _flags &= ~mask; }); } @@ -2857,21 +2857,21 @@ void EntityItem::clearDirtyFlags(uint32_t mask) { uint32_t EntityItem::getSpecialFlags() const { uint32_t result; withReadLock([&] { - result = _flags & 0xffff0000; + result = _flags & ~Simulation::DIRTY_FLAGS; }); return result; } void EntityItem::markSpecialFlags(uint32_t mask) { withWriteLock([&] { - mask &= 0xffff0000; + mask &= ~Simulation::DIRTY_FLAGS; _flags |= mask; }); } void EntityItem::clearSpecialFlags(uint32_t mask) { withWriteLock([&] { - mask &= 0xffff0000; + mask &= ~Simulation::DIRTY_FLAGS; _flags &= ~mask; }); } diff --git a/libraries/entities/src/SimulationFlags.h b/libraries/entities/src/SimulationFlags.h index da82916fe3..c45b333b29 100644 --- a/libraries/entities/src/SimulationFlags.h +++ b/libraries/entities/src/SimulationFlags.h @@ -33,6 +33,22 @@ namespace Simulation { const uint32_t DIRTY_TRANSFORM = DIRTY_POSITION | DIRTY_ROTATION; const uint32_t DIRTY_VELOCITIES = DIRTY_LINEAR_VELOCITY | DIRTY_ANGULAR_VELOCITY; + const uint32_t SPECIAL_FLAGS = SPECIAL_FLAGS_NO_BOOTSTRAPPING; + + const uint32_t DIRTY_FLAGS = DIRTY_POSITION | + DIRTY_ROTATION | + DIRTY_LINEAR_VELOCITY | + DIRTY_ANGULAR_VELOCITY | + DIRTY_MASS | + DIRTY_COLLISION_GROUP | + DIRTY_MOTION_TYPE | + DIRTY_SHAPE | + DIRTY_LIFETIME | + DIRTY_UPDATEABLE | + DIRTY_MATERIAL | + DIRTY_PHYSICS_ACTIVATION | + DIRTY_SIMULATOR_ID | + DIRTY_SIMULATION_OWNERSHIP_PRIORITY; }; #endif // hifi_SimulationFlags_h From bd5fc65bfbaab291e0deba95d774a7cfc6aca273 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 31 Jan 2018 16:19:14 -0800 Subject: [PATCH 41/57] fix getDirtyFlags & getSpecialFlags function --- libraries/entities/src/EntityItem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 9ac24b4324..842e5cd7b4 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2834,7 +2834,7 @@ DEFINE_PROPERTY_ACCESSOR(quint32, StaticCertificateVersion, staticCertificateVer uint32_t EntityItem::getDirtyFlags() const { uint32_t result; withReadLock([&] { - result = _flags & ~Simulation::SPECIAL_FLAGS; + result = _flags & Simulation::SPECIAL_FLAGS; }); return result; } @@ -2857,7 +2857,7 @@ void EntityItem::clearDirtyFlags(uint32_t mask) { uint32_t EntityItem::getSpecialFlags() const { uint32_t result; withReadLock([&] { - result = _flags & ~Simulation::DIRTY_FLAGS; + result = _flags & Simulation::DIRTY_FLAGS; }); return result; } From 89f4fe1c04a132fbd73093a657a4f42d60a6dd4c Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 31 Jan 2018 17:28:45 -0800 Subject: [PATCH 42/57] Adding the map of existing shaders and programs and ways to identify them to avoid recompiling them --- libraries/gpu/src/gpu/Shader.cpp | 114 +++++++++++++++++++++++-------- libraries/gpu/src/gpu/Shader.h | 50 +++++++++++++- 2 files changed, 132 insertions(+), 32 deletions(-) diff --git a/libraries/gpu/src/gpu/Shader.cpp b/libraries/gpu/src/gpu/Shader.cpp index b6b90e98fa..649e7d9e66 100755 --- a/libraries/gpu/src/gpu/Shader.cpp +++ b/libraries/gpu/src/gpu/Shader.cpp @@ -17,59 +17,112 @@ using namespace gpu; -Shader::Shader(Type type, const Source& source): +std::atomic Shader::_nextShaderID( 1 ); +Shader::DomainShaderMaps Shader::_domainShaderMaps; +Shader::ProgramMap Shader::_programMap; + + +Shader::Shader(Type type, const Source& source) : _source(source), - _type(type) + _type(type), + _ID(_nextShaderID++) { } -Shader::Shader(Type type, const Pointer& vertex, const Pointer& pixel): - _type(type) +Shader::Shader(Type type, const Pointer& vertex, const Pointer& geometry, const Pointer& pixel): + _type(type), + _ID(_nextShaderID++) { - _shaders.resize(2); - _shaders[VERTEX] = vertex; - _shaders[PIXEL] = pixel; -} - -Shader::Shader(Type type, const Pointer& vertex, const Pointer& geometry, const Pointer& pixel) : -_type(type) { - _shaders.resize(3); - _shaders[VERTEX] = vertex; - _shaders[GEOMETRY] = geometry; - _shaders[PIXEL] = pixel; + if (geometry) { + _shaders.resize(3); + _shaders[VERTEX] = vertex; + _shaders[GEOMETRY] = geometry; + _shaders[PIXEL] = pixel; + } else { + _shaders.resize(2); + _shaders[VERTEX] = vertex; + _shaders[PIXEL] = pixel; + } } Shader::~Shader() { } +Shader::Pointer Shader::createOrReuseDomainShader(Type type, const Source& source) { + auto found = _domainShaderMaps[type].find(source); + if (found != _domainShaderMaps[type].end()) { + auto sharedShader = (*found).second.lock(); + if (sharedShader) { + return sharedShader; + } + } + auto shader = Pointer(new Shader(type, source)); + _domainShaderMaps[type].emplace(source, std::weak_ptr(shader)); + return shader; +} + Shader::Pointer Shader::createVertex(const Source& source) { - return Pointer(new Shader(VERTEX, source)); + return createOrReuseDomainShader(VERTEX, source); } Shader::Pointer Shader::createPixel(const Source& source) { - return Pointer(new Shader(PIXEL, source)); + return createOrReuseDomainShader(PIXEL, source); } Shader::Pointer Shader::createGeometry(const Source& source) { - return Pointer(new Shader(GEOMETRY, source)); + return createOrReuseDomainShader(GEOMETRY, source); } -Shader::Pointer Shader::createProgram(const Pointer& vertexShader, const Pointer& pixelShader) { - if (vertexShader && vertexShader->getType() == VERTEX && - pixelShader && pixelShader->getType() == PIXEL) { - return Pointer(new Shader(PROGRAM, vertexShader, pixelShader)); +ShaderPointer Shader::createOrReuseProgramShader(Type type, const Pointer& vertexShader, const Pointer& geometryShader, const Pointer& pixelShader) { + ProgramMapKey key(0); + + if (vertexShader && vertexShader->getType() == VERTEX) { + key.x = vertexShader->getID(); + } else { + // Shader is not valid, exit + return Pointer(); } - return Pointer(); + + if (pixelShader && pixelShader->getType() == PIXEL) { + key.y = pixelShader->getID(); + } else { + // Shader is not valid, exit + return Pointer(); + } + + if (geometryShader) { + if (geometryShader->getType() == GEOMETRY) { + key.z = geometryShader->getID(); + } else { + // Shader is not valid, exit + return Pointer(); + } + } + + // program key is defined, now try to reuse + auto found = _programMap.find(key); + if (found != _programMap.end()) { + auto sharedShader = (*found).second.lock(); + if (sharedShader) { + return sharedShader; + } + } + + // Program is a new one, let's create it + auto program = Pointer(new Shader(type, vertexShader, geometryShader, pixelShader)); + _programMap.emplace(key, std::weak_ptr(program)); + return program; +} + + +Shader::Pointer Shader::createProgram(const Pointer& vertexShader, const Pointer& pixelShader) { + return createOrReuseProgramShader(PROGRAM, vertexShader, nullptr, pixelShader); } Shader::Pointer Shader::createProgram(const Pointer& vertexShader, const Pointer& geometryShader, const Pointer& pixelShader) { - if (vertexShader && vertexShader->getType() == VERTEX && - geometryShader && geometryShader->getType() == GEOMETRY && - pixelShader && pixelShader->getType() == PIXEL) { - return Pointer(new Shader(PROGRAM, vertexShader, geometryShader, pixelShader)); - } - return Pointer(); + return createOrReuseProgramShader(PROGRAM, vertexShader, geometryShader, pixelShader); + } void Shader::defineSlots(const SlotSet& uniforms, const SlotSet& uniformBuffers, const SlotSet& resourceBuffers, const SlotSet& textures, const SlotSet& samplers, const SlotSet& inputs, const SlotSet& outputs) { @@ -98,4 +151,5 @@ void Shader::setCompilationLogs(const CompilationLogs& logs) const { void Shader::incrementCompilationAttempt() const { _numCompilationAttempts++; -} \ No newline at end of file +} + diff --git a/libraries/gpu/src/gpu/Shader.h b/libraries/gpu/src/gpu/Shader.h index a489146e36..1e251e6f67 100755 --- a/libraries/gpu/src/gpu/Shader.h +++ b/libraries/gpu/src/gpu/Shader.h @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -22,6 +23,8 @@ namespace gpu { class Shader { public: + // unique identifier of a shader + using ID = uint32_t; typedef std::shared_ptr< Shader > Pointer; typedef std::vector< Pointer > Shaders; @@ -39,6 +42,11 @@ public: virtual const std::string& getCode() const { return _code; } + class Less { + public: + bool operator() (const Source& x, const Source& y) const { if (x._lang == y._lang) { return x._code < y._code; } else { return (x._lang < y._lang); } } + }; + protected: std::string _code; Language _lang = GLSL; @@ -134,6 +142,8 @@ public: ~Shader(); + ID getID() const { return _ID; } + Type getType() const { return _type; } bool isProgram() const { return getType() > NUM_DOMAINS; } bool isDomain() const { return getType() < NUM_DOMAINS; } @@ -194,15 +204,15 @@ public: const GPUObjectPointer gpuObject {}; - + protected: Shader(Type type, const Source& source); - Shader(Type type, const Pointer& vertex, const Pointer& pixel); Shader(Type type, const Pointer& vertex, const Pointer& geometry, const Pointer& pixel); Shader(const Shader& shader); // deep copy of the sysmem shader Shader& operator=(const Shader& shader); // deep copy of the sysmem texture + // Source contains the actual source code or nothing if the shader is a program Source _source; @@ -221,6 +231,9 @@ protected: // The type of the shader, the master key Type _type; + // The unique identifier of a shader in the GPU lib + uint32_t _ID{ 0 }; + // Number of attempts to compile the shader mutable uint32_t _numCompilationAttempts{ 0 }; // Compilation logs (one for each versions generated) @@ -228,6 +241,39 @@ protected: // Whether or not the shader compilation failed bool _compilationHasFailed { false }; + + + // Global maps of the shaders + // Unique shader ID + static std::atomic _nextShaderID; + + using ShaderMap = std::map, Source::Less>; + using DomainShaderMaps = std::array; + static DomainShaderMaps _domainShaderMaps; + + static ShaderPointer createOrReuseDomainShader(Type type, const Source& source); + + using ProgramMapKey = glm::uvec3; // THe IDs of the shaders in a progrma make its key + class ProgramKeyLess { + public: + bool operator() (const ProgramMapKey& l, const ProgramMapKey& r) const { + if (l.x == r.x) { + if (l.y == r.y) { + return (l.z < l.z); + } + else { + return (l.y < l.y); + } + } + else { + return (l.x < r.x); + } + } + }; + using ProgramMap = std::map, ProgramKeyLess>; + static ProgramMap _programMap; + + static ShaderPointer createOrReuseProgramShader(Type type, const Pointer& vertexShader, const Pointer& geometryShader, const Pointer& pixelShader); }; typedef Shader::Pointer ShaderPointer; From edb416d24eacc2046d46f1f13c16d54d408cc343 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 31 Jan 2018 21:32:22 -0800 Subject: [PATCH 43/57] Fixing the program map sorting, good to go --- libraries/gpu/src/gpu/Shader.cpp | 1 - libraries/gpu/src/gpu/Shader.h | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/gpu/src/gpu/Shader.cpp b/libraries/gpu/src/gpu/Shader.cpp index 649e7d9e66..e428c758b1 100755 --- a/libraries/gpu/src/gpu/Shader.cpp +++ b/libraries/gpu/src/gpu/Shader.cpp @@ -122,7 +122,6 @@ Shader::Pointer Shader::createProgram(const Pointer& vertexShader, const Pointer Shader::Pointer Shader::createProgram(const Pointer& vertexShader, const Pointer& geometryShader, const Pointer& pixelShader) { return createOrReuseProgramShader(PROGRAM, vertexShader, geometryShader, pixelShader); - } void Shader::defineSlots(const SlotSet& uniforms, const SlotSet& uniformBuffers, const SlotSet& resourceBuffers, const SlotSet& textures, const SlotSet& samplers, const SlotSet& inputs, const SlotSet& outputs) { diff --git a/libraries/gpu/src/gpu/Shader.h b/libraries/gpu/src/gpu/Shader.h index 1e251e6f67..b7ca000d43 100755 --- a/libraries/gpu/src/gpu/Shader.h +++ b/libraries/gpu/src/gpu/Shader.h @@ -259,10 +259,10 @@ protected: bool operator() (const ProgramMapKey& l, const ProgramMapKey& r) const { if (l.x == r.x) { if (l.y == r.y) { - return (l.z < l.z); + return (l.z < r.z); } else { - return (l.y < l.y); + return (l.y < r.y); } } else { From 60238fa644b4ae603a3011f2abbdf8818ed8f37c Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 31 Jan 2018 23:15:19 -0800 Subject: [PATCH 44/57] Fixing the android build --- libraries/gpu-gles/src/gpu/gl/GLShader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gpu-gles/src/gpu/gl/GLShader.cpp b/libraries/gpu-gles/src/gpu/gl/GLShader.cpp index a626376e27..42d4fe3845 100644 --- a/libraries/gpu-gles/src/gpu/gl/GLShader.cpp +++ b/libraries/gpu-gles/src/gpu/gl/GLShader.cpp @@ -39,7 +39,7 @@ GLShader* GLShader::sync(GLBackend& backend, const Shader& shader, Shader::Compi } // need to have a gpu object? if (shader.isProgram()) { - GLShader* tempObject = backend.compileBackendProgram(shader); + GLShader* tempObject = backend.compileBackendProgram(shader, handler); if (tempObject) { object = tempObject; Backend::setGPUObject(shader, object); From a650c5bbc62c8fc5d61f87b843b83fc373131691 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 31 Jan 2018 23:31:31 -0800 Subject: [PATCH 45/57] Move a define to resume watchdog a bit further --- interface/src/Application.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 808f6eb890..f7c30869c2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2296,10 +2296,6 @@ void Application::initializeGL() { #endif _renderEngine->addJob("RenderMainView", cullFunctor, !DISABLE_DEFERRED); -#ifdef Q_OS_OSX - DeadlockWatchdogThread::resume(); -#endif - _renderEngine->load(); _renderEngine->registerScene(_main3DScene); From 351f619555c736a7ae878c06c4dcb6775c727284 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 31 Jan 2018 23:35:16 -0800 Subject: [PATCH 46/57] Fixing a shader error on android --- libraries/render-utils/src/LightAmbient.slh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/LightAmbient.slh b/libraries/render-utils/src/LightAmbient.slh index acd30d527d..89d3f4faee 100644 --- a/libraries/render-utils/src/LightAmbient.slh +++ b/libraries/render-utils/src/LightAmbient.slh @@ -46,7 +46,7 @@ vec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface) { float levels = getLightAmbientMapNumMips(ambient); float m = 12.0 / (1.0+11.0*surface.roughness); float lod = levels - m; - lod = max(lod, 0); + lod = max(lod, 0.0); specularLight = evalSkyboxLight(lightDir, lod).xyz; } <@endif@> From ab20643ada020d58b196685f795e7570c1213bdc Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 1 Feb 2018 08:13:43 -0800 Subject: [PATCH 47/57] fix mistakes --- libraries/entities/src/EntityItem.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 842e5cd7b4..ed13a46414 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2834,7 +2834,7 @@ DEFINE_PROPERTY_ACCESSOR(quint32, StaticCertificateVersion, staticCertificateVer uint32_t EntityItem::getDirtyFlags() const { uint32_t result; withReadLock([&] { - result = _flags & Simulation::SPECIAL_FLAGS; + result = _flags & Simulation::DIRTY_FLAGS; }); return result; } @@ -2842,14 +2842,14 @@ uint32_t EntityItem::getDirtyFlags() const { void EntityItem::markDirtyFlags(uint32_t mask) { withWriteLock([&] { - mask &= ~Simulation::SPECIAL_FLAGS; + mask &= Simulation::DIRTY_FLAGS; _flags |= mask; }); } void EntityItem::clearDirtyFlags(uint32_t mask) { withWriteLock([&] { - mask &= ~Simulation::SPECIAL_FLAGS; + mask &= Simulation::DIRTY_FLAGS; _flags &= ~mask; }); } @@ -2857,21 +2857,21 @@ void EntityItem::clearDirtyFlags(uint32_t mask) { uint32_t EntityItem::getSpecialFlags() const { uint32_t result; withReadLock([&] { - result = _flags & Simulation::DIRTY_FLAGS; + result = _flags & Simulation::SPECIAL_FLAGS; }); return result; } void EntityItem::markSpecialFlags(uint32_t mask) { withWriteLock([&] { - mask &= ~Simulation::DIRTY_FLAGS; + mask &= Simulation::SPECIAL_FLAGS; _flags |= mask; }); } void EntityItem::clearSpecialFlags(uint32_t mask) { withWriteLock([&] { - mask &= ~Simulation::DIRTY_FLAGS; + mask &= Simulation::SPECIAL_FLAGS; _flags &= ~mask; }); } From bd26c9dfc0fc922a0e635af5641f4284112277c9 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 31 Jan 2018 12:32:54 -0800 Subject: [PATCH 48/57] More improvements --- .../hifi/commerce/common/images/loader.gif | Bin 0 -> 59412 bytes .../commerce/wallet/sendMoney/SendMoney.qml | 34 ++++++------------ scripts/system/commerce/wallet.js | 4 +-- 3 files changed, 12 insertions(+), 26 deletions(-) create mode 100644 interface/resources/qml/hifi/commerce/common/images/loader.gif diff --git a/interface/resources/qml/hifi/commerce/common/images/loader.gif b/interface/resources/qml/hifi/commerce/common/images/loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..0536bd1884f1cb4a814b729803b1996c8347d182 GIT binary patch literal 59412 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�)#8TsS*rVAU%J0tpt=B2=IG*djp3b$!Y|O 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 L8@}NiK8F7Q4CAa& literal 0 HcmV?d00001 diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml index 63acf6bac8..8f7757963c 100644 --- a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml +++ b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml @@ -57,6 +57,9 @@ Item { if (result.status === 'success') { root.nextActiveView = 'paymentSuccess'; + if (sendPubliclyCheckbox.checked && sendMoneyStep.referrer === "nearby") { + sendSignalToWallet({method: 'sendMoney_sendPublicly', recipient: sendMoneyStep.selectedRecipientNodeID, amount: parseInt(amountTextField.text)}); + } } else { root.nextActiveView = 'paymentFailure'; } @@ -308,22 +311,6 @@ Item { } } } - - // "Particle" button - HifiControlsUit.Button { - id: particle; - color: hifi.buttons.blue; - colorScheme: hifi.colorSchemes.dark; - anchors.horizontalCenter: parent.horizontalCenter; - anchors.top: nearbyButton.bottom; - anchors.topMargin: 24; - height: 50; - width: 160; - text: "Try Particles"; - onClicked: { - sendSignalToWallet({method: 'sendMoney_sendPublicly', recipient: "{09f76bc2-c108-41e9-9a94-18bbda228ed2}", amount: 2}); - } - } } } // Send Money Home END @@ -983,7 +970,8 @@ Item { HifiControlsUit.CheckBox { id: sendPubliclyCheckbox; - visible: true; + visible: sendMoneyStep.referrer === "nearby"; + checked: Settings.getValue("sendMoneyNearbyPublicly", true); text: "Send Publicly" // Anchors anchors.top: messageContainer.bottom; @@ -992,7 +980,10 @@ Item { anchors.leftMargin: 20; anchors.right: parent.right; anchors.rightMargin: 16; - boxSize: 24; + boxSize: 28; + onCheckedChanged: { + Settings.setValue("sendMoneyNearbyPublicly", checked); + } } Item { @@ -1051,11 +1042,7 @@ Item { if (sendMoneyStep.referrer === "connections") { Commerce.transferHfcToUsername(sendMoneyStep.selectedRecipientUserName, parseInt(amountTextField.text), optionalMessage.text); } else if (sendMoneyStep.referrer === "nearby") { - var transferAmount = parseInt(amountTextField.text); - Commerce.transferHfcToNode(sendMoneyStep.selectedRecipientNodeID, transferAmount, optionalMessage.text); - if (sendPubliclyCheckbox.checked) { - sendSignalToWallet({method: 'sendMoney_sendPublicly', recipient: sendMoneyStep.selectedRecipientNodeID, amount: transferAmount}); - } + Commerce.transferHfcToNode(sendMoneyStep.selectedRecipientNodeID, parseInt(amountTextField.text), optionalMessage.text); } } } @@ -1554,6 +1541,7 @@ Item { amountTextField.text = ""; optionalMessage.text = ""; sendPubliclyCheckbox.checked = false; + sendMoneyStep.referrer = ""; } // diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index 4e49ee324f..b1eef8ca83 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -684,9 +684,7 @@ sendMoneyRecipient = message.recipient; var amount = message.amount; var props = SEND_MONEY_PARTICLE_PROPERTIES; - if (sendMoneyParticleEffect) { - deleteSendMoneyParticleEffect(); - } + deleteSendMoneyParticleEffect(); props.parentID = MyAvatar.sessionUUID; props.position = MyAvatar.position; props.position.y += 0.2; From fd501cf3af75357cb1de1a5496e8ae9c58fb79e8 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 1 Feb 2018 10:37:54 -0800 Subject: [PATCH 49/57] Addressing review comments --- libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp | 3 +++ libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp | 3 +++ libraries/gpu/src/gpu/Shader.h | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp index e9d23b543f..42e95ba6c6 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp @@ -71,6 +71,9 @@ GLShader* GLBackend::compileBackendShader(const Shader& shader, Shader::Compilat if (handler) { bool retest = true; std::string currentSrc = shaderSource; + // When a Handler is specified, we can try multiple times to build the shader and let the handler change the source if the compilation fails. + // The retest bool is set to false as soon as the compilation succeed to wexit the while loop. + // The handler tells us if we should retry or not while returning a modified version of the source. while (retest) { bool result = ::gl::compileShader(shaderDomain, currentSrc, shaderDefines, shaderObject.glshader, compilationLogs[version].message); compilationLogs[version].compiled = result; diff --git a/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp b/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp index 350e95b46a..b799fb0037 100644 --- a/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp +++ b/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp @@ -74,6 +74,9 @@ GLShader* GLBackend::compileBackendShader(const Shader& shader, Shader::Compilat if (handler) { bool retest = true; std::string currentSrc = shaderSource; + // When a Handler is specified, we can try multiple times to build the shader and let the handler change the source if the compilation fails. + // The retest bool is set to false as soon as the compilation succeed to wexit the while loop. + // The handler tells us if we should retry or not while returning a modified version of the source. while (retest) { bool result = ::gl::compileShader(shaderDomain, currentSrc, shaderDefines, shaderObject.glshader, compilationLogs[version].message); compilationLogs[version].compiled = result; diff --git a/libraries/gpu/src/gpu/Shader.h b/libraries/gpu/src/gpu/Shader.h index b7ca000d43..07800fa14a 100755 --- a/libraries/gpu/src/gpu/Shader.h +++ b/libraries/gpu/src/gpu/Shader.h @@ -253,7 +253,7 @@ protected: static ShaderPointer createOrReuseDomainShader(Type type, const Source& source); - using ProgramMapKey = glm::uvec3; // THe IDs of the shaders in a progrma make its key + using ProgramMapKey = glm::uvec3; // The IDs of the shaders in a program make its key class ProgramKeyLess { public: bool operator() (const ProgramMapKey& l, const ProgramMapKey& r) const { From ce79504f03a96de88603ecb1ad5244adfe3fc685 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 1 Feb 2018 11:51:08 -0800 Subject: [PATCH 50/57] Fix checkbox --- .../resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml index 8f7757963c..765b2aecdb 100644 --- a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml +++ b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml @@ -1540,7 +1540,7 @@ Item { sendMoneyStep.selectedRecipientProfilePic = ""; amountTextField.text = ""; optionalMessage.text = ""; - sendPubliclyCheckbox.checked = false; + sendPubliclyCheckbox.checked = Settings.getValue("sendMoneyNearbyPublicly", true); sendMoneyStep.referrer = ""; } From 89e52561e39c0f117bdeb85825b9ee27532c99a6 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 1 Feb 2018 11:53:27 -0800 Subject: [PATCH 51/57] Silly bugfix --- scripts/system/commerce/wallet.js | 2 +- scripts/system/marketplaces/marketplaces.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index b1eef8ca83..cef61bdc53 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -681,10 +681,10 @@ removeOverlays(); break; case 'sendMoney_sendPublicly': + deleteSendMoneyParticleEffect(); sendMoneyRecipient = message.recipient; var amount = message.amount; var props = SEND_MONEY_PARTICLE_PROPERTIES; - deleteSendMoneyParticleEffect(); props.parentID = MyAvatar.sessionUUID; props.position = MyAvatar.position; props.position.y += 0.2; diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index ee3a9ce7ec..facb932eb0 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -578,6 +578,7 @@ var selectionDisplay = null; // for gridTool.js to ignore case 'refreshConnections': case 'enable_ChooseRecipientNearbyMode': case 'disable_ChooseRecipientNearbyMode': + case 'sendMoney_sendPublicly': // NOP break; default: From 9867b479fd30f2a3987bf3ef4c7df9703ff58d69 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 1 Feb 2018 13:12:28 -0800 Subject: [PATCH 52/57] APplying review feedback --- libraries/gpu-gl/src/gpu/gl/GLBackend.cpp | 2 +- libraries/gpu-gl/src/gpu/gl/GLBackend.h | 6 +++--- libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp | 4 ++-- libraries/gpu-gl/src/gpu/gl/GLShader.cpp | 4 ++-- libraries/gpu-gl/src/gpu/gl/GLShader.h | 4 ++-- libraries/gpu-gles/src/gpu/gl/GLBackend.cpp | 2 +- libraries/gpu-gles/src/gpu/gl/GLBackend.h | 6 +++--- libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp | 4 ++-- libraries/gpu-gles/src/gpu/gl/GLShader.cpp | 4 ++-- libraries/gpu-gles/src/gpu/gl/GLShader.h | 4 ++-- libraries/gpu/src/gpu/Context.cpp | 2 +- libraries/gpu/src/gpu/Context.h | 4 ++-- libraries/gpu/src/gpu/Shader.cpp | 2 +- libraries/gpu/src/gpu/Shader.h | 11 +++++++++-- libraries/gpu/src/gpu/null/NullBackend.h | 2 +- 15 files changed, 34 insertions(+), 27 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp index 2a052c5210..08bd20be66 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp @@ -68,7 +68,7 @@ GLBackend& getBackend() { return *INSTANCE; } -bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindings, Shader::CompilationHandler handler) { +bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindings, const Shader::CompilationHandler& handler) { return GLShader::makeProgram(getBackend(), shader, slotBindings, handler); } diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.h b/libraries/gpu-gl/src/gpu/gl/GLBackend.h index f0b74803e4..18916ac18c 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.h @@ -64,7 +64,7 @@ protected: explicit GLBackend(bool syncCache); GLBackend(); public: - static bool makeProgram(Shader& shader, const Shader::BindingSet& slotBindings, Shader::CompilationHandler handler); + static bool makeProgram(Shader& shader, const Shader::BindingSet& slotBindings, const Shader::CompilationHandler& handler); virtual ~GLBackend(); @@ -423,8 +423,8 @@ protected: } _pipeline; // Backend dependant compilation of the shader - virtual GLShader* compileBackendProgram(const Shader& program, Shader::CompilationHandler handler); - virtual GLShader* compileBackendShader(const Shader& shader, Shader::CompilationHandler handler); + virtual GLShader* compileBackendProgram(const Shader& program, const Shader::CompilationHandler& handler); + virtual GLShader* compileBackendShader(const Shader& shader, const Shader::CompilationHandler& handler); virtual std::string getBackendShaderHeader() const; virtual void makeProgramBindings(ShaderObject& shaderObject); class ElementResource { diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp index 42e95ba6c6..93c9b0d2ff 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendShader.cpp @@ -56,7 +56,7 @@ static const std::array VERSION_DEFINES { { stereoVersion } }; -GLShader* GLBackend::compileBackendShader(const Shader& shader, Shader::CompilationHandler handler) { +GLShader* GLBackend::compileBackendShader(const Shader& shader, const Shader::CompilationHandler& handler) { // Any GLSLprogram ? normally yes... const std::string& shaderSource = shader.getSource().getCode(); GLenum shaderDomain = SHADER_DOMAINS[shader.getType()]; @@ -105,7 +105,7 @@ GLShader* GLBackend::compileBackendShader(const Shader& shader, Shader::Compilat return object; } -GLShader* GLBackend::compileBackendProgram(const Shader& program, Shader::CompilationHandler handler) { +GLShader* GLBackend::compileBackendProgram(const Shader& program, const Shader::CompilationHandler& handler) { if (!program.isProgram()) { return nullptr; } diff --git a/libraries/gpu-gl/src/gpu/gl/GLShader.cpp b/libraries/gpu-gl/src/gpu/gl/GLShader.cpp index 42d4fe3845..010a7c479c 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLShader.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLShader.cpp @@ -30,7 +30,7 @@ GLShader::~GLShader() { } } -GLShader* GLShader::sync(GLBackend& backend, const Shader& shader, Shader::CompilationHandler handler) { +GLShader* GLShader::sync(GLBackend& backend, const Shader& shader, const Shader::CompilationHandler& handler) { GLShader* object = Backend::getGPUObject(shader); // If GPU object already created then good @@ -56,7 +56,7 @@ GLShader* GLShader::sync(GLBackend& backend, const Shader& shader, Shader::Compi return object; } -bool GLShader::makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings, Shader::CompilationHandler handler) { +bool GLShader::makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings, const Shader::CompilationHandler& handler) { // First make sure the Shader has been compiled GLShader* object = sync(backend, shader, handler); diff --git a/libraries/gpu-gl/src/gpu/gl/GLShader.h b/libraries/gpu-gl/src/gpu/gl/GLShader.h index 8625b3e64a..3259982e93 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLShader.h +++ b/libraries/gpu-gl/src/gpu/gl/GLShader.h @@ -21,8 +21,8 @@ struct ShaderObject { class GLShader : public GPUObject { public: - static GLShader* sync(GLBackend& backend, const Shader& shader, Shader::CompilationHandler handler = nullptr); - static bool makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings, Shader::CompilationHandler handler); + static GLShader* sync(GLBackend& backend, const Shader& shader, const Shader::CompilationHandler& handler = nullptr); + static bool makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings, const Shader::CompilationHandler& handler); enum Version { Mono = 0, diff --git a/libraries/gpu-gles/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gles/src/gpu/gl/GLBackend.cpp index 8a118b7b71..fc1bc39929 100644 --- a/libraries/gpu-gles/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gles/src/gpu/gl/GLBackend.cpp @@ -61,7 +61,7 @@ GLBackend& getBackend() { return *INSTANCE; } -bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindings, Shader::CompilationHandler handler) { +bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindings, const Shader::CompilationHandler& handler) { return GLShader::makeProgram(getBackend(), shader, slotBindings, handler); } diff --git a/libraries/gpu-gles/src/gpu/gl/GLBackend.h b/libraries/gpu-gles/src/gpu/gl/GLBackend.h index 0db46985f7..3681fc0492 100644 --- a/libraries/gpu-gles/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gles/src/gpu/gl/GLBackend.h @@ -61,7 +61,7 @@ protected: explicit GLBackend(bool syncCache); GLBackend(); public: - static bool makeProgram(Shader& shader, const Shader::BindingSet& slotBindings = Shader::BindingSet(), Shader::CompilationHandler handler = nullptr); + static bool makeProgram(Shader& shader, const Shader::BindingSet& slotBindings = Shader::BindingSet(), const Shader::CompilationHandler& handler = nullptr); virtual ~GLBackend(); @@ -420,8 +420,8 @@ protected: } _pipeline; // Backend dependant compilation of the shader - virtual GLShader* compileBackendProgram(const Shader& program, Shader::CompilationHandler handler); - virtual GLShader* compileBackendShader(const Shader& shader, Shader::CompilationHandler handler); + virtual GLShader* compileBackendProgram(const Shader& program, const Shader::CompilationHandler& handler); + virtual GLShader* compileBackendShader(const Shader& shader, const Shader::CompilationHandler& handler); virtual std::string getBackendShaderHeader() const; virtual void makeProgramBindings(ShaderObject& shaderObject); class ElementResource { diff --git a/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp b/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp index b799fb0037..677bba97ca 100644 --- a/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp +++ b/libraries/gpu-gles/src/gpu/gl/GLBackendShader.cpp @@ -56,7 +56,7 @@ static const std::array VERSION_DEFINES { { stereoVersion } }; -GLShader* GLBackend::compileBackendShader(const Shader& shader, Shader::CompilationHandler handler) { +GLShader* GLBackend::compileBackendShader(const Shader& shader, const Shader::CompilationHandler& handler) { // Any GLSLprogram ? normally yes... const std::string& shaderSource = shader.getSource().getCode(); GLenum shaderDomain = SHADER_DOMAINS[shader.getType()]; @@ -108,7 +108,7 @@ GLShader* GLBackend::compileBackendShader(const Shader& shader, Shader::Compilat return object; } -GLShader* GLBackend::compileBackendProgram(const Shader& program, Shader::CompilationHandler handler) { +GLShader* GLBackend::compileBackendProgram(const Shader& program, const Shader::CompilationHandler& handler) { if (!program.isProgram()) { return nullptr; } diff --git a/libraries/gpu-gles/src/gpu/gl/GLShader.cpp b/libraries/gpu-gles/src/gpu/gl/GLShader.cpp index 42d4fe3845..010a7c479c 100644 --- a/libraries/gpu-gles/src/gpu/gl/GLShader.cpp +++ b/libraries/gpu-gles/src/gpu/gl/GLShader.cpp @@ -30,7 +30,7 @@ GLShader::~GLShader() { } } -GLShader* GLShader::sync(GLBackend& backend, const Shader& shader, Shader::CompilationHandler handler) { +GLShader* GLShader::sync(GLBackend& backend, const Shader& shader, const Shader::CompilationHandler& handler) { GLShader* object = Backend::getGPUObject(shader); // If GPU object already created then good @@ -56,7 +56,7 @@ GLShader* GLShader::sync(GLBackend& backend, const Shader& shader, Shader::Compi return object; } -bool GLShader::makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings, Shader::CompilationHandler handler) { +bool GLShader::makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings, const Shader::CompilationHandler& handler) { // First make sure the Shader has been compiled GLShader* object = sync(backend, shader, handler); diff --git a/libraries/gpu-gles/src/gpu/gl/GLShader.h b/libraries/gpu-gles/src/gpu/gl/GLShader.h index 42d63f8dfb..f2a144a81c 100644 --- a/libraries/gpu-gles/src/gpu/gl/GLShader.h +++ b/libraries/gpu-gles/src/gpu/gl/GLShader.h @@ -21,8 +21,8 @@ struct ShaderObject { class GLShader : public GPUObject { public: - static GLShader* sync(GLBackend& backend, const Shader& shader, Shader::CompilationHandler handler = nullptr); - static bool makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings, Shader::CompilationHandler handler = nullptr); + static GLShader* sync(GLBackend& backend, const Shader& shader, const Shader::CompilationHandler& handler = nullptr); + static bool makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings, const Shader::CompilationHandler& handler = nullptr); enum Version { Mono = 0, diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index 2399d3ddc3..d7d86c3ef7 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -127,7 +127,7 @@ void Context::executeFrame(const FramePointer& frame) const { _frameStats.evalDelta(beginStats, endStats); } -bool Context::makeProgram(Shader& shader, const Shader::BindingSet& bindings, Shader::CompilationHandler handler) { +bool Context::makeProgram(Shader& shader, const Shader::BindingSet& bindings, const Shader::CompilationHandler& handler) { // If we're running in another DLL context, we need to fetch the program callback out of the application // FIXME find a way to do this without reliance on Qt app properties if (!_makeProgramCallback) { diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index e22cc57570..195565f438 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -143,7 +143,7 @@ class Context { public: using Size = Resource::Size; typedef BackendPointer (*CreateBackend)(); - typedef bool (*MakeProgram)(Shader& shader, const Shader::BindingSet& bindings, Shader::CompilationHandler handler); + typedef bool (*MakeProgram)(Shader& shader, const Shader::BindingSet& bindings, const Shader::CompilationHandler& handler); // This one call must happen before any context is created or used (Shader::MakeProgram) in order to setup the Backend and any singleton data needed @@ -262,7 +262,7 @@ protected: // makeProgramShader(...) make a program shader ready to be used in a Batch. // It compiles the sub shaders, link them and defines the Slots and their bindings. // If the shader passed is not a program, nothing happens. - static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings, Shader::CompilationHandler handler); + static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings, const Shader::CompilationHandler& handler); static CreateBackend _createBackendCallback; static MakeProgram _makeProgramCallback; diff --git a/libraries/gpu/src/gpu/Shader.cpp b/libraries/gpu/src/gpu/Shader.cpp index e428c758b1..aa7898569b 100755 --- a/libraries/gpu/src/gpu/Shader.cpp +++ b/libraries/gpu/src/gpu/Shader.cpp @@ -134,7 +134,7 @@ void Shader::defineSlots(const SlotSet& uniforms, const SlotSet& uniformBuffers, _outputs = outputs; } -bool Shader::makeProgram(Shader& shader, const Shader::BindingSet& bindings, CompilationHandler handler) { +bool Shader::makeProgram(Shader& shader, const Shader::BindingSet& bindings, const CompilationHandler& handler) { if (shader.isProgram()) { return Context::makeProgram(shader, bindings, handler); } diff --git a/libraries/gpu/src/gpu/Shader.h b/libraries/gpu/src/gpu/Shader.h index 07800fa14a..4504337789 100755 --- a/libraries/gpu/src/gpu/Shader.h +++ b/libraries/gpu/src/gpu/Shader.h @@ -175,7 +175,14 @@ public: const SlotSet& inputs, const SlotSet& outputs); - typedef bool(*CompilationHandler)(const Shader& shader, const std::string& src, CompilationLog& log, std::string& newSrc); + // Compilation Handler can be passed while compiling a shader (in the makeProgram call) to be able to give the hand to + // the caller thread if the comilation fails and to prvide a different version of the source for it + // @param0 the Shader object that just failed to compile + // @param1 the original source code as submited to the compiler + // @param2 the compilation log containing the error message + // @param3 a new string ready to be filled with the new version of the source that could be proposed from the handler functor + // @return boolean true if the backend should keep trying to compile the shader with the new source returned or false to stop and fail that shader compilation + using CompilationHandler = std::function; // makeProgram(...) make a program shader ready to be used in a Batch. // It compiles the sub shaders, link them and defines the Slots and their bindings. @@ -190,7 +197,7 @@ public: // on a gl Context and the driver to compile the glsl shader. // Hoppefully in a few years the shader compilation will be completely abstracted in a separate shader compiler library // independant of the graphics api in use underneath (looking at you opengl & vulkan). - static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings = Shader::BindingSet(), CompilationHandler handler = nullptr); + static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings = Shader::BindingSet(), const CompilationHandler& handler = nullptr); // Check the compilation state bool compilationHasFailed() const { return _compilationHasFailed; } diff --git a/libraries/gpu/src/gpu/null/NullBackend.h b/libraries/gpu/src/gpu/null/NullBackend.h index abaa24812f..57b8fbafbc 100644 --- a/libraries/gpu/src/gpu/null/NullBackend.h +++ b/libraries/gpu/src/gpu/null/NullBackend.h @@ -28,7 +28,7 @@ class Backend : public gpu::Backend { friend class gpu::Context; static void init() {} static gpu::Backend* createBackend() { return new Backend(); } - static bool makeProgram(Shader& shader, const Shader::BindingSet& slotBindings, Shader::CompilationHandler handler) { return true; } + static bool makeProgram(Shader& shader, const Shader::BindingSet& slotBindings, const Shader::CompilationHandler& handler) { return true; } protected: explicit Backend(bool syncCache) : Parent() { } From dd2b7eb10703b93550a4704e91e2f345d7429264 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 1 Feb 2018 15:17:50 -0800 Subject: [PATCH 53/57] Send Money Effect & Lightbox --- .../commerce/wallet/sendMoney/SendMoney.qml | 46 ++++++++++++++++-- .../sendMoney/images/send-money-effect-sm.jpg | Bin 0 -> 22213 bytes 2 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 interface/resources/qml/hifi/commerce/wallet/sendMoney/images/send-money-effect-sm.jpg diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml index 765b2aecdb..16b56407ac 100644 --- a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml +++ b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml @@ -106,6 +106,12 @@ Item { } } + HifiCommerceCommon.CommerceLightbox { + id: lightboxPopup; + visible: false; + anchors.fill: parent; + } + // Send Money Home BEGIN Item { id: sendMoneyHome; @@ -972,19 +978,53 @@ Item { id: sendPubliclyCheckbox; visible: sendMoneyStep.referrer === "nearby"; checked: Settings.getValue("sendMoneyNearbyPublicly", true); - text: "Send Publicly" + text: "Show Effect" // Anchors anchors.top: messageContainer.bottom; anchors.topMargin: 16; anchors.left: parent.left; anchors.leftMargin: 20; - anchors.right: parent.right; - anchors.rightMargin: 16; + width: 110; boxSize: 28; onCheckedChanged: { Settings.setValue("sendMoneyNearbyPublicly", checked); } } + RalewaySemiBold { + id: sendPubliclyCheckboxHelp; + visible: sendPubliclyCheckbox.visible; + text: "[?]"; + // Anchors + anchors.left: sendPubliclyCheckbox.right; + anchors.leftMargin: 8; + anchors.verticalCenter: sendPubliclyCheckbox.verticalCenter; + height: 30; + width: paintedWidth; + // Text size + size: 18; + // Style + color: hifi.colors.blueAccent; + MouseArea { + enabled: sendPubliclyCheckboxHelp.visible; + anchors.fill: parent; + hoverEnabled: true; + onEntered: { + parent.color = hifi.colors.blueHighlight; + } + onExited: { + parent.color = hifi.colors.blueAccent; + } + onClicked: { + lightboxPopup.titleText = "Send Money Effect"; + lightboxPopup.bodyImageSource = "../wallet/sendMoney/images/send-money-effect-sm.jpg"; // Path relative to CommerceLightbox.qml + lightboxPopup.bodyText = "Enabling this option will create a particle effect between you and " + + "your recipient that is visible to everyone nearby."; + lightboxPopup.button1text = "CLOSE"; + lightboxPopup.button1method = "root.visible = false;" + lightboxPopup.visible = true; + } + } + } Item { id: bottomBarContainer; diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/send-money-effect-sm.jpg b/interface/resources/qml/hifi/commerce/wallet/sendMoney/images/send-money-effect-sm.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7cabf9414a1d9f9a28a983c2fdffeda72912897b GIT binary patch literal 22213 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 literal 0 HcmV?d00001 From 14d5029f4d4893664b0ec1d36953d0ccfa6bf38b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 2 Feb 2018 08:56:11 -0800 Subject: [PATCH 54/57] only update cauterization of child entities when something relevant changes --- interface/src/avatar/MyAvatar.cpp | 38 +++++++++++++++------ interface/src/avatar/MyAvatar.h | 7 ++++ libraries/render-utils/src/LightPayload.cpp | 2 +- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 3cf7874b50..54bdd79de5 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -504,6 +504,16 @@ void MyAvatar::updateEyeContactTarget(float deltaTime) { extern QByteArray avatarStateToFrame(const AvatarData* _avatar); extern void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar); +void MyAvatar::beParentOfChild(SpatiallyNestablePointer newChild) const { + _cauterizationNeedsUpdate = true; + SpatiallyNestable::beParentOfChild(newChild); +} + +void MyAvatar::forgetChild(SpatiallyNestablePointer newChild) const { + _cauterizationNeedsUpdate = true; + SpatiallyNestable::forgetChild(newChild); +} + void MyAvatar::updateChildCauterization(SpatiallyNestablePointer object) { if (object->getNestableType() == NestableType::Entity) { EntityItemPointer entity = std::static_pointer_cast(object); @@ -516,16 +526,19 @@ void MyAvatar::simulate(float deltaTime) { animateScaleChanges(deltaTime); - const std::unordered_set& headBoneSet = _skeletonModel->getCauterizeBoneSet(); - forEachChild([&](SpatiallyNestablePointer object) { - bool isChildOfHead = headBoneSet.find(object->getParentJointIndex()) != headBoneSet.end(); - if (isChildOfHead) { - updateChildCauterization(object); - object->forEachDescendant([&](SpatiallyNestablePointer descendant) { - updateChildCauterization(descendant); - }); - } - }); + if (_cauterizationNeedsUpdate) { + const std::unordered_set& headBoneSet = _skeletonModel->getCauterizeBoneSet(); + forEachChild([&](SpatiallyNestablePointer object) { + bool isChildOfHead = headBoneSet.find(object->getParentJointIndex()) != headBoneSet.end(); + if (isChildOfHead) { + updateChildCauterization(object); + object->forEachDescendant([&](SpatiallyNestablePointer descendant) { + updateChildCauterization(descendant); + }); + } + }); + _cauterizationNeedsUpdate = false; + } { PerformanceTimer perfTimer("transform"); @@ -1438,6 +1451,7 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { Avatar::setSkeletonModelURL(skeletonModelURL); _skeletonModel->setVisibleInScene(true, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE); _headBoneSet.clear(); + _cauterizationNeedsUpdate = true; emit skeletonChanged(); } @@ -1809,6 +1823,8 @@ void MyAvatar::initHeadBones() { } q.pop(); } + + _cauterizationNeedsUpdate = true; } QUrl MyAvatar::getAnimGraphOverrideUrl() const { @@ -1879,6 +1895,7 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) { _fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl(); initAnimGraph(); _isAnimatingScale = true; + _cauterizationNeedsUpdate = true; } if (_enableDebugDrawDefaultPose || _enableDebugDrawAnimPose) { @@ -1967,6 +1984,7 @@ void MyAvatar::preDisplaySide(RenderArgs* renderArgs) { // toggle using the cauterizedBones depending on where the camera is and the rendering pass type. const bool shouldDrawHead = shouldRenderHead(renderArgs); if (shouldDrawHead != _prevShouldDrawHead) { + _cauterizationNeedsUpdate = true; _skeletonModel->setEnableCauterization(!shouldDrawHead); for (int i = 0; i < _attachmentData.size(); i++) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index c32013b8d1..97e82b87f5 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -633,6 +633,11 @@ signals: private slots: void leaveDomain(); + +protected: + virtual void beParentOfChild(SpatiallyNestablePointer newChild) const override; + virtual void forgetChild(SpatiallyNestablePointer newChild) const override; + private: bool requiresSafeLanding(const glm::vec3& positionIn, glm::vec3& positionOut); @@ -812,6 +817,8 @@ private: bool _enableDebugDrawIKChains { false }; bool _enableDebugDrawDetailedCollision { false }; + mutable bool _cauterizationNeedsUpdate; // do we need to scan children and update their "cauterized" state? + AudioListenerMode _audioListenerMode; glm::vec3 _customListenPosition; glm::quat _customListenOrientation; diff --git a/libraries/render-utils/src/LightPayload.cpp b/libraries/render-utils/src/LightPayload.cpp index f1eef19498..79e0c1d94d 100644 --- a/libraries/render-utils/src/LightPayload.cpp +++ b/libraries/render-utils/src/LightPayload.cpp @@ -19,7 +19,7 @@ namespace render { ItemKey::Builder builder; builder.withTypeLight(); builder.withTagBits(ItemKey::TAG_BITS_ALL); - if (!payload) { + if (payload) { if (!payload->isVisible()) { builder.withInvisible(); } From 03daba9bacad4b82a3e6e79625608bd23af1cc06 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 2 Feb 2018 18:18:24 +0100 Subject: [PATCH 55/57] Removed duplicate shader include --- libraries/render-utils/src/RenderPipelines.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index ccfe28f698..eacd5b5b66 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -72,7 +72,6 @@ #include "model_lightmap_normal_specular_map_frag.h" #include "model_lightmap_specular_map_frag.h" #include "model_translucent_frag.h" -#include "model_translucent_normal_map_frag.h" #include "model_translucent_unlit_frag.h" #include "model_translucent_normal_map_frag.h" From 19235b8d946f539f4e4fe36d9f71c8683a17e339 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 2 Feb 2018 10:50:35 -0800 Subject: [PATCH 56/57] Fix a bug where hover events incorrectly propagate under popups --- interface/resources/qml/hifi/commerce/checkout/Checkout.qml | 1 + .../resources/qml/hifi/commerce/common/CommerceLightbox.qml | 1 + .../resources/qml/hifi/commerce/common/FirstUseTutorial.qml | 1 + .../commerce/inspectionCertificate/InspectionCertificate.qml | 1 + .../resources/qml/hifi/commerce/purchases/PurchasedItem.qml | 1 + .../resources/qml/hifi/commerce/wallet/PassphraseModal.qml | 1 + .../qml/hifi/commerce/wallet/PassphraseSelection.qml | 1 + interface/resources/qml/hifi/commerce/wallet/Security.qml | 1 + interface/resources/qml/hifi/commerce/wallet/WalletSetup.qml | 1 + .../qml/hifi/commerce/wallet/sendMoney/SendMoney.qml | 5 +++++ 10 files changed, 14 insertions(+) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 4de09c1bf3..809f48361d 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -571,6 +571,7 @@ Rectangle { MouseArea { anchors.fill: parent; propagateComposedEvents: false; + hoverEnabled: true; } RalewayBold { diff --git a/interface/resources/qml/hifi/commerce/common/CommerceLightbox.qml b/interface/resources/qml/hifi/commerce/common/CommerceLightbox.qml index 145b78bdc4..8b0ec17232 100644 --- a/interface/resources/qml/hifi/commerce/common/CommerceLightbox.qml +++ b/interface/resources/qml/hifi/commerce/common/CommerceLightbox.qml @@ -45,6 +45,7 @@ Rectangle { MouseArea { anchors.fill: parent; propagateComposedEvents: false; + hoverEnabled: true; } Rectangle { diff --git a/interface/resources/qml/hifi/commerce/common/FirstUseTutorial.qml b/interface/resources/qml/hifi/commerce/common/FirstUseTutorial.qml index 0d3f67ef7a..bcc641acd5 100644 --- a/interface/resources/qml/hifi/commerce/common/FirstUseTutorial.qml +++ b/interface/resources/qml/hifi/commerce/common/FirstUseTutorial.qml @@ -44,6 +44,7 @@ Rectangle { MouseArea { anchors.fill: parent; propagateComposedEvents: false; + hoverEnabled: true; } Item { diff --git a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml index c331532f5e..421fa4b074 100644 --- a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml +++ b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml @@ -119,6 +119,7 @@ Rectangle { MouseArea { anchors.fill: parent; propagateComposedEvents: false; + hoverEnabled: true; } Image { diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index f7913e5b1e..05e280b839 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -316,6 +316,7 @@ Item { MouseArea { anchors.fill: parent; propagateComposedEvents: false; + hoverEnabled: true; } RalewayBold { diff --git a/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml b/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml index 87430246f3..c586af9e80 100644 --- a/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml +++ b/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml @@ -66,6 +66,7 @@ Item { MouseArea { anchors.fill: parent; propagateComposedEvents: false; + hoverEnabled: true; } // This will cause a bug -- if you bring up passphrase selection in HUD mode while diff --git a/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml b/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml index 50e58f8cc4..50bea2a3cf 100644 --- a/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml +++ b/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml @@ -34,6 +34,7 @@ Item { MouseArea { anchors.fill: parent; propagateComposedEvents: false; + hoverEnabled: true; } Connections { diff --git a/interface/resources/qml/hifi/commerce/wallet/Security.qml b/interface/resources/qml/hifi/commerce/wallet/Security.qml index 634a68d117..224b743c06 100644 --- a/interface/resources/qml/hifi/commerce/wallet/Security.qml +++ b/interface/resources/qml/hifi/commerce/wallet/Security.qml @@ -306,6 +306,7 @@ Item { MouseArea { anchors.fill: parent; propagateComposedEvents: false; + hoverEnabled: true; } RalewayBold { diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletSetup.qml b/interface/resources/qml/hifi/commerce/wallet/WalletSetup.qml index fd74b07465..fab27a29bb 100644 --- a/interface/resources/qml/hifi/commerce/wallet/WalletSetup.qml +++ b/interface/resources/qml/hifi/commerce/wallet/WalletSetup.qml @@ -394,6 +394,7 @@ Item { MouseArea { anchors.fill: parent; propagateComposedEvents: false; + hoverEnabled: true; } Image { diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml index f66781c919..24b6c6b9a1 100644 --- a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml +++ b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml @@ -43,6 +43,7 @@ Item { width: parent.width; height: (root.shouldShowTopAndBottomOfWallet || root.shouldShowTopOfWallet) ? parent.height : parent.height - root.parentAppTitleBarHeight - root.parentAppNavBarHeight; propagateComposedEvents: false; + hoverEnabled: true; } Connections { @@ -326,6 +327,7 @@ Item { MouseArea { anchors.fill: parent; propagateComposedEvents: false; + hoverEnabled: true; } ListModel { @@ -477,6 +479,7 @@ Item { enabled: connectionsList.currentIndex !== index; anchors.fill: parent; propagateComposedEvents: false; + hoverEnabled: true; onClicked: { connectionsList.currentIndex = index; } @@ -505,6 +508,7 @@ Item { MouseArea { anchors.fill: parent; propagateComposedEvents: false; + hoverEnabled: true; } Rectangle { @@ -1059,6 +1063,7 @@ Item { MouseArea { anchors.fill: parent; propagateComposedEvents: false; + hoverEnabled: true; } AnimatedImage { From f26477b3e16d00215593b51c296c05cef2e5c167 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 2 Feb 2018 11:00:32 -0800 Subject: [PATCH 57/57] Slight wording change to Optional Message placeholder --- .../resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml index 16b56407ac..4ef80234dc 100644 --- a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml +++ b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml @@ -926,7 +926,7 @@ Item { id: optionalMessage; property int maximumLength: 72; property string previousText: text; - placeholderText: "Optional Message (" + maximumLength + " character limit)"; + placeholderText: "Optional Public Message (" + maximumLength + " character limit)"; font.family: firaSansSemiBold.name; font.pixelSize: 20; // Anchors