Merge pull request #16548 from HifiExperiments/visible

Case 17368: Fix wearables not disappearing with avatar
This commit is contained in:
Brad Hefta-Gaub 2019-12-13 13:20:15 -08:00 committed by GitHub
commit fb70569fc2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 137 additions and 107 deletions

View file

@ -2125,6 +2125,8 @@ void Avatar::updateAttachmentRenderIDs() {
void Avatar::updateDescendantRenderIDs() {
_subItemLock.withWriteLock([&] {
auto oldRenderingDescendantEntityIDs = _renderingDescendantEntityIDs;
_renderingDescendantEntityIDs.clear();
_descendantRenderIDs.clear();
auto entityTreeRenderer = DependencyManager::get<EntityTreeRenderer>();
EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr;
@ -2134,7 +2136,12 @@ void Avatar::updateDescendantRenderIDs() {
if (object && object->getNestableType() == NestableType::Entity) {
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(object);
if (entity->isVisible()) {
auto renderer = entityTreeRenderer->renderableForEntityId(object->getID());
auto id = object->getID();
_renderingDescendantEntityIDs.insert(id);
oldRenderingDescendantEntityIDs.erase(id);
entity->setCullWithParent(true);
auto renderer = entityTreeRenderer->renderableForEntityId(id);
if (renderer) {
render::ItemIDs renderableSubItems;
uint32_t numRenderableSubItems = renderer->metaFetchMetaSubItems(renderableSubItems);
@ -2145,6 +2152,13 @@ void Avatar::updateDescendantRenderIDs() {
}
}
});
for (auto& oldRenderingDescendantEntityID : oldRenderingDescendantEntityIDs) {
auto entity = entityTree->findEntityByEntityItemID(oldRenderingDescendantEntityID);
if (entity) {
entity->setCullWithParent(false);
}
}
});
}
});

View file

@ -783,6 +783,7 @@ protected:
render::ItemIDs _attachmentRenderIDs;
void updateDescendantRenderIDs();
render::ItemIDs _descendantRenderIDs;
std::unordered_set<EntityItemID> _renderingDescendantEntityIDs;
uint32_t _lastAncestorChainRenderableVersion { 0 };
};

View file

@ -177,6 +177,10 @@ ItemKey EntityRenderer::getKey() {
builder.withShadowCaster();
}
if (_cullWithParent) {
builder.withSubMetaCulled();
}
if (!_visible) {
builder.withInvisible();
}
@ -420,6 +424,7 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa
setRenderLayer(entity->getRenderLayer());
setPrimitiveMode(entity->getPrimitiveMode());
_canCastShadow = entity->getCanCastShadow();
setCullWithParent(entity->getCullWithParent());
_cauterized = entity->getCauterized();
entity->setNeedsRenderUpdate(false);
});

View file

@ -108,6 +108,7 @@ protected:
virtual void setIsVisibleInSecondaryCamera(bool value) { _isVisibleInSecondaryCamera = value; }
virtual void setRenderLayer(RenderLayer value) { _renderLayer = value; }
virtual void setPrimitiveMode(PrimitiveMode value) { _primitiveMode = value; }
virtual void setCullWithParent(bool value) { _cullWithParent = value; }
signals:
void requestRenderUpdate();
@ -130,6 +131,7 @@ protected:
bool _visible { false };
bool _isVisibleInSecondaryCamera { false };
bool _canCastShadow { false };
bool _cullWithParent { false };
RenderLayer _renderLayer { RenderLayer::WORLD };
PrimitiveMode _primitiveMode { PrimitiveMode::SOLID };
bool _cauterized { false };

View file

