From fc86525863df9eb5a2a01c948fa08f30e6cf616d Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 4 Apr 2018 12:00:06 +0200 Subject: [PATCH 1/9] Cleaned up a bit shadow map clear --- libraries/render-utils/src/RenderShadowTask.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 69c5b3c689..faa5889307 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -149,9 +149,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con batch.setStateScissorRect(viewport); batch.setFramebuffer(fbo); - batch.clearFramebuffer( - gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH, - vec4(vec3(1.0, 1.0, 1.0), 0.0), 1.0, 0, true); + batch.clearDepthFramebuffer(1.0, false); glm::mat4 projMat; Transform viewMat; From 573f399023eafd625212284f827ea3207f006f76 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 6 Apr 2018 14:45:16 +0200 Subject: [PATCH 2/9] Fixed incorrect shadow frustum far clip computation due to not taking into account shadow receivers --- .../render-utils/src/RenderShadowTask.cpp | 27 ++++++++++-------- libraries/render-utils/src/RenderShadowTask.h | 2 +- libraries/render/src/render/CullTask.cpp | 28 +++++++++++++------ libraries/render/src/render/CullTask.h | 2 +- 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index faa5889307..fbb4bba263 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -230,12 +230,11 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende const auto queryResolution = setupOutput.getN(2); // Fetch and cull the items from the scene - // Enable models to not cast shadows (otherwise, models will always cast shadows) - static const auto shadowCasterFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask).withShadowCaster(); + static const auto shadowCasterReceiverFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask); - const auto fetchInput = FetchSpatialTree::Inputs(shadowCasterFilter, queryResolution).asVarying(); + const auto fetchInput = FetchSpatialTree::Inputs(shadowCasterReceiverFilter, queryResolution).asVarying(); const auto shadowSelection = task.addJob("FetchShadowTree", fetchInput); - const auto selectionInputs = FetchSpatialSelection::Inputs(shadowSelection, shadowCasterFilter).asVarying(); + const auto selectionInputs = FetchSpatialSelection::Inputs(shadowSelection, shadowCasterReceiverFilter).asVarying(); const auto shadowItems = task.addJob("FetchShadowSelection", selectionInputs); // Cull objects that are not visible in camera view. Hopefully the cull functor only performs LOD culling, not @@ -259,21 +258,22 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende char jobName[64]; sprintf(jobName, "ShadowCascadeSetup%d", i); const auto cascadeSetupOutput = task.addJob(jobName, i, _cullFunctor, tagBits, tagMask); - const auto shadowFilter = cascadeSetupOutput.getN(0); + const auto shadowRenderFilter = cascadeSetupOutput.getN(0); + const auto shadowBoundsFilter = cascadeSetupOutput.getN(1); auto antiFrustum = render::Varying(ViewFrustumPointer()); - cascadeFrustums[i] = cascadeSetupOutput.getN(1); + cascadeFrustums[i] = cascadeSetupOutput.getN(2); if (i > 1) { antiFrustum = cascadeFrustums[i - 2]; } // CPU jobs: finer grained culling - const auto cullInputs = CullShapeBounds::Inputs(sortedShapes, shadowFilter, antiFrustum).asVarying(); + const auto cullInputs = CullShapeBounds::Inputs(sortedShapes, shadowRenderFilter, shadowBoundsFilter, antiFrustum).asVarying(); const auto culledShadowItemsAndBounds = task.addJob("CullShadowCascade", cullInputs, shadowCullFunctor, RenderDetails::SHADOW); // GPU jobs: Render to shadow map sprintf(jobName, "RenderShadowMap%d", i); task.addJob(jobName, culledShadowItemsAndBounds, shapePlumber, i); - task.addJob("ShadowCascadeTeardown", shadowFilter); + task.addJob("ShadowCascadeTeardown", shadowRenderFilter); } task.addJob("ShadowTeardown", setupOutput); @@ -404,7 +404,11 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon const auto globalShadow = lightStage->getCurrentKeyShadow(); if (globalShadow && _cascadeIndexgetCascadeCount()) { - output.edit0() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(_tagBits, _tagMask).withShadowCaster(); + auto baseFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(_tagBits, _tagMask); + // Second item filter is to filter items to keep in shadow frustum computation (here we need to keep shadow receivers) + output.edit1() = baseFilter; + // First item filter is to filter items to render in shadow map (so only keep casters) + output.edit0() = baseFilter.withShadowCaster(); // Set the keylight render args auto& cascade = globalShadow->getCascade(_cascadeIndex); @@ -417,10 +421,11 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon texelSize *= minTexelCount; _cullFunctor._minSquareSize = texelSize * texelSize; - output.edit1() = cascadeFrustum; + output.edit2() = cascadeFrustum; } else { output.edit0() = ItemFilter::Builder::nothing(); - output.edit1() = ViewFrustumPointer(); + output.edit1() = ItemFilter::Builder::nothing(); + output.edit2() = ViewFrustumPointer(); } } diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index 98b70c0c9f..19ffcb4234 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -118,7 +118,7 @@ private: class RenderShadowCascadeSetup { public: - using Outputs = render::VaryingSet2; + using Outputs = render::VaryingSet3; using JobModel = render::Job::ModelO; RenderShadowCascadeSetup(unsigned int cascadeIndex, RenderShadowTask::CullFunctor& cullFunctor, uint8_t tagBits = 0x00, uint8_t tagMask = 0x00) : diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp index f04427540a..b5819f114f 100644 --- a/libraries/render/src/render/CullTask.cpp +++ b/libraries/render/src/render/CullTask.cpp @@ -368,17 +368,19 @@ void CullShapeBounds::run(const RenderContextPointer& renderContext, const Input RenderArgs* args = renderContext->args; const auto& inShapes = inputs.get0(); - const auto& filter = inputs.get1(); - const auto& antiFrustum = inputs.get2(); + const auto& cullFilter = inputs.get1(); + const auto& boundsFilter = inputs.get2(); + const auto& antiFrustum = inputs.get3(); auto& outShapes = outputs.edit0(); auto& outBounds = outputs.edit1(); outShapes.clear(); outBounds = AABox(); - if (!filter.selectsNothing()) { + if (!cullFilter.selectsNothing() || !boundsFilter.selectsNothing()) { auto& details = args->_details.edit(_detailType); Test test(_cullFunctor, args, details, antiFrustum); + auto scene = args->_scene; for (auto& inItems : inShapes) { auto key = inItems.first; @@ -393,16 +395,26 @@ void CullShapeBounds::run(const RenderContextPointer& renderContext, const Input if (antiFrustum == nullptr) { for (auto& item : inItems.second) { if (test.solidAngleTest(item.bound) && test.frustumTest(item.bound)) { - outItems->second.emplace_back(item); - outBounds += item.bound; + const auto shapeKey = scene->getItem(item.id).getKey(); + if (cullFilter.test(shapeKey)) { + outItems->second.emplace_back(item); + } + if (boundsFilter.test(shapeKey)) { + outBounds += item.bound; + } } } } else { for (auto& item : inItems.second) { if (test.solidAngleTest(item.bound) && test.frustumTest(item.bound) && test.antiFrustumTest(item.bound)) { - outItems->second.emplace_back(item); - outBounds += item.bound; - } + const auto shapeKey = scene->getItem(item.id).getKey(); + if (cullFilter.test(shapeKey)) { + outItems->second.emplace_back(item); + } + if (boundsFilter.test(shapeKey)) { + outBounds += item.bound; + } + } } } details._rendered += (int)outItems->second.size(); diff --git a/libraries/render/src/render/CullTask.h b/libraries/render/src/render/CullTask.h index 3c5a30de89..47abe8a960 100644 --- a/libraries/render/src/render/CullTask.h +++ b/libraries/render/src/render/CullTask.h @@ -110,7 +110,7 @@ namespace render { class CullShapeBounds { public: - using Inputs = render::VaryingSet3; + using Inputs = render::VaryingSet4; using Outputs = render::VaryingSet2; using JobModel = Job::ModelIO; From f454dac709d5b709545a7e484f7c3eed30333594 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 9 May 2018 12:04:44 -0700 Subject: [PATCH 3/9] avoid div by zero when measuring acceleration --- libraries/physics/src/EntityMotionState.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index a801392b66..fbb4b69ce0 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -731,7 +731,9 @@ void EntityMotionState::measureBodyAcceleration() { // hence the equation for acceleration is: a = (v1 / (1 - D)^dt - v0) / dt glm::vec3 velocity = getBodyLinearVelocityGTSigma(); - _measuredAcceleration = (velocity / powf(1.0f - _body->getLinearDamping(), dt) - _lastVelocity) * invDt; + const float MIN_DAMPING_FACTOR = 0.01f; + float dampingAttenuationFactor = 1.0f / glm::max(powf(1.0f - _body->getLinearDamping(), dt), MIN_DAMPING_FACTOR); + _measuredAcceleration = (velocity * dampingAttenuationFactor - _lastVelocity) * invDt; _lastVelocity = velocity; if (numSubsteps > PHYSICS_ENGINE_MAX_NUM_SUBSTEPS) { // we fall in here when _lastMeasureStep is old: the body has just become active From b8d34f4b8fee9f754f7312f6351bc347db31ba85 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 9 May 2018 12:13:27 -0700 Subject: [PATCH 4/9] more correct variable name --- libraries/physics/src/EntityMotionState.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index fbb4b69ce0..e04055ec32 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -732,8 +732,8 @@ void EntityMotionState::measureBodyAcceleration() { glm::vec3 velocity = getBodyLinearVelocityGTSigma(); const float MIN_DAMPING_FACTOR = 0.01f; - float dampingAttenuationFactor = 1.0f / glm::max(powf(1.0f - _body->getLinearDamping(), dt), MIN_DAMPING_FACTOR); - _measuredAcceleration = (velocity * dampingAttenuationFactor - _lastVelocity) * invDt; + float invDampingAttenuationFactor = 1.0f / glm::max(powf(1.0f - _body->getLinearDamping(), dt), MIN_DAMPING_FACTOR); + _measuredAcceleration = (velocity * invDampingAttenuationFactor - _lastVelocity) * invDt; _lastVelocity = velocity; if (numSubsteps > PHYSICS_ENGINE_MAX_NUM_SUBSTEPS) { // we fall in here when _lastMeasureStep is old: the body has just become active From 50a53a5174bd3dc2a29131d0e316266c060a5d66 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 10 May 2018 16:00:01 -0700 Subject: [PATCH 5/9] fix lastEdited vs pal --- scripts/system/pal.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 0a01007ee9..84328001e1 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -251,6 +251,7 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See }); } break; + case 'refresh': // old name for refreshNearby case 'refreshNearby': data = {}; ExtendedOverlay.some(function (overlay) { // capture the audio data @@ -743,10 +744,13 @@ function receiveMessage(channel, messageString, senderID) { var message = JSON.parse(messageString); switch (message.method) { case 'select': - sendToQml(message); // Accepts objects, not just strings. + if (!onPalScreen) { + tablet.loadQMLSource(PAL_QML_SOURCE); + Script.setTimeout(function () { sendToQml(message); }, 1000); + } else { + sendToQml(message); // Accepts objects, not just strings. + } break; - default: - print('Unrecognized PAL message', messageString); } } From bf26aec260fe661b2391d1a92157c80c5c29b6cc Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 10 May 2018 16:39:56 -0700 Subject: [PATCH 6/9] untabify --- scripts/system/pal.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 84328001e1..c70c2729f5 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -744,12 +744,12 @@ function receiveMessage(channel, messageString, senderID) { var message = JSON.parse(messageString); switch (message.method) { case 'select': - if (!onPalScreen) { - tablet.loadQMLSource(PAL_QML_SOURCE); - Script.setTimeout(function () { sendToQml(message); }, 1000); - } else { + if (!onPalScreen) { + tablet.loadQMLSource(PAL_QML_SOURCE); + Script.setTimeout(function () { sendToQml(message); }, 1000); + } else { sendToQml(message); // Accepts objects, not just strings. - } + } break; } } From 81ebb681bb185ff5ec5430e981333425b79f7be8 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 14 May 2018 09:35:34 -0700 Subject: [PATCH 7/9] Show invalidated items in My Purchases --- .../resources/qml/hifi/commerce/purchases/Purchases.qml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index d79b8d09fa..0b95f26f55 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -995,10 +995,6 @@ Rectangle { for (var i = 0; i < purchasesModel.count; i++) { if (purchasesModel.get(i).title.toLowerCase().indexOf(filterBar.text.toLowerCase()) !== -1) { - if (!purchasesModel.get(i).valid) { - continue; - } - if (purchasesModel.get(i).status !== "confirmed" && !root.isShowingMyItems) { tempPurchasesModel.insert(0, purchasesModel.get(i)); } else if ((root.isShowingMyItems && purchasesModel.get(i).edition_number === "0") || @@ -1055,10 +1051,6 @@ Rectangle { var currentId; for (var i = 0; i < tempPurchasesModel.count; i++) { currentId = tempPurchasesModel.get(i).id; - - if (!purchasesModel.get(i).valid) { - continue; - } filteredPurchasesModel.append(tempPurchasesModel.get(i)); filteredPurchasesModel.setProperty(i, 'cardBackVisible', false); filteredPurchasesModel.setProperty(i, 'isInstalled', ((root.installedApps).indexOf(currentId) > -1)); From 2a1c2ba7b1ce7fe3e583117f4d2a3c2f18f0f2d4 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 14 May 2018 09:54:05 -0700 Subject: [PATCH 8/9] PurchasedItem logic --- .../resources/qml/hifi/commerce/purchases/PurchasedItem.qml | 5 ++++- .../resources/qml/hifi/commerce/purchases/Purchases.qml | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index 4db98091c1..17c42d1b08 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -49,6 +49,7 @@ Item { property string upgradeTitle; property bool updateAvailable: root.upgradeUrl !== "" && !root.isShowingMyItems; property bool isShowingMyItems; + property bool valid; property string originalStatusText; property string originalStatusColor; @@ -239,6 +240,7 @@ Item { width: 62; onLoaded: { + item.enabled = root.valid; item.buttonGlyphText = hifi.glyphs.gift; item.buttonText = "Gift"; item.buttonClicked = function() { @@ -646,7 +648,8 @@ Item { height: 40; enabled: root.hasPermissionToRezThis && root.purchaseStatus !== "invalidated" && - MyAvatar.skeletonModelURL !== root.itemHref; + MyAvatar.skeletonModelURL !== root.itemHref && + root.valid; onHoveredChanged: { if (hovered) { diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index 0b95f26f55..8fe1ebe6c9 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -616,6 +616,7 @@ Rectangle { upgradeTitle: model.upgrade_title; itemType: model.itemType; isShowingMyItems: root.isShowingMyItems; + valid: model.valid; anchors.topMargin: 10; anchors.bottomMargin: 10; From 83cae5460101cae5f8f5c3c76d3e76a24790ce3a Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 14 May 2018 13:34:20 -0700 Subject: [PATCH 9/9] Show 'invalidated' label for valid = false --- .../hifi/commerce/purchases/PurchasedItem.qml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index 17c42d1b08..19b57354dc 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -465,7 +465,7 @@ Item { Item { id: statusContainer; - visible: root.purchaseStatus === "pending" || root.purchaseStatus === "invalidated" || root.numberSold > -1; + visible: root.purchaseStatus === "pending" || !root.valid || root.numberSold > -1; anchors.left: itemName.left; anchors.right: itemName.right; anchors.top: itemName.bottom; @@ -482,7 +482,7 @@ Item { text: { if (root.purchaseStatus === "pending") { "PENDING..." - } else if (root.purchaseStatus === "invalidated") { + } else if (!root.valid) { "INVALIDATED" } else if (root.numberSold > -1) { ("Sales: " + root.numberSold + "/" + (root.limitedRun === -1 ? "\u221e" : root.limitedRun)) @@ -494,7 +494,7 @@ Item { color: { if (root.purchaseStatus === "pending") { hifi.colors.blueAccent - } else if (root.purchaseStatus === "invalidated") { + } else if (!root.valid) { hifi.colors.redAccent } else { hifi.colors.baseGray @@ -508,7 +508,7 @@ Item { text: { if (root.purchaseStatus === "pending") { hifi.glyphs.question - } else if (root.purchaseStatus === "invalidated") { + } else if (!root.valid) { hifi.glyphs.question } else { "" @@ -525,7 +525,7 @@ Item { color: { if (root.purchaseStatus === "pending") { hifi.colors.blueAccent - } else if (root.purchaseStatus === "invalidated") { + } else if (!root.valid) { hifi.colors.redAccent } else { hifi.colors.baseGray @@ -540,7 +540,7 @@ Item { onClicked: { if (root.purchaseStatus === "pending") { sendToPurchases({method: 'showPendingLightbox'}); - } else if (root.purchaseStatus === "invalidated") { + } else if (!root.valid) { sendToPurchases({method: 'showInvalidatedLightbox'}); } } @@ -548,7 +548,7 @@ Item { if (root.purchaseStatus === "pending") { statusText.color = hifi.colors.blueHighlight; statusIcon.color = hifi.colors.blueHighlight; - } else if (root.purchaseStatus === "invalidated") { + } else if (!root.valid) { statusText.color = hifi.colors.redAccent; statusIcon.color = hifi.colors.redAccent; } @@ -557,7 +557,7 @@ Item { if (root.purchaseStatus === "pending") { statusText.color = hifi.colors.blueAccent; statusIcon.color = hifi.colors.blueAccent; - } else if (root.purchaseStatus === "invalidated") { + } else if (!root.valid) { statusText.color = hifi.colors.redHighlight; statusIcon.color = hifi.colors.redHighlight; } @@ -647,7 +647,6 @@ Item { width: 160; height: 40; enabled: root.hasPermissionToRezThis && - root.purchaseStatus !== "invalidated" && MyAvatar.skeletonModelURL !== root.itemHref && root.valid;