From 3fdb39882935cc07490c83cd201963c78e94fdee Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Wed, 17 Mar 2021 19:10:29 -0700 Subject: [PATCH] fixing up material entity logic, refresh reference material on material change --- .../src/RenderableMaterialEntityItem.cpp | 35 ++++++++++++++++--- libraries/graphics/src/graphics/Material.cpp | 13 +++++++ libraries/graphics/src/graphics/Material.h | 4 +++ .../procedural/ProceduralMaterialCache.cpp | 11 ++++++ .../src/procedural/ProceduralMaterialCache.h | 3 +- .../src/procedural/ReferenceMaterial.cpp | 15 +++++--- .../src/procedural/ReferenceMaterial.h | 11 +++--- .../render-utils/src/RenderPipelines.cpp | 5 +++ 8 files changed, 84 insertions(+), 13 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index 8f8a2076f8..b8f829f4ba 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -79,26 +79,42 @@ void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo } } + bool usingMaterialData = _materialURL.startsWith("materialData"); + bool usingEntityID = _materialURL.startsWith("{"); + bool materialDataChanged = false; bool urlChanged = false; std::string newCurrentMaterialName = _currentMaterialName; + QString targetEntityID = _materialURL; { QString materialURL = entity->getMaterialURL(); if (materialURL != _materialURL) { _materialURL = materialURL; + usingMaterialData = _materialURL.startsWith("materialData"); + usingEntityID = _materialURL.startsWith("{"); + targetEntityID = _materialURL; if (_materialURL.contains("#")) { auto split = _materialURL.split("#"); newCurrentMaterialName = split.last().toStdString(); + if (usingEntityID) { + targetEntityID = split.first(); + } } else if (_materialURL.contains("?")) { qDebug() << "DEPRECATED: Use # instead of ? for material URLS:" << _materialURL; auto split = _materialURL.split("?"); newCurrentMaterialName = split.last().toStdString(); + if (usingEntityID) { + targetEntityID = split.first(); + } + } + + if (usingMaterialData) { + materialDataChanged = true; + } else { + urlChanged = true; } - urlChanged = true; } } - bool usingMaterialData = _materialURL.startsWith("materialData"); - bool materialDataChanged = false; QUuid oldParentID = _parentID; QString oldParentMaterialName = _parentMaterialName; { @@ -135,7 +151,7 @@ void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo } } - if (urlChanged && !usingMaterialData) { + if (urlChanged && !usingMaterialData && !usingEntityID) { _networkMaterial = DependencyManager::get()->getMaterial(_materialURL); auto onMaterialRequestFinished = [this, entity, oldParentID, oldParentMaterialName, newCurrentMaterialName](bool success) { deleteMaterial(oldParentID, oldParentMaterialName); @@ -159,6 +175,13 @@ void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo }); } } + } else if (urlChanged && usingEntityID) { + deleteMaterial(oldParentID, oldParentMaterialName); + _texturesLoaded = true; + _parsedMaterials = NetworkMaterialResource::parseMaterialForUUID(QJsonValue(targetEntityID)); + // Since our material changed, the current name might not be valid anymore, so we need to update + setCurrentMaterialName(newCurrentMaterialName); + applyMaterial(entity); } else if (materialDataChanged && usingMaterialData) { deleteMaterial(oldParentID, oldParentMaterialName); _texturesLoaded = false; @@ -167,6 +190,10 @@ void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo setCurrentMaterialName(newCurrentMaterialName); applyMaterial(entity); } else { + if (newCurrentMaterialName != _currentMaterialName) { + setCurrentMaterialName(newCurrentMaterialName); + } + if (deleteNeeded) { deleteMaterial(oldParentID, oldParentMaterialName); } diff --git a/libraries/graphics/src/graphics/Material.cpp b/libraries/graphics/src/graphics/Material.cpp index 91265b6bfc..836487de14 100755 --- a/libraries/graphics/src/graphics/Material.cpp +++ b/libraries/graphics/src/graphics/Material.cpp @@ -285,16 +285,29 @@ void MultiMaterial::calculateMaterialInfo() const { void MultiMaterial::resetReferenceTexturesAndMaterials() { _referenceTextures.clear(); + _referenceMaterials.clear(); } void MultiMaterial::addReferenceTexture(const std::function& textureOperator) { _referenceTextures.emplace_back(textureOperator, textureOperator()); } +void MultiMaterial::addReferenceMaterial(const std::function& materialOperator) { + _referenceMaterials.emplace_back(materialOperator, materialOperator()); +} + bool MultiMaterial::anyReferenceMaterialsOrTexturesChanged() const { for (auto textureOperatorPair : _referenceTextures) { if (textureOperatorPair.first() != textureOperatorPair.second) { return true; } } + + for (auto materialOperatorPair : _referenceMaterials) { + if (materialOperatorPair.first() != materialOperatorPair.second) { + return true; + } + } + + return false; } diff --git a/libraries/graphics/src/graphics/Material.h b/libraries/graphics/src/graphics/Material.h index 8caa4a3187..3abcb8b4c0 100755 --- a/libraries/graphics/src/graphics/Material.h +++ b/libraries/graphics/src/graphics/Material.h @@ -430,6 +430,8 @@ public: virtual bool isReady() const { return true; } virtual QString getProceduralString() const { return QString(); } + virtual bool isReference() const { return false; } + static const std::string HIFI_PBR; static const std::string HIFI_SHADER_SIMPLE; @@ -555,6 +557,7 @@ public: void resetReferenceTexturesAndMaterials(); void addReferenceTexture(const std::function& textureOperator); + void addReferenceMaterial(const std::function& materialOperator); private: gpu::BufferView _schemaBuffer; @@ -572,6 +575,7 @@ private: bool anyReferenceMaterialsOrTexturesChanged() const; std::vector, gpu::TexturePointer>> _referenceTextures; + std::vector, graphics::MaterialPointer>> _referenceMaterials; }; }; diff --git a/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp b/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp index 7e1a769c61..450995f4eb 100644 --- a/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp +++ b/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp @@ -111,6 +111,17 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater return toReturn; } +NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseMaterialForUUID(const QJsonValue& entityIDJSON) { + ParsedMaterials toReturn; + if (!entityIDJSON.isNull() && entityIDJSON.isString()) { + auto parsedMaterial = parseJSONMaterial(entityIDJSON); + toReturn.networkMaterials[parsedMaterial.first] = parsedMaterial.second; + toReturn.names.push_back(parsedMaterial.first); + } + + return toReturn; +} + /**jsdoc * A material used in a {@link Entities.MaterialResource|MaterialResource}. * @typedef {object} Entities.Material diff --git a/libraries/procedural/src/procedural/ProceduralMaterialCache.h b/libraries/procedural/src/procedural/ProceduralMaterialCache.h index 7b71438898..ff0a8cf81c 100644 --- a/libraries/procedural/src/procedural/ProceduralMaterialCache.h +++ b/libraries/procedural/src/procedural/ProceduralMaterialCache.h @@ -100,7 +100,8 @@ public: ParsedMaterials parsedMaterials; static ParsedMaterials parseJSONMaterials(const QJsonDocument& materialJSON, const QUrl& baseUrl); - static std::pair> parseJSONMaterial(const QJsonValue& materialJSONValue, const QUrl& baseUrl); + static ParsedMaterials parseMaterialForUUID(const QJsonValue& entityIDJSON); + static std::pair> parseJSONMaterial(const QJsonValue& materialJSONValue, const QUrl& baseUrl = QUrl()); private: static bool parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB); diff --git a/libraries/procedural/src/procedural/ReferenceMaterial.cpp b/libraries/procedural/src/procedural/ReferenceMaterial.cpp index 389224c60b..acb9dd5369 100644 --- a/libraries/procedural/src/procedural/ReferenceMaterial.cpp +++ b/libraries/procedural/src/procedural/ReferenceMaterial.cpp @@ -8,7 +8,14 @@ #include "ReferenceMaterial.h" -std::function ReferenceMaterial::_materialForUUIDOperator = nullptr; +std::function ReferenceMaterial::_unboundMaterialForUUIDOperator = nullptr; + +ReferenceMaterial::ReferenceMaterial(QUuid uuid) : + graphics::ProceduralMaterial() { + if (_unboundMaterialForUUIDOperator) { + _materialForUUIDOperator = std::bind(_unboundMaterialForUUIDOperator, uuid); + } +} // Material const graphics::MaterialKey& ReferenceMaterial::getKey() const { @@ -153,14 +160,14 @@ void ReferenceMaterial::initializeProcedural() { graphics::MaterialPointer ReferenceMaterial::getMaterial() const { if (_materialForUUIDOperator) { - return _materialForUUIDOperator(_uuid); + return _materialForUUIDOperator(); } return nullptr; } std::shared_ptr ReferenceMaterial::getNetworkMaterial() const { if (_materialForUUIDOperator) { - auto material = _materialForUUIDOperator(_uuid); + auto material = _materialForUUIDOperator(); if (material && material->isProcedural()) { return std::static_pointer_cast(material); } @@ -170,7 +177,7 @@ std::shared_ptr ReferenceMaterial::getNetworkMaterial() const { graphics::ProceduralMaterialPointer ReferenceMaterial::getProceduralMaterial() const { if (_materialForUUIDOperator) { - auto material = _materialForUUIDOperator(_uuid); + auto material = _materialForUUIDOperator(); if (material && material->isProcedural()) { return std::static_pointer_cast(material); } diff --git a/libraries/procedural/src/procedural/ReferenceMaterial.h b/libraries/procedural/src/procedural/ReferenceMaterial.h index fcefac8407..393ef10816 100644 --- a/libraries/procedural/src/procedural/ReferenceMaterial.h +++ b/libraries/procedural/src/procedural/ReferenceMaterial.h @@ -15,7 +15,7 @@ public: using Parent = graphics::ProceduralMaterial; ReferenceMaterial() {} - ReferenceMaterial(QUuid uuid) : graphics::ProceduralMaterial(), _uuid(uuid) {} + ReferenceMaterial(QUuid uuid); // Material const graphics::MaterialKey& getKey() const override; @@ -54,11 +54,14 @@ public: const uint64_t& created, const ProceduralProgramKey key = ProceduralProgramKey()) override; void initializeProcedural() override; - static void setMaterialForUUIDOperator(std::function materialForUUIDOperator) { _materialForUUIDOperator = materialForUUIDOperator; } + bool isReference() const override { return true; } + std::function getReferenceOperator() const { return _materialForUUIDOperator; } + + static void setMaterialForUUIDOperator(std::function materialForUUIDOperator) { _unboundMaterialForUUIDOperator = materialForUUIDOperator; } private: - static std::function _materialForUUIDOperator; - QUuid _uuid; + static std::function _unboundMaterialForUUIDOperator; + std::function _materialForUUIDOperator; graphics::MaterialPointer getMaterial() const; std::shared_ptr getNetworkMaterial() const; diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index b1c927761e..3e760b2110 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include "render-utils/ShaderConstants.h" #include "StencilMaskPass.h" @@ -409,6 +410,10 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial } materials.pop(); + if (material->isReference()) { + multiMaterial.addReferenceMaterial(std::static_pointer_cast(material)->getReferenceOperator()); + } + bool defaultFallthrough = material->getDefaultFallthrough(); const auto& materialKey = material->getKey(); const auto& textureMaps = material->getTextureMaps();