@ -210,8 +210,7 @@ void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo
}
ItemKey MaterialEntityRenderer::getKey() {
ItemKey::Builder builder;
builder.withTypeShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
auto builder = ItemKey::Builder().withTypeShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
if (!_visible) {
builder.withInvisible();

View file

@ -997,8 +997,10 @@ ModelEntityRenderer::ModelEntityRenderer(const EntityItemPointer& entity) : Pare
void ModelEntityRenderer::setKey(bool didVisualGeometryRequestSucceed) {
auto builder = ItemKey::Builder().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
if (_model && _model->isGroupCulled()) {
if (!_cullWithParent && _model && _model->isGroupCulled()) {
builder.withMetaCullGroup();
} else if (_cullWithParent) {
builder.withSubMetaCulled();
}
if (didVisualGeometryRequestSucceed) {
@ -1437,6 +1439,14 @@ void ModelEntityRenderer::setPrimitiveMode(PrimitiveMode value) {
}
}
void ModelEntityRenderer::setCullWithParent(bool value) {
Parent::setCullWithParent(value);
setKey(_didLastVisualGeometryRequestSucceed);
if (_model) {
_model->setCullWithParent(_cullWithParent);
}
}
// NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items
void ModelEntityRenderer::doRender(RenderArgs* args) {
DETAILED_PROFILE_RANGE(render_detail, "MetaModelRender");

View file

@ -164,6 +164,7 @@ protected:
void setIsVisibleInSecondaryCamera(bool value) override;
void setRenderLayer(RenderLayer value) override;
void setPrimitiveMode(PrimitiveMode value) override;
void setCullWithParent(bool value) override;
private:
void animate(const TypedEntityPointer& entity);

View file

@ -151,11 +151,17 @@ void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEn
ItemKey ParticleEffectEntityRenderer::getKey() {
// FIXME: implement isTransparent() for particles and an opaque pipeline
if (_visible) {
return ItemKey::Builder::transparentShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
} else {
return ItemKey::Builder().withInvisible().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()).build();
auto builder = ItemKey::Builder::transparentShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
if (!_visible) {
builder.withInvisible();
}
if (_cullWithParent) {
builder.withSubMetaCulled();
}
return builder.build();
}
ShapeKey ParticleEffectEntityRenderer::getShapeKey() {

View file

@ -97,9 +97,17 @@ void PolyLineEntityRenderer::buildPipelines() {
}
ItemKey PolyLineEntityRenderer::getKey() {
return isTransparent() ?
ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()) :
ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
auto builder = ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
if (isTransparent()) {
builder.withTransparent();
}
if (_cullWithParent) {
builder.withSubMetaCulled();
}
return builder.build();
}
ShapeKey PolyLineEntityRenderer::getShapeKey() {

View file

@ -1776,6 +1776,16 @@ PolyVoxEntityRenderer::PolyVoxEntityRenderer(const EntityItemPointer& entity) :
_params = std::make_shared<gpu::Buffer>(sizeof(glm::vec4), nullptr);
}
ItemKey PolyVoxEntityRenderer::getKey() {
auto builder = ItemKey::Builder::opaqueShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
if (_cullWithParent) {
builder.withSubMetaCulled();
}
return builder.build();
}
ShapeKey PolyVoxEntityRenderer::getShapeKey() {
auto builder = ShapeKey::Builder().withCustom(CUSTOM_PIPELINE_NUMBER);
if (_primitiveMode == PrimitiveMode::LINES) {

View file

@ -209,7 +209,7 @@ public:
}
protected:
virtual ItemKey getKey() override { return ItemKey::Builder::opaqueShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); }
virtual ItemKey getKey() override;
virtual ShapeKey getShapeKey() override;
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;

View file

@ -3027,6 +3027,21 @@ void EntityItem::setCanCastShadow(bool value) {
});
}
bool EntityItem::getCullWithParent() const {
bool result;
withReadLock([&] {
result = _cullWithParent;
});
return result;
}
void EntityItem::setCullWithParent(bool value) {
withWriteLock([&] {
_needsRenderUpdate |= _cullWithParent != value;
_cullWithParent = value;
});
}
bool EntityItem::isChildOfMyAvatar() const {
QUuid ancestorID = findAncestorOfType(NestableType::Avatar);
return !ancestorID.isNull() && (ancestorID == Physics::getSessionUUID() || ancestorID == AVATAR_SELF_ID);

View file

@ -307,6 +307,9 @@ public:
bool getCanCastShadow() const;
void setCanCastShadow(bool value);
bool getCullWithParent() const;
void setCullWithParent(bool value);
void setCauterized(bool value);
bool getCauterized() const;
@ -767,6 +770,8 @@ protected:
QHash<QUuid, EntityDynamicPointer> _grabActions;
bool _cullWithParent { false };
mutable bool _needsRenderUpdate { false };
private:

View file

@ -106,6 +106,10 @@ void MeshPartPayload::updateKey(const render::ItemKey& key) {
builder.withTransparent();
}
if (_cullWithParent) {
builder.withSubMetaCulled();
}
_itemKey = builder.build();
}
@ -368,6 +372,10 @@ void ModelMeshPartPayload::updateKey(const render::ItemKey& key) {
builder.withTransparent();
}
if (_cullWithParent) {
builder.withSubMetaCulled();
}
_itemKey = builder.build();
}

View file

@ -44,7 +44,7 @@ public:
// Render Item interface
virtual render::ItemKey getKey() const;
virtual render::Item::Bound getBound() const;
virtual render::ShapeKey getShapeKey() const; // shape interface
virtual render::ShapeKey getShapeKey() const;
virtual void render(RenderArgs* args);
// ModelMeshPartPayload functions to perform render
@ -72,10 +72,13 @@ public:
void addMaterial(graphics::MaterialLayer material);
void removeMaterial(graphics::MaterialPointer material);
void setCullWithParent(bool value) { _cullWithParent = value; }
static bool enableMaterialProceduralShaders;
protected:
render::ItemKey _itemKey{ render::ItemKey::Builder::opaqueShape().build() };
bool _cullWithParent { false };
uint64_t _created;
};
@ -104,7 +107,7 @@ public:
void updateClusterBuffer(const std::vector<Model::TransformDualQuaternion>& clusterDualQuaternions);
// Render Item interface
render::ShapeKey getShapeKey() const override; // shape interface
render::ShapeKey getShapeKey() const override;
void render(RenderArgs* args) override;
void setShapeKey(bool invalidateShapeKey, PrimitiveMode primitiveMode, bool useDualQuaternionSkinning);

View file

@ -154,7 +154,7 @@ void Model::setOffset(const glm::vec3& offset) {
}
void Model::calculateTextureInfo() {
if (!_hasCalculatedTextureInfo && isLoaded() && getNetworkModel()->areTexturesLoaded() && !_modelMeshRenderItemIDs.empty()) {
if (!_hasCalculatedTextureInfo && isLoaded() && getNetworkModel()->areTexturesLoaded() && !_modelMeshRenderItems.isEmpty()) {
size_t textureSize = 0;
int textureCount = 0;
bool allTexturesLoaded = true;
@ -973,6 +973,22 @@ void Model::setCauterized(bool cauterized, const render::ScenePointer& scene) {
}
}
void Model::setCullWithParent(bool cullWithParent) {
if (_cullWithParent != cullWithParent) {
_cullWithParent = cullWithParent;
render::Transaction transaction;
auto renderItemsKey = _renderItemKeyGlobalFlags;
for(auto item : _modelMeshRenderItemIDs) {
transaction.updateItem<ModelMeshPartPayload>(item, [cullWithParent, renderItemsKey](ModelMeshPartPayload& data) {
data.setCullWithParent(cullWithParent);
data.updateKey(renderItemsKey);
});
}
AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction);
}
}
const render::ItemKey Model::getRenderItemKeyGlobalFlags() const {
return _renderItemKeyGlobalFlags;
}

View file

@ -129,6 +129,8 @@ public:
bool isCauterized() const { return _cauterized; }
void setCauterized(bool value, const render::ScenePointer& scene);
void setCullWithParent(bool value);
// Access the current RenderItemKey Global Flags used by the model and applied to the render items representing the parts of the model.
const render::ItemKey getRenderItemKeyGlobalFlags() const;
@ -515,6 +517,7 @@ protected:
//
render::ItemKey _renderItemKeyGlobalFlags;
bool _cauterized { false };
bool _cullWithParent { false };
bool shouldInvalidatePayloadShapeKey(int meshIndex);

View file

@ -61,12 +61,12 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende
const auto currentKeyLight = setupOutput.getN<RenderShadowSetup::Output>(4);
// Fetch and cull the items from the scene
static const auto shadowCasterReceiverFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask);
static const auto shadowCasterReceiverFilter = ItemFilter::Builder::visibleWorldItems().withOpaque().withoutLayered().withTagBits(tagBits, tagMask);
const auto fetchInput = FetchSpatialTree::Inputs(shadowCasterReceiverFilter, queryResolution).asVarying();
const auto shadowSelection = task.addJob<FetchSpatialTree>("FetchShadowTree", fetchInput);
const auto selectionInputs = FilterSpatialSelection::Inputs(shadowSelection, shadowCasterReceiverFilter).asVarying();
const auto shadowItems = task.addJob<FilterSpatialSelection>("FilterShadowSelection", selectionInputs);
const auto selectionInputs = CullSpatialSelection::Inputs(shadowSelection, shadowCasterReceiverFilter).asVarying();
const auto shadowItems = task.addJob<CullSpatialSelection>("FilterShadowSelection", selectionInputs, nullptr, true, RenderDetails::SHADOW);
// Cull objects that are not visible in camera view. Hopefully the cull functor only performs LOD culling, not
// frustum culling or this will make shadow casters out of the camera frustum disappear.

View file

@ -172,7 +172,7 @@ void FetchSpatialTree::run(const RenderContextPointer& renderContext, const Inpu
void CullSpatialSelection::configure(const Config& config) {
_justFrozeFrustum = _justFrozeFrustum || (config.freezeFrustum && !_freezeFrustum);
_freezeFrustum = config.freezeFrustum;
_skipCulling = config.skipCulling;
_overrideSkipCulling = config.skipCulling;
}
void CullSpatialSelection::run(const RenderContextPointer& renderContext,
@ -209,7 +209,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext,
// filter individually against the _filter
// visibility cull if partially selected ( octree cell contianing it was partial)
// distance cull if was a subcell item ( octree cell is way bigger than the item bound itself, so now need to test per item)
if (_skipCulling) {
if (_skipCulling || _overrideSkipCulling) {
// inside & fit items: filter only, culling is disabled
{
PerformanceTimer perfTimer("insideFitItems");
@ -444,69 +444,3 @@ void ApplyCullFunctorOnItemBounds::run(const RenderContextPointer& renderContext
args->popViewFrustum();
}
}
void FilterSpatialSelection::run(const RenderContextPointer& renderContext,
const Inputs& inputs, ItemBounds& outItems) {
assert(renderContext->args);
auto& scene = renderContext->_scene;
auto& inSelection = inputs.get0();
// Now we have a selection of items to render
outItems.clear();
outItems.reserve(inSelection.numItems());
const auto filter = inputs.get1();
if (!filter.selectsNothing()) {
// Now get the bound, and
// filter individually against the _filter
// inside & fit items: filter only
{
PerformanceTimer perfTimer("insideFitItems");
for (auto id : inSelection.insideItems) {
auto& item = scene->getItem(id);
if (filter.test(item.getKey())) {
ItemBound itemBound(id, item.getBound());
outItems.emplace_back(itemBound);
}
}
}
// inside & subcell items: filter only
{
PerformanceTimer perfTimer("insideSmallItems");
for (auto id : inSelection.insideSubcellItems) {
auto& item = scene->getItem(id);
if (filter.test(item.getKey())) {
ItemBound itemBound(id, item.getBound());
outItems.emplace_back(itemBound);
}
}
}
// partial & fit items: filter only
{
PerformanceTimer perfTimer("partialFitItems");
for (auto id : inSelection.partialItems) {
auto& item = scene->getItem(id);
if (filter.test(item.getKey())) {
ItemBound itemBound(id, item.getBound());
outItems.emplace_back(itemBound);
}
}
}
// partial & subcell items: filter only
{
PerformanceTimer perfTimer("partialSmallItems");
for (auto id : inSelection.partialSubcellItems) {
auto& item = scene->getItem(id);
if (filter.test(item.getKey())) {
ItemBound itemBound(id, item.getBound());
outItems.emplace_back(itemBound);
}
}
}
}
}

View file

@ -100,26 +100,25 @@ namespace render {
};
class CullSpatialSelection {
bool _freezeFrustum{ false }; // initialized by Config
bool _justFrozeFrustum{ false };
bool _skipCulling{ false };
ViewFrustum _frozenFrustum;
public:
using Config = CullSpatialSelectionConfig;
using Inputs = render::VaryingSet2<ItemSpatialTree::ItemSelection, ItemFilter>;
using JobModel = Job::ModelIO<CullSpatialSelection, Inputs, ItemBounds, Config>;
CullSpatialSelection(CullFunctor cullFunctor, RenderDetails::Type type) :
_cullFunctor{ cullFunctor },
CullSpatialSelection(CullFunctor cullFunctor, bool skipCulling, RenderDetails::Type type) :
_cullFunctor(cullFunctor),
_skipCulling(skipCulling),
_detailType(type) {}
CullSpatialSelection(CullFunctor cullFunctor) :
_cullFunctor{ cullFunctor } {
}
CullFunctor _cullFunctor;
bool _skipCulling { false };
RenderDetails::Type _detailType{ RenderDetails::OTHER };
bool _freezeFrustum { false }; // initialized by Config
bool _justFrozeFrustum { false };
bool _overrideSkipCulling { false };
ViewFrustum _frozenFrustum;
void configure(const Config& config);
void run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems);
};
@ -147,15 +146,6 @@ namespace render {
};
class FilterSpatialSelection {
public:
using Inputs = render::VaryingSet2<ItemSpatialTree::ItemSelection, ItemFilter>;
using JobModel = Job::ModelIO<FilterSpatialSelection, Inputs, ItemBounds>;
FilterSpatialSelection() {}
void run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems);
};
class ApplyCullFunctorOnItemBounds {
public:
using Inputs = render::VaryingSet2<ItemBounds, ViewFrustumPointer>;

View file

@ -625,7 +625,7 @@ template <> const ShapeKey shapeGetShapeKey(const PayloadProxyInterface::Pointer
typedef Item::PayloadPointer PayloadPointer;
typedef std::vector< PayloadPointer > Payloads;
typedef std::vector<PayloadPointer> Payloads;
// A map of items by ShapeKey to optimize rendering pipeline assignments
using ShapeBounds = std::unordered_map<ShapeKey, ItemBounds, ShapeKey::Hash, ShapeKey::KeyEqual>;

View file

@ -27,7 +27,7 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin
const auto fetchInput = FetchSpatialTree::Inputs(filter, glm::ivec2(0,0)).asVarying();
const auto spatialSelection = task.addJob<FetchSpatialTree>("FetchSceneSelection", fetchInput);
const auto cullInputs = CullSpatialSelection::Inputs(spatialSelection, spatialFilter).asVarying();
const auto culledSpatialSelection = task.addJob<CullSpatialSelection>("CullSceneSelection", cullInputs, cullFunctor, RenderDetails::ITEM);
const auto culledSpatialSelection = task.addJob<CullSpatialSelection>("CullSceneSelection", cullInputs, cullFunctor, false, RenderDetails::ITEM);
// Layered objects are not culled
const ItemFilter layeredFilter = ItemFilter::Builder::visibleWorldItems().withTagBits(tagBits, tagMask);