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;
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<MaterialCache>()->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);
}

View file

@ -285,16 +285,29 @@ void MultiMaterial::calculateMaterialInfo() const {
void MultiMaterial::resetReferenceTexturesAndMaterials() {
_referenceTextures.clear();
_referenceMaterials.clear();
}
void MultiMaterial::addReferenceTexture(const std::function<gpu::TexturePointer()>& textureOperator) {
_referenceTextures.emplace_back(textureOperator, textureOperator());
}
void MultiMaterial::addReferenceMaterial(const std::function<graphics::MaterialPointer()>& 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;
}

View file

@ -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<gpu::TexturePointer()>& textureOperator);
void addReferenceMaterial(const std::function<graphics::MaterialPointer()>& materialOperator);
private:
gpu::BufferView _schemaBuffer;
@ -572,6 +575,7 @@ private:
bool anyReferenceMaterialsOrTexturesChanged() const;
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;
}
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

View file

@ -100,7 +100,8 @@ public:
ParsedMaterials parsedMaterials;
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:
static bool parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB);

View file

@ -8,7 +8,14 @@
#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
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<NetworkMaterial> ReferenceMaterial::getNetworkMaterial() const {
if (_materialForUUIDOperator) {
auto material = _materialForUUIDOperator(_uuid);
auto material = _materialForUUIDOperator();
if (material && material->isProcedural()) {
return std::static_pointer_cast<NetworkMaterial>(material);
}
@ -170,7 +177,7 @@ std::shared_ptr<NetworkMaterial> 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<graphics::ProceduralMaterial>(material);
}

View file

@ -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<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:
static std::function<graphics::MaterialPointer(QUuid)> _materialForUUIDOperator;
QUuid _uuid;
static std::function<graphics::MaterialPointer(QUuid)> _unboundMaterialForUUIDOperator;
std::function<graphics::MaterialPointer()> _materialForUUIDOperator;
graphics::MaterialPointer getMaterial() const;
std::shared_ptr<NetworkMaterial> getNetworkMaterial() const;

View file

@ -19,6 +19,7 @@
#include <render/DrawTask.h>
#include <shaders/Shaders.h>
#include <graphics/ShaderConstants.h>
#include <procedural/ReferenceMaterial.h>
#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<ReferenceMaterial>(material)->getReferenceOperator());
}
bool defaultFallthrough = material->getDefaultFallthrough();
const auto& materialKey = material->getKey();
const auto& textureMaps = material->getTextureMaps();