fixing up material entity logic, refresh reference material on material change

This commit is contained in:
HifiExperiments 2021-03-17 19:10:29 -07:00
parent 9514ade844
commit 3fdb398829
8 changed files with 84 additions and 13 deletions

View file

@ -79,26 +79,42 @@ void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo
} }
} }
bool usingMaterialData = _materialURL.startsWith("materialData");
bool usingEntityID = _materialURL.startsWith("{");
bool materialDataChanged = false;
bool urlChanged = false; bool urlChanged = false;
std::string newCurrentMaterialName = _currentMaterialName; std::string newCurrentMaterialName = _currentMaterialName;
QString targetEntityID = _materialURL;
{ {
QString materialURL = entity->getMaterialURL(); QString materialURL = entity->getMaterialURL();
if (materialURL != _materialURL) { if (materialURL != _materialURL) {
_materialURL = materialURL; _materialURL = materialURL;
usingMaterialData = _materialURL.startsWith("materialData");
usingEntityID = _materialURL.startsWith("{");
targetEntityID = _materialURL;
if (_materialURL.contains("#")) { if (_materialURL.contains("#")) {
auto split = _materialURL.split("#"); auto split = _materialURL.split("#");
newCurrentMaterialName = split.last().toStdString(); newCurrentMaterialName = split.last().toStdString();
if (usingEntityID) {
targetEntityID = split.first();
}
} else if (_materialURL.contains("?")) { } else if (_materialURL.contains("?")) {
qDebug() << "DEPRECATED: Use # instead of ? for material URLS:" << _materialURL; qDebug() << "DEPRECATED: Use # instead of ? for material URLS:" << _materialURL;
auto split = _materialURL.split("?"); auto split = _materialURL.split("?");
newCurrentMaterialName = split.last().toStdString(); 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; QUuid oldParentID = _parentID;
QString oldParentMaterialName = _parentMaterialName; QString oldParentMaterialName = _parentMaterialName;
{ {
@ -135,7 +151,7 @@ void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo
} }
} }
if (urlChanged && !usingMaterialData) { if (urlChanged && !usingMaterialData && !usingEntityID) {
_networkMaterial = DependencyManager::get<MaterialCache>()->getMaterial(_materialURL); _networkMaterial = DependencyManager::get<MaterialCache>()->getMaterial(_materialURL);
auto onMaterialRequestFinished = [this, entity, oldParentID, oldParentMaterialName, newCurrentMaterialName](bool success) { auto onMaterialRequestFinished = [this, entity, oldParentID, oldParentMaterialName, newCurrentMaterialName](bool success) {
deleteMaterial(oldParentID, oldParentMaterialName); 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) { } else if (materialDataChanged && usingMaterialData) {
deleteMaterial(oldParentID, oldParentMaterialName); deleteMaterial(oldParentID, oldParentMaterialName);
_texturesLoaded = false; _texturesLoaded = false;
@ -167,6 +190,10 @@ void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo
setCurrentMaterialName(newCurrentMaterialName); setCurrentMaterialName(newCurrentMaterialName);
applyMaterial(entity); applyMaterial(entity);
} else { } else {
if (newCurrentMaterialName != _currentMaterialName) {
setCurrentMaterialName(newCurrentMaterialName);
}
if (deleteNeeded) { if (deleteNeeded) {
deleteMaterial(oldParentID, oldParentMaterialName); deleteMaterial(oldParentID, oldParentMaterialName);
} }

View file

@ -285,16 +285,29 @@ void MultiMaterial::calculateMaterialInfo() const {
void MultiMaterial::resetReferenceTexturesAndMaterials() { void MultiMaterial::resetReferenceTexturesAndMaterials() {
_referenceTextures.clear(); _referenceTextures.clear();
_referenceMaterials.clear();
} }
void MultiMaterial::addReferenceTexture(const std::function<gpu::TexturePointer()>& textureOperator) { void MultiMaterial::addReferenceTexture(const std::function<gpu::TexturePointer()>& textureOperator) {
_referenceTextures.emplace_back(textureOperator, textureOperator()); _referenceTextures.emplace_back(textureOperator, textureOperator());
} }
void MultiMaterial::addReferenceMaterial(const std::function<graphics::MaterialPointer()>& materialOperator) {
_referenceMaterials.emplace_back(materialOperator, materialOperator());
}
bool MultiMaterial::anyReferenceMaterialsOrTexturesChanged() const { bool MultiMaterial::anyReferenceMaterialsOrTexturesChanged() const {
for (auto textureOperatorPair : _referenceTextures) { for (auto textureOperatorPair : _referenceTextures) {
if (textureOperatorPair.first() != textureOperatorPair.second) { if (textureOperatorPair.first() != textureOperatorPair.second) {
return true; return true;
} }
} }
for (auto materialOperatorPair : _referenceMaterials) {
if (materialOperatorPair.first() != materialOperatorPair.second) {
return true;
}
}
return false;
} }

View file

@ -430,6 +430,8 @@ public:
virtual bool isReady() const { return true; } virtual bool isReady() const { return true; }
virtual QString getProceduralString() const { return QString(); } virtual QString getProceduralString() const { return QString(); }
virtual bool isReference() const { return false; }
static const std::string HIFI_PBR; static const std::string HIFI_PBR;
static const std::string HIFI_SHADER_SIMPLE; static const std::string HIFI_SHADER_SIMPLE;
@ -555,6 +557,7 @@ public:
void resetReferenceTexturesAndMaterials(); void resetReferenceTexturesAndMaterials();
void addReferenceTexture(const std::function<gpu::TexturePointer()>& textureOperator); void addReferenceTexture(const std::function<gpu::TexturePointer()>& textureOperator);
void addReferenceMaterial(const std::function<graphics::MaterialPointer()>& materialOperator);
private: private:
gpu::BufferView _schemaBuffer; gpu::BufferView _schemaBuffer;
@ -572,6 +575,7 @@ private:
bool anyReferenceMaterialsOrTexturesChanged() const; bool anyReferenceMaterialsOrTexturesChanged() const;
std::vector<std::pair<std::function<gpu::TexturePointer()>, gpu::TexturePointer>> _referenceTextures; std::vector<std::pair<std::function<gpu::TexturePointer()>, gpu::TexturePointer>> _referenceTextures;
std::vector<std::pair<std::function<graphics::MaterialPointer()>, graphics::MaterialPointer>> _referenceMaterials;
}; };
}; };

View file

@ -111,6 +111,17 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater
return toReturn; 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 /**jsdoc
* A material used in a {@link Entities.MaterialResource|MaterialResource}. * A material used in a {@link Entities.MaterialResource|MaterialResource}.
* @typedef {object} Entities.Material * @typedef {object} Entities.Material

View file

@ -100,7 +100,8 @@ public:
ParsedMaterials parsedMaterials; ParsedMaterials parsedMaterials;
static ParsedMaterials parseJSONMaterials(const QJsonDocument& materialJSON, const QUrl& baseUrl); static ParsedMaterials parseJSONMaterials(const QJsonDocument& materialJSON, const QUrl& baseUrl);
static std::pair<std::string, std::shared_ptr<NetworkMaterial>> parseJSONMaterial(const QJsonValue& materialJSONValue, const QUrl& baseUrl); static ParsedMaterials parseMaterialForUUID(const QJsonValue& entityIDJSON);
static std::pair<std::string, std::shared_ptr<NetworkMaterial>> parseJSONMaterial(const QJsonValue& materialJSONValue, const QUrl& baseUrl = QUrl());
private: private:
static bool parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB); static bool parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB);

View file

@ -8,7 +8,14 @@
#include "ReferenceMaterial.h" #include "ReferenceMaterial.h"
std::function<graphics::MaterialPointer(QUuid)> ReferenceMaterial::_materialForUUIDOperator = nullptr; std::function<graphics::MaterialPointer(QUuid)> ReferenceMaterial::_unboundMaterialForUUIDOperator = nullptr;
ReferenceMaterial::ReferenceMaterial(QUuid uuid) :
graphics::ProceduralMaterial() {
if (_unboundMaterialForUUIDOperator) {
_materialForUUIDOperator = std::bind(_unboundMaterialForUUIDOperator, uuid);
}
}
// Material // Material
const graphics::MaterialKey& ReferenceMaterial::getKey() const { const graphics::MaterialKey& ReferenceMaterial::getKey() const {
@ -153,14 +160,14 @@ void ReferenceMaterial::initializeProcedural() {
graphics::MaterialPointer ReferenceMaterial::getMaterial() const { graphics::MaterialPointer ReferenceMaterial::getMaterial() const {
if (_materialForUUIDOperator) { if (_materialForUUIDOperator) {
return _materialForUUIDOperator(_uuid); return _materialForUUIDOperator();
} }
return nullptr; return nullptr;
} }
std::shared_ptr<NetworkMaterial> ReferenceMaterial::getNetworkMaterial() const { std::shared_ptr<NetworkMaterial> ReferenceMaterial::getNetworkMaterial() const {
if (_materialForUUIDOperator) { if (_materialForUUIDOperator) {
auto material = _materialForUUIDOperator(_uuid); auto material = _materialForUUIDOperator();
if (material && material->isProcedural()) { if (material && material->isProcedural()) {
return std::static_pointer_cast<NetworkMaterial>(material); return std::static_pointer_cast<NetworkMaterial>(material);
} }
@ -170,7 +177,7 @@ std::shared_ptr<NetworkMaterial> ReferenceMaterial::getNetworkMaterial() const {
graphics::ProceduralMaterialPointer ReferenceMaterial::getProceduralMaterial() const { graphics::ProceduralMaterialPointer ReferenceMaterial::getProceduralMaterial() const {
if (_materialForUUIDOperator) { if (_materialForUUIDOperator) {
auto material = _materialForUUIDOperator(_uuid); auto material = _materialForUUIDOperator();
if (material && material->isProcedural()) { if (material && material->isProcedural()) {
return std::static_pointer_cast<graphics::ProceduralMaterial>(material); return std::static_pointer_cast<graphics::ProceduralMaterial>(material);
} }

View file

@ -15,7 +15,7 @@ public:
using Parent = graphics::ProceduralMaterial; using Parent = graphics::ProceduralMaterial;
ReferenceMaterial() {} ReferenceMaterial() {}
ReferenceMaterial(QUuid uuid) : graphics::ProceduralMaterial(), _uuid(uuid) {} ReferenceMaterial(QUuid uuid);
// Material // Material
const graphics::MaterialKey& getKey() const override; const graphics::MaterialKey& getKey() const override;
@ -54,11 +54,14 @@ public:
const uint64_t& created, const ProceduralProgramKey key = ProceduralProgramKey()) override; const uint64_t& created, const ProceduralProgramKey key = ProceduralProgramKey()) override;
void initializeProcedural() override; void initializeProcedural() override;
static void setMaterialForUUIDOperator(std::function<graphics::MaterialPointer(QUuid)> materialForUUIDOperator) { _materialForUUIDOperator = materialForUUIDOperator; } bool isReference() const override { return true; }
std::function<graphics::MaterialPointer()> getReferenceOperator() const { return _materialForUUIDOperator; }
static void setMaterialForUUIDOperator(std::function<graphics::MaterialPointer(QUuid)> materialForUUIDOperator) { _unboundMaterialForUUIDOperator = materialForUUIDOperator; }
private: private:
static std::function<graphics::MaterialPointer(QUuid)> _materialForUUIDOperator; static std::function<graphics::MaterialPointer(QUuid)> _unboundMaterialForUUIDOperator;
QUuid _uuid; std::function<graphics::MaterialPointer()> _materialForUUIDOperator;
graphics::MaterialPointer getMaterial() const; graphics::MaterialPointer getMaterial() const;
std::shared_ptr<NetworkMaterial> getNetworkMaterial() const; std::shared_ptr<NetworkMaterial> getNetworkMaterial() const;

View file

@ -19,6 +19,7 @@
#include <render/DrawTask.h> #include <render/DrawTask.h>
#include <shaders/Shaders.h> #include <shaders/Shaders.h>
#include <graphics/ShaderConstants.h> #include <graphics/ShaderConstants.h>
#include <procedural/ReferenceMaterial.h>
#include "render-utils/ShaderConstants.h" #include "render-utils/ShaderConstants.h"
#include "StencilMaskPass.h" #include "StencilMaskPass.h"
@ -409,6 +410,10 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
} }
materials.pop(); materials.pop();
if (material->isReference()) {
multiMaterial.addReferenceMaterial(std::static_pointer_cast<ReferenceMaterial>(material)->getReferenceOperator());
}
bool defaultFallthrough = material->getDefaultFallthrough(); bool defaultFallthrough = material->getDefaultFallthrough();
const auto& materialKey = material->getKey(); const auto& materialKey = material->getKey();
const auto& textureMaps = material->getTextureMaps(); const auto& textureMaps = material->getTextureMaps();