From f64e5f2444343bd15a05dc0fee9fdb65477efc61 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 13 Feb 2018 13:06:26 -0800 Subject: [PATCH] Introducing the cull group --- .../src/avatars-renderer/Avatar.cpp | 2 +- libraries/render/src/render/CullTask.cpp | 24 +++++++++++++++++++ libraries/render/src/render/Item.cpp | 10 ++++++++ libraries/render/src/render/Item.h | 19 +++++++++++++++ .../src/render/RenderFetchCullSortTask.cpp | 4 ++-- 5 files changed, 56 insertions(+), 3 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 86635cd3bf..9cdd4e2d00 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().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); + return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1).withCullGroup(); } template <> const Item::Bound payloadGetBound(const AvatarSharedPointer& avatar) { return static_pointer_cast(avatar)->getBounds(); diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp index 4dec3030ef..467cf5adbf 100644 --- a/libraries/render/src/render/CullTask.cpp +++ b/libraries/render/src/render/CullTask.cpp @@ -227,6 +227,9 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, if (filter.test(item.getKey())) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); + if (item.getKey().isCullGroup()) { + item.fetchMetaSubItemBounds(outItems, (*scene)); + } } } } @@ -239,6 +242,9 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, if (filter.test(item.getKey())) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); + if (item.getKey().isCullGroup()) { + item.fetchMetaSubItemBounds(outItems, (*scene)); + } } } } @@ -251,6 +257,9 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, if (filter.test(item.getKey())) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); + if (item.getKey().isCullGroup()) { + item.fetchMetaSubItemBounds(outItems, (*scene)); + } } } } @@ -263,6 +272,9 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, if (filter.test(item.getKey())) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); + if (item.getKey().isCullGroup()) { + item.fetchMetaSubItemBounds(outItems, (*scene)); + } } } } @@ -277,6 +289,9 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, if (filter.test(item.getKey())) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); + if (item.getKey().isCullGroup()) { + item.fetchMetaSubItemBounds(outItems, (*scene)); + } } } } @@ -290,6 +305,9 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, ItemBound itemBound(id, item.getBound()); if (test.solidAngleTest(itemBound.bound)) { outItems.emplace_back(itemBound); + if (item.getKey().isCullGroup()) { + item.fetchMetaSubItemBounds(outItems, (*scene)); + } } } } @@ -304,6 +322,9 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, ItemBound itemBound(id, item.getBound()); if (test.frustumTest(itemBound.bound)) { outItems.emplace_back(itemBound); + if (item.getKey().isCullGroup()) { + item.fetchMetaSubItemBounds(outItems, (*scene)); + } } } } @@ -319,6 +340,9 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, if (test.frustumTest(itemBound.bound)) { if (test.solidAngleTest(itemBound.bound)) { outItems.emplace_back(itemBound); + if (item.getKey().isCullGroup()) { + item.fetchMetaSubItemBounds(outItems, (*scene)); + } } } } diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index 612dba076b..b8ca091c40 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -113,6 +113,16 @@ const ShapeKey Item::getShapeKey() const { return shapeKey; } +uint32_t Item::fetchMetaSubItemBounds(ItemBounds& subItemBounds, Scene& scene) const { + ItemIDs subItems; + auto numSubs = fetchMetaSubItems(subItems); + + for (auto id : subItems) { + subItemBounds.emplace_back(id, scene.getItem(id).getBound()); + } + return numSubs; +} + namespace render { template <> const ItemKey payloadGetKey(const PayloadProxyInterface::Pointer& payload) { if (!payload) { diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index ff4b3a0458..3c82e49e8d 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -78,11 +78,13 @@ public: INVISIBLE, // Visible or not in the scene? SHADOW_CASTER, // Item cast shadows LAYERED, // Item belongs to one of the layers different from the default layer + CULL_GROUP, // As a meta item, the culling of my sub items is based solely on my bounding box and my visibility in the 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) + __META_CULLED, // Reserved bit for sub item of a meta render item to indicate that the culling is tied to the culling of the meta render item, not this one NUM_FLAGS, // Not a valid flag }; @@ -122,6 +124,7 @@ public: Builder& withInvisible() { _flags.set(INVISIBLE); return (*this); } Builder& withShadowCaster() { _flags.set(SHADOW_CASTER); return (*this); } Builder& withLayered() { _flags.set(LAYERED); return (*this); } + Builder& withCullGroup() { _flags.set(CULL_GROUP); 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 @@ -132,6 +135,9 @@ public: static Builder transparentShape() { return Builder().withTypeShape().withTransparent(); } static Builder light() { return Builder().withTypeLight(); } static Builder background() { return Builder().withViewSpace().withLayered(); } + + // Not meant to be public, part of the inner item / key / filter system + Builder& __withMetaCulled() { _flags.set(__META_CULLED); return (*this); } }; ItemKey(const Builder& builder) : ItemKey(builder._flags) {} @@ -159,6 +165,9 @@ public: bool isLayered() const { return _flags[LAYERED]; } bool isSpatial() const { return !isLayered(); } + bool isCullGroup() const { return _flags[CULL_GROUP]; } + void setCullGroup(bool cullGroup) { (cullGroup ? _flags.set(CULL_GROUP) : _flags.reset(CULL_GROUP)); } + 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); } @@ -166,6 +175,9 @@ public: bool isSmall() const { return _flags[__SMALLER]; } void setSmaller(bool smaller) { (smaller ? _flags.set(__SMALLER) : _flags.reset(__SMALLER)); } + bool isMetaCulled() const { return _flags[__META_CULLED]; } + void setMetaCulled(bool metaCulled) { (metaCulled ? _flags.set(__META_CULLED) : _flags.reset(__META_CULLED)); } + bool operator==(const ItemKey& key) { return (_flags == key._flags); } bool operator!=(const ItemKey& key) { return (_flags != key._flags); } }; @@ -221,6 +233,12 @@ public: 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& withoutCullGroup() { _value.reset(ItemKey::CULL_GROUP); _mask.set(ItemKey::CULL_GROUP); return (*this); } + Builder& withCullGroup() { _value.set(ItemKey::CULL_GROUP); _mask.set(ItemKey::CULL_GROUP); return (*this); } + + Builder& withoutMetaCulled() { _value.reset(ItemKey::__META_CULLED); _mask.set(ItemKey::__META_CULLED); return (*this); } + Builder& withMetaCulled() { _value.set(ItemKey::__META_CULLED); _mask.set(ItemKey::__META_CULLED); 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 @@ -420,6 +438,7 @@ public: // Meta Type Interface uint32_t fetchMetaSubItems(ItemIDs& subItems) const { return _payload->fetchMetaSubItems(subItems); } + uint32_t fetchMetaSubItemBounds(ItemBounds& subItemBounds, Scene& scene) const; // Access the status const StatusPointer& getStatus() const { return _payload->getStatus(); } diff --git a/libraries/render/src/render/RenderFetchCullSortTask.cpp b/libraries/render/src/render/RenderFetchCullSortTask.cpp index 6fb9ba88aa..4fe5e2f1be 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.cpp +++ b/libraries/render/src/render/RenderFetchCullSortTask.cpp @@ -22,7 +22,7 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin // CPU jobs: // Fetch and cull the items from the scene - const ItemFilter filter = ItemFilter::Builder::visibleWorldItems().withoutLayered().withTagBits(tagBits, tagMask); + const ItemFilter filter = ItemFilter::Builder::visibleWorldItems().withoutLayered().withoutMetaCulled().withTagBits(tagBits, tagMask); const auto spatialFilter = render::Varying(filter); const auto fetchInput = FetchSpatialTree::Inputs(filter, glm::ivec2(0,0)).asVarying(); const auto spatialSelection = task.addJob("FetchSceneSelection", fetchInput); @@ -30,7 +30,7 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin const auto culledSpatialSelection = task.addJob("CullSceneSelection", cullInputs, cullFunctor, RenderDetails::ITEM); // Overlays are not culled - const ItemFilter overlayfilter = ItemFilter::Builder().withVisible().withTagBits(tagBits, tagMask); + const ItemFilter overlayfilter = ItemFilter::Builder().withVisible().withoutMetaCulled().withTagBits(tagBits, tagMask); const auto nonspatialFilter = render::Varying(overlayfilter); const auto nonspatialSelection = task.addJob("FetchOverlaySelection", nonspatialFilter);