mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 17:54:20 +02:00
Merge pull request #1102 from HifiExperiments/materials2
Material improvements 2: reference textures/materials by entity ID
This commit is contained in:
commit
d75df82687
25 changed files with 798 additions and 103 deletions
|
@ -164,6 +164,7 @@
|
|||
#include <RenderableWebEntityItem.h>
|
||||
#include <StencilMaskPass.h>
|
||||
#include <procedural/ProceduralMaterialCache.h>
|
||||
#include <procedural/ReferenceMaterial.h>
|
||||
#include "recording/ClipCache.h"
|
||||
|
||||
#include "AudioClient.h"
|
||||
|
@ -2158,6 +2159,32 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
return QSizeF(0.0f, 0.0f);
|
||||
});
|
||||
|
||||
Texture::setUnboundTextureForUUIDOperator([this](const QUuid& entityID) -> gpu::TexturePointer {
|
||||
if (_aboutToQuit) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto renderable = getEntities()->renderableForEntityId(entityID);
|
||||
if (renderable) {
|
||||
return renderable->getTexture();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
ReferenceMaterial::setMaterialForUUIDOperator([this](const QUuid& entityID) -> graphics::MaterialPointer {
|
||||
if (_aboutToQuit) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto renderable = getEntities()->renderableForEntityId(entityID);
|
||||
if (renderable) {
|
||||
return renderable->getTopMaterial();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
connect(this, &Application::aboutToQuit, [this]() {
|
||||
setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
|
||||
});
|
||||
|
|
|
@ -495,6 +495,15 @@ void EntityRenderer::removeMaterial(graphics::MaterialPointer material, const st
|
|||
emit requestRenderUpdate();
|
||||
}
|
||||
|
||||
graphics::MaterialPointer EntityRenderer::getTopMaterial() {
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
auto materials = _materials.find("0");
|
||||
if (materials != _materials.end()) {
|
||||
return materials->second.top().material;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EntityRenderer::Pipeline EntityRenderer::getPipelineType(const graphics::MultiMaterial& materials) {
|
||||
if (materials.top().material && materials.top().material->isProcedural() && materials.top().material->isReady()) {
|
||||
return Pipeline::PROCEDURAL;
|
||||
|
@ -626,6 +635,7 @@ void EntityRenderer::updateShapeKeyBuilderFromMaterials(ShapeKey::Builder& build
|
|||
{
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
materials = _materials.find("0");
|
||||
|
||||
if (materials != _materials.end()) {
|
||||
if (materials->second.shouldUpdate()) {
|
||||
RenderPipelines::updateMultiMaterial(materials->second);
|
||||
|
@ -653,7 +663,6 @@ void EntityRenderer::updateShapeKeyBuilderFromMaterials(ShapeKey::Builder& build
|
|||
auto pipelineType = getPipelineType(materials->second);
|
||||
if (pipelineType == Pipeline::MATERIAL) {
|
||||
builder.withMaterial();
|
||||
|
||||
if (drawMaterialKey.isNormalMap()) {
|
||||
builder.withTangents();
|
||||
}
|
||||
|
|
|
@ -62,7 +62,9 @@ public:
|
|||
};
|
||||
virtual void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName);
|
||||
virtual void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName);
|
||||
virtual graphics::MaterialPointer getTopMaterial();
|
||||
static Pipeline getPipelineType(const graphics::MultiMaterial& materials);
|
||||
virtual gpu::TexturePointer getTexture() { return nullptr; }
|
||||
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() override { return scriptable::ScriptableModelBase(); }
|
||||
|
||||
|
|
|
@ -198,10 +198,8 @@ void ImageEntityRenderer::doRender(RenderArgs* args) {
|
|||
procedural->prepare(*batch, transform.getTranslation(), transform.getScale(), transform.getRotation(), _created, ProceduralProgramKey(transparent));
|
||||
} else if (pipelineType == Pipeline::SIMPLE) {
|
||||
batch->setResourceTexture(0, _texture->getGPUTexture());
|
||||
} else {
|
||||
if (RenderPipelines::bindMaterials(materials, *batch, args->_renderMode, args->_enableTexturing)) {
|
||||
args->_details._materialSwitches++;
|
||||
}
|
||||
} else if (RenderPipelines::bindMaterials(materials, *batch, args->_renderMode, args->_enableTexturing)) {
|
||||
args->_details._materialSwitches++;
|
||||
}
|
||||
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(
|
||||
|
|
|
@ -24,6 +24,8 @@ public:
|
|||
ImageEntityRenderer(const EntityItemPointer& entity);
|
||||
~ImageEntityRenderer();
|
||||
|
||||
gpu::TexturePointer getTexture() override { return _texture ? _texture->getGPUTexture() : nullptr; }
|
||||
|
||||
protected:
|
||||
Item::Bound getBound(RenderArgs* args) override;
|
||||
ShapeKey getShapeKey() override;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ public:
|
|||
MaterialEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {}
|
||||
~MaterialEntityRenderer() { deleteMaterial(_parentID, _parentMaterialName); }
|
||||
|
||||
graphics::MaterialPointer getTopMaterial() override { return getMaterial(); }
|
||||
|
||||
private:
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
|
|
|
@ -274,6 +274,7 @@ void WebEntityRenderer::doRender(RenderArgs* args) {
|
|||
|
||||
// Try to update the texture
|
||||
OffscreenQmlSurface::TextureAndFence newTextureAndFence;
|
||||
QSize windowSize;
|
||||
bool newTextureAvailable = false;
|
||||
if (!resultWithReadLock<bool>([&] {
|
||||
if (!_webSurface) {
|
||||
|
@ -281,6 +282,7 @@ void WebEntityRenderer::doRender(RenderArgs* args) {
|
|||
}
|
||||
|
||||
newTextureAvailable = _webSurface->fetchTexture(newTextureAndFence);
|
||||
windowSize = _webSurface->size();
|
||||
return true;
|
||||
})) {
|
||||
return;
|
||||
|
@ -288,6 +290,8 @@ void WebEntityRenderer::doRender(RenderArgs* args) {
|
|||
|
||||
if (newTextureAvailable) {
|
||||
_texture->setExternalTexture(newTextureAndFence.first, newTextureAndFence.second);
|
||||
_texture->setSize(windowSize.width(), windowSize.height());
|
||||
_texture->setOriginalSize(windowSize.width(), windowSize.height());
|
||||
}
|
||||
|
||||
static const glm::vec2 texMin(0.0f), texMax(1.0f), topLeft(-0.5f), bottomRight(0.5f);
|
||||
|
|
|
@ -55,6 +55,8 @@ public:
|
|||
virtual void setProxyWindow(QWindow* proxyWindow) override;
|
||||
virtual QObject* getEventHandler() override;
|
||||
|
||||
gpu::TexturePointer getTexture() override { return _texture; }
|
||||
|
||||
protected:
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
|
|
|
@ -951,10 +951,11 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
*
|
||||
* @typedef {object} Entities.EntityProperties-Material
|
||||
* @property {Vec3} dimensions=0.1,0.1,0.1 - Used when <code>materialMappingMode == "projected"</code>.
|
||||
* @property {string} materialURL="" - URL to a {@link Entities.MaterialResource|MaterialResource}. If you append
|
||||
* <code>"#name"</code> to the URL, the material with that name in the {@link Entities.MaterialResource|MaterialResource}
|
||||
* will be applied to the entity. Alternatively, set the property value to <code>"materialData"</code> to use the
|
||||
* <code>materialData</code> property for the {@link Entities.MaterialResource|MaterialResource} values.
|
||||
* @property {string} materialURL="" - URL to a {@link Entities.MaterialResource|MaterialResource}. Alternatively, set the
|
||||
* property value to <code>"materialData"</code> to use the <code>materialData</code> property for the
|
||||
* {@link Entities.MaterialResource|MaterialResource} values. If you append <code>"#name"</code> to the URL, the material
|
||||
* with that name will be applied to the entity. You can also use the ID of another Material entity as the URL, in which
|
||||
* case this material will act as a copy of that material, with its own unique material transform, priority, etc.
|
||||
* @property {string} materialData="" - Used to store {@link Entities.MaterialResource|MaterialResource} data as a JSON string.
|
||||
* You can use <code>JSON.parse()</code> to parse the string into a JavaScript object which you can manipulate the
|
||||
* properties of, and use <code>JSON.stringify()</code> to convert the object into a string to put in the property.
|
||||
|
@ -1379,7 +1380,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
/*@jsdoc
|
||||
* The <code>"Web"</code> {@link Entities.EntityType|EntityType} displays a browsable web page. Each user views their own copy
|
||||
* of the web page: if one user navigates to another page on the entity, other users do not see the change; if a video is being
|
||||
* played, users don't see it in sync. It has properties in addition to the common
|
||||
* played, users don't see it in sync. Internally, a Web entity is rendered as a non-repeating, upside down texture, so additional
|
||||
* transformations may be necessary if you reference a Web entity texture by UUID. It has properties in addition to the common
|
||||
* {@link Entities.EntityProperties|EntityProperties}.
|
||||
*
|
||||
* @typedef {object} Entities.EntityProperties-Web
|
||||
|
|
|
@ -2751,6 +2751,47 @@ QVector<EntityItemID> EntityTree::sendEntities(EntityEditPacketSender* packetSen
|
|||
return map.values().toVector();
|
||||
}
|
||||
|
||||
QJsonValue replaceEntityIDsInJSONHelper(const QJsonValue& jsonValue, std::function<EntityItemID(EntityItemID)> getMapped) {
|
||||
if (jsonValue.isString()) {
|
||||
QString stringValue = jsonValue.toString();
|
||||
QUuid oldID = stringValue;
|
||||
if (!oldID.isNull()) {
|
||||
return QJsonValue(getMapped(oldID).toString());
|
||||
}
|
||||
return stringValue;
|
||||
} else if (jsonValue.isArray()) {
|
||||
QJsonArray jsonArray = jsonValue.toArray();
|
||||
for (int i = 0; i < jsonArray.count(); i++) {
|
||||
jsonArray[i] = replaceEntityIDsInJSONHelper(jsonArray[i], getMapped);
|
||||
}
|
||||
return jsonArray;
|
||||
} else if (jsonValue.isObject()) {
|
||||
QJsonObject jsonObject = jsonValue.toObject();
|
||||
auto keys = jsonObject.keys();
|
||||
for (auto& key : keys) {
|
||||
auto value = jsonObject.value(key);
|
||||
jsonObject[key] = replaceEntityIDsInJSONHelper(value, getMapped);
|
||||
}
|
||||
return jsonObject;
|
||||
} else {
|
||||
return jsonValue;
|
||||
}
|
||||
}
|
||||
|
||||
QString replaceEntityIDsInJSON(const QString& json, std::function<EntityItemID(EntityItemID)> getMapped) {
|
||||
QJsonDocument document = QJsonDocument::fromJson(json.toUtf8());
|
||||
if (!document.isNull() && document.isObject()) {
|
||||
QJsonObject jsonObject = document.object();
|
||||
auto keys = jsonObject.keys();
|
||||
for (auto& key : keys) {
|
||||
auto value = jsonObject.value(key);
|
||||
jsonObject[key] = replaceEntityIDsInJSONHelper(value, getMapped);
|
||||
}
|
||||
document = QJsonDocument(jsonObject);
|
||||
}
|
||||
return document.toJson();
|
||||
}
|
||||
|
||||
bool EntityTree::sendEntitiesOperation(const OctreeElementPointer& element, void* extraData) {
|
||||
SendEntitiesOperationArgs* args = static_cast<SendEntitiesOperationArgs*>(extraData);
|
||||
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
|
||||
|
@ -2819,6 +2860,61 @@ bool EntityTree::sendEntitiesOperation(const OctreeElementPointer& element, void
|
|||
QByteArray actionData = properties.getActionData();
|
||||
properties.setActionData(remapActionDataIDs(actionData, *args->map));
|
||||
|
||||
{
|
||||
QString materialURL = properties.getMaterialURL();
|
||||
QString uuidString = materialURL;
|
||||
QString materialName = "";
|
||||
|
||||
if (materialURL.contains("?")) {
|
||||
QStringList split = materialURL.split("?");
|
||||
uuidString = split[0];
|
||||
if (split.length() > 1) {
|
||||
materialName = split[1];
|
||||
}
|
||||
} else if (materialURL.contains("#")) {
|
||||
QStringList split = materialURL.split("#");
|
||||
uuidString = split[0];
|
||||
if (split.length() > 1) {
|
||||
materialName = split[1];
|
||||
}
|
||||
}
|
||||
|
||||
QUuid oldID = uuidString;
|
||||
if (!oldID.isNull()) {
|
||||
uuidString = getMapped(oldID).toString();
|
||||
}
|
||||
QUuid oldMaterialName = materialName;
|
||||
if (!oldMaterialName.isNull()) {
|
||||
materialName = getMapped(oldMaterialName).toString();
|
||||
}
|
||||
|
||||
if (!materialName.isEmpty()) {
|
||||
properties.setMaterialURL(uuidString + "?" + materialName);
|
||||
} else {
|
||||
properties.setMaterialURL(uuidString);
|
||||
}
|
||||
}
|
||||
|
||||
QString imageURL = properties.getImageURL();
|
||||
if (imageURL.startsWith("{")) {
|
||||
QUuid oldID = imageURL;
|
||||
if (!oldID.isNull()) {
|
||||
properties.setImageURL(getMapped(oldID).toString());
|
||||
}
|
||||
}
|
||||
|
||||
QString materialData = properties.getMaterialData();
|
||||
if (!materialData.isEmpty()) {
|
||||
materialData = replaceEntityIDsInJSON(materialData, getMapped);
|
||||
properties.setMaterialData(materialData);
|
||||
}
|
||||
|
||||
QString userData = properties.getUserData();
|
||||
if (!userData.isEmpty()) {
|
||||
userData = replaceEntityIDsInJSON(userData, getMapped);
|
||||
properties.setUserData(userData);
|
||||
}
|
||||
|
||||
// set creation time to "now" for imported entities
|
||||
properties.setCreated(usecTimestampNow());
|
||||
|
||||
|
|
|
@ -322,6 +322,16 @@ bool Texture::isDepthStencilRenderTarget() const {
|
|||
return (_texelFormat.getSemantic() == gpu::DEPTH) || (_texelFormat.getSemantic() == gpu::DEPTH_STENCIL);
|
||||
}
|
||||
|
||||
void Texture::setSize(int width, int height) {
|
||||
_width = width;
|
||||
_height = height;
|
||||
}
|
||||
|
||||
void Texture::setOriginalSize(int width, int height) {
|
||||
_originalWidth = width;
|
||||
_originalHeight = height;
|
||||
}
|
||||
|
||||
uint16 Texture::evalDimMaxNumMips(uint16 size) {
|
||||
double largerDim = size;
|
||||
double val = log(largerDim)/log(2.0);
|
||||
|
@ -887,16 +897,34 @@ void SphericalHarmonics::evalFromTexture(const Texture& texture, gpu::BackendTar
|
|||
|
||||
|
||||
// TextureSource
|
||||
void TextureSource::resetTexture(gpu::TexturePointer texture) {
|
||||
const gpu::TexturePointer TextureSource::getGPUTexture() const {
|
||||
if (_gpuTextureOperator && !_locked) {
|
||||
_locked = true;
|
||||
auto gpuTexture = _gpuTextureOperator();
|
||||
_locked = false;
|
||||
return gpuTexture;
|
||||
}
|
||||
return _gpuTexture;
|
||||
}
|
||||
|
||||
void TextureSource::resetTexture(const gpu::TexturePointer& texture) {
|
||||
_gpuTexture = texture;
|
||||
_gpuTextureOperator = nullptr;
|
||||
}
|
||||
|
||||
void TextureSource::resetTextureOperator(const std::function<gpu::TexturePointer()>& textureOperator) {
|
||||
_gpuTexture = nullptr;
|
||||
_gpuTextureOperator = textureOperator;
|
||||
}
|
||||
|
||||
bool TextureSource::isDefined() const {
|
||||
if (_gpuTexture) {
|
||||
return _gpuTexture->isDefined();
|
||||
} else {
|
||||
return false;
|
||||
if (_gpuTextureOperator && !_locked) {
|
||||
_locked = true;
|
||||
auto gpuTexture = _gpuTextureOperator();
|
||||
_locked = false;
|
||||
return gpuTexture && gpuTexture->isDefined();
|
||||
}
|
||||
return _gpuTexture && _gpuTexture->isDefined();
|
||||
}
|
||||
|
||||
bool Texture::setMinMip(uint16 newMinMip) {
|
||||
|
@ -930,6 +958,7 @@ void Texture::setExternalTexture(uint32 externalId, void* externalFence) {
|
|||
Lock lock(_externalMutex);
|
||||
assert(_externalRecycler);
|
||||
_externalUpdates.push_back({ externalId, externalFence });
|
||||
_defined = true;
|
||||
}
|
||||
|
||||
Texture::ExternalUpdates Texture::getUpdates() const {
|
||||
|
|
|
@ -417,11 +417,16 @@ public:
|
|||
|
||||
Element getTexelFormat() const { return _texelFormat; }
|
||||
|
||||
void setSize(int width, int height);
|
||||
Vec3u getDimensions() const { return Vec3u(_width, _height, _depth); }
|
||||
uint16 getWidth() const { return _width; }
|
||||
uint16 getHeight() const { return _height; }
|
||||
uint16 getDepth() const { return _depth; }
|
||||
|
||||
void setOriginalSize(int width, int height);
|
||||
int getOriginalWidth() const { return _originalWidth; }
|
||||
int getOriginalHeight() const { return _originalHeight; }
|
||||
|
||||
// The number of faces is mostly used for cube map, and maybe for stereo ? otherwise it's 1
|
||||
// For cube maps, this means the pixels of the different faces are supposed to be packed back to back in a mip
|
||||
// as if the height was NUM_FACES time bigger.
|
||||
|
@ -615,6 +620,8 @@ protected:
|
|||
uint16 _width { 1 };
|
||||
uint16 _height { 1 };
|
||||
uint16 _depth { 1 };
|
||||
int _originalWidth { 0 };
|
||||
int _originalHeight { 0 };
|
||||
|
||||
uint16 _numSamples { 1 };
|
||||
|
||||
|
@ -676,9 +683,10 @@ public:
|
|||
_element(element)
|
||||
{};
|
||||
|
||||
TextureView(const TexturePointer& texture, uint16 subresource) :
|
||||
TextureView(const TexturePointer& texture, uint16 subresource, std::function<gpu::TexturePointer()> textureOperator = nullptr) :
|
||||
_texture(texture),
|
||||
_subresource(subresource)
|
||||
_subresource(subresource),
|
||||
_textureOperator(textureOperator)
|
||||
{};
|
||||
|
||||
~TextureView() {}
|
||||
|
@ -689,6 +697,12 @@ public:
|
|||
bool operator !() const { return (!_texture); }
|
||||
|
||||
bool isValid() const { return bool(_texture); }
|
||||
|
||||
bool isReference() const { return (bool)_textureOperator; }
|
||||
std::function<gpu::TexturePointer()> getTextureOperator() const { return _textureOperator; }
|
||||
|
||||
private:
|
||||
std::function<gpu::TexturePointer()> _textureOperator { nullptr };
|
||||
};
|
||||
typedef std::vector<TextureView> TextureViews;
|
||||
|
||||
|
@ -700,16 +714,20 @@ public:
|
|||
|
||||
void setUrl(const QUrl& url) { _imageUrl = url; }
|
||||
const QUrl& getUrl() const { return _imageUrl; }
|
||||
const gpu::TexturePointer getGPUTexture() const { return _gpuTexture; }
|
||||
const gpu::TexturePointer getGPUTexture() const;
|
||||
void setType(int type) { _type = type; }
|
||||
int getType() const { return _type; }
|
||||
|
||||
void resetTexture(gpu::TexturePointer texture);
|
||||
void resetTexture(const gpu::TexturePointer& texture);
|
||||
void resetTextureOperator(const std::function<gpu::TexturePointer()>& textureOperator);
|
||||
|
||||
bool isDefined() const;
|
||||
std::function<gpu::TexturePointer()> getTextureOperator() const { return _gpuTextureOperator; }
|
||||
|
||||
protected:
|
||||
gpu::TexturePointer _gpuTexture;
|
||||
std::function<gpu::TexturePointer()> _gpuTextureOperator { nullptr };
|
||||
mutable bool _locked { false };
|
||||
QUrl _imageUrl;
|
||||
int _type { 0 };
|
||||
};
|
||||
|
|
|
@ -281,4 +281,33 @@ void MultiMaterial::calculateMaterialInfo() const {
|
|||
}
|
||||
_hasCalculatedTextureInfo = allTextures;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -341,57 +341,57 @@ public:
|
|||
virtual ~Material() = default;
|
||||
Material& operator= (const Material& material);
|
||||
|
||||
const MaterialKey& getKey() const { return _key; }
|
||||
virtual MaterialKey getKey() const { return _key; }
|
||||
|
||||
static const float DEFAULT_EMISSIVE;
|
||||
void setEmissive(const glm::vec3& emissive, bool isSRGB = true);
|
||||
glm::vec3 getEmissive(bool SRGB = true) const { return (SRGB ? ColorUtils::tosRGBVec3(_emissive) : _emissive); }
|
||||
virtual glm::vec3 getEmissive(bool SRGB = true) const { return (SRGB ? ColorUtils::tosRGBVec3(_emissive) : _emissive); }
|
||||
|
||||
static const float DEFAULT_OPACITY;
|
||||
void setOpacity(float opacity);
|
||||
float getOpacity() const { return _opacity; }
|
||||
virtual float getOpacity() const { return _opacity; }
|
||||
|
||||
static const MaterialKey::OpacityMapMode DEFAULT_OPACITY_MAP_MODE;
|
||||
void setOpacityMapMode(MaterialKey::OpacityMapMode opacityMapMode);
|
||||
MaterialKey::OpacityMapMode getOpacityMapMode() const;
|
||||
virtual MaterialKey::OpacityMapMode getOpacityMapMode() const;
|
||||
|
||||
static const float DEFAULT_OPACITY_CUTOFF;
|
||||
void setOpacityCutoff(float opacityCutoff);
|
||||
float getOpacityCutoff() const { return _opacityCutoff; }
|
||||
virtual float getOpacityCutoff() const { return _opacityCutoff; }
|
||||
|
||||
static const MaterialKey::CullFaceMode DEFAULT_CULL_FACE_MODE;
|
||||
void setCullFaceMode(MaterialKey::CullFaceMode cullFaceMode) { _cullFaceMode = cullFaceMode; }
|
||||
MaterialKey::CullFaceMode getCullFaceMode() const { return _cullFaceMode; }
|
||||
virtual MaterialKey::CullFaceMode getCullFaceMode() const { return _cullFaceMode; }
|
||||
|
||||
void setUnlit(bool value);
|
||||
bool isUnlit() const { return _key.isUnlit(); }
|
||||
virtual bool isUnlit() const { return _key.isUnlit(); }
|
||||
|
||||
static const float DEFAULT_ALBEDO;
|
||||
void setAlbedo(const glm::vec3& albedo, bool isSRGB = true);
|
||||
glm::vec3 getAlbedo(bool SRGB = true) const { return (SRGB ? ColorUtils::tosRGBVec3(_albedo) : _albedo); }
|
||||
virtual glm::vec3 getAlbedo(bool SRGB = true) const { return (SRGB ? ColorUtils::tosRGBVec3(_albedo) : _albedo); }
|
||||
|
||||
static const float DEFAULT_METALLIC;
|
||||
void setMetallic(float metallic);
|
||||
float getMetallic() const { return _metallic; }
|
||||
virtual float getMetallic() const { return _metallic; }
|
||||
|
||||
static const float DEFAULT_ROUGHNESS;
|
||||
void setRoughness(float roughness);
|
||||
float getRoughness() const { return _roughness; }
|
||||
virtual float getRoughness() const { return _roughness; }
|
||||
|
||||
static const float DEFAULT_SCATTERING;
|
||||
void setScattering(float scattering);
|
||||
float getScattering() const { return _scattering; }
|
||||
virtual float getScattering() const { return _scattering; }
|
||||
|
||||
// The texture map to channel association
|
||||
static const int NUM_TEXCOORD_TRANSFORMS { 2 };
|
||||
void setTextureMap(MapChannel channel, const TextureMapPointer& textureMap);
|
||||
const TextureMaps& getTextureMaps() const { return _textureMaps; } // FIXME - not thread safe...
|
||||
virtual TextureMaps getTextureMaps() const { return _textureMaps; } // FIXME - not thread safe...
|
||||
const TextureMapPointer getTextureMap(MapChannel channel) const;
|
||||
|
||||
// Albedo maps cannot have opacity detected until they are loaded
|
||||
// This method allows const changing of the key/schemaBuffer without touching the map
|
||||
// return true if the opacity changed, flase otherwise
|
||||
bool resetOpacityMap() const;
|
||||
virtual bool resetOpacityMap() const;
|
||||
|
||||
// conversion from legacy material properties to PBR equivalent
|
||||
static float shininessToRoughness(float shininess) { return 1.0f - shininess / 100.0f; }
|
||||
|
@ -404,12 +404,12 @@ public:
|
|||
const std::string& getModel() const { return _model; }
|
||||
void setModel(const std::string& model) { _model = model; }
|
||||
|
||||
glm::mat4 getTexCoordTransform(uint i) const { return _texcoordTransforms[i]; }
|
||||
virtual glm::mat4 getTexCoordTransform(uint i) const { return _texcoordTransforms[i]; }
|
||||
void setTexCoordTransform(uint i, const glm::mat4& mat4) { _texcoordTransforms[i] = mat4; }
|
||||
glm::vec2 getLightmapParams() const { return _lightmapParams; }
|
||||
glm::vec2 getMaterialParams() const { return _materialParams; }
|
||||
virtual glm::vec2 getLightmapParams() const { return _lightmapParams; }
|
||||
virtual glm::vec2 getMaterialParams() const { return _materialParams; }
|
||||
|
||||
bool getDefaultFallthrough() const { return _defaultFallthrough; }
|
||||
virtual bool getDefaultFallthrough() const { return _defaultFallthrough; }
|
||||
void setDefaultFallthrough(bool defaultFallthrough) { _defaultFallthrough = defaultFallthrough; }
|
||||
|
||||
enum ExtraFlagBit {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -547,12 +549,16 @@ public:
|
|||
void setTexturesLoading(bool value) { _texturesLoading = value; }
|
||||
void setInitialized() { _initialized = true; }
|
||||
|
||||
bool shouldUpdate() const { return !_initialized || _needsUpdate || _texturesLoading; }
|
||||
bool shouldUpdate() const { return !_initialized || _needsUpdate || _texturesLoading || anyReferenceMaterialsOrTexturesChanged(); }
|
||||
|
||||
int getTextureCount() const { calculateMaterialInfo(); return _textureCount; }
|
||||
size_t getTextureSize() const { calculateMaterialInfo(); return _textureSize; }
|
||||
bool hasTextureInfo() const { return _hasCalculatedTextureInfo; }
|
||||
|
||||
void resetReferenceTexturesAndMaterials();
|
||||
void addReferenceTexture(const std::function<gpu::TexturePointer()>& textureOperator);
|
||||
void addReferenceMaterial(const std::function<graphics::MaterialPointer()>& materialOperator);
|
||||
|
||||
private:
|
||||
gpu::BufferView _schemaBuffer;
|
||||
graphics::MaterialKey::CullFaceMode _cullFaceMode { graphics::Material::DEFAULT_CULL_FACE_MODE };
|
||||
|
@ -565,6 +571,11 @@ private:
|
|||
mutable int _textureCount { 0 };
|
||||
mutable bool _hasCalculatedTextureInfo { false };
|
||||
void calculateMaterialInfo() const;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -18,16 +18,12 @@ void TextureMap::setTextureSource(TextureSourcePointer& textureSource) {
|
|||
}
|
||||
|
||||
bool TextureMap::isDefined() const {
|
||||
if (_textureSource) {
|
||||
return _textureSource->isDefined();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return _textureSource && _textureSource->isDefined();
|
||||
}
|
||||
|
||||
gpu::TextureView TextureMap::getTextureView() const {
|
||||
if (_textureSource) {
|
||||
return gpu::TextureView(_textureSource->getGPUTexture(), 0);
|
||||
return gpu::TextureView(_textureSource->getGPUTexture(), 0, _textureSource->getTextureOperator());
|
||||
} else {
|
||||
return gpu::TextureView();
|
||||
}
|
||||
|
|
|
@ -98,6 +98,8 @@ static const QUrl HMD_PREVIEW_FRAME_URL("resource://hmdPreviewFrame");
|
|||
static const float SKYBOX_LOAD_PRIORITY { 10.0f }; // Make sure skybox loads first
|
||||
static const float HIGH_MIPS_LOAD_PRIORITY { 9.0f }; // Make sure high mips loads after skybox but before models
|
||||
|
||||
std::function<gpu::TexturePointer(const QUuid&)> Texture::_unboundTextureForUUIDOperator { nullptr };
|
||||
|
||||
TextureCache::TextureCache() {
|
||||
_ktxCache->initialize();
|
||||
#if defined(DISABLE_KTX_CACHE)
|
||||
|
@ -252,6 +254,10 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUs
|
|||
if (url.scheme() == RESOURCE_SCHEME) {
|
||||
return getResourceTexture(url);
|
||||
}
|
||||
QString decodedURL = QUrl::fromPercentEncoding(url.toEncoded());
|
||||
if (decodedURL.startsWith("{")) {
|
||||
return getTextureByUUID(decodedURL);
|
||||
}
|
||||
auto modifiedUrl = url;
|
||||
if (type == image::TextureUsage::SKY_TEXTURE) {
|
||||
QUrlQuery query { url.query() };
|
||||
|
@ -385,8 +391,6 @@ NetworkTexture::NetworkTexture(const NetworkTexture& other) :
|
|||
_type(other._type),
|
||||
_sourceChannel(other._sourceChannel),
|
||||
_currentlyLoadingResourceType(other._currentlyLoadingResourceType),
|
||||
_originalWidth(other._originalWidth),
|
||||
_originalHeight(other._originalHeight),
|
||||
_width(other._width),
|
||||
_height(other._height),
|
||||
_maxNumPixels(other._maxNumPixels),
|
||||
|
@ -462,13 +466,12 @@ void NetworkTexture::setExtra(void* extra) {
|
|||
|
||||
void NetworkTexture::setImage(gpu::TexturePointer texture, int originalWidth,
|
||||
int originalHeight) {
|
||||
_originalWidth = originalWidth;
|
||||
_originalHeight = originalHeight;
|
||||
|
||||
// Passing ownership
|
||||
_textureSource->resetTexture(texture);
|
||||
|
||||
if (texture) {
|
||||
texture->setOriginalSize(originalWidth, originalHeight);
|
||||
_width = texture->getWidth();
|
||||
_height = texture->getHeight();
|
||||
setSize(texture->getStoredSize());
|
||||
|
@ -481,6 +484,12 @@ void NetworkTexture::setImage(gpu::TexturePointer texture, int originalWidth,
|
|||
emit networkTextureCreated(qWeakPointerCast<NetworkTexture, Resource> (_self));
|
||||
}
|
||||
|
||||
void NetworkTexture::setImageOperator(std::function<gpu::TexturePointer()> textureOperator) {
|
||||
_textureSource->resetTextureOperator(textureOperator);
|
||||
finishedLoading((bool)textureOperator);
|
||||
emit networkTextureCreated(qWeakPointerCast<NetworkTexture, Resource> (_self));
|
||||
}
|
||||
|
||||
gpu::TexturePointer NetworkTexture::getFallbackTexture() const {
|
||||
return getFallbackTextureForType(_type);
|
||||
}
|
||||
|
@ -1312,7 +1321,6 @@ void ImageReader::read() {
|
|||
}
|
||||
|
||||
NetworkTexturePointer TextureCache::getResourceTexture(const QUrl& resourceTextureUrl) {
|
||||
gpu::TexturePointer texture;
|
||||
if (resourceTextureUrl == SPECTATOR_CAMERA_FRAME_URL) {
|
||||
if (!_spectatorCameraNetworkTexture) {
|
||||
_spectatorCameraNetworkTexture.reset(new NetworkTexture(resourceTextureUrl, true));
|
||||
|
@ -1329,6 +1337,7 @@ NetworkTexturePointer TextureCache::getResourceTexture(const QUrl& resourceTextu
|
|||
_hmdPreviewNetworkTexture.reset(new NetworkTexture(resourceTextureUrl, true));
|
||||
}
|
||||
if (_hmdPreviewFramebuffer) {
|
||||
gpu::TexturePointer texture;
|
||||
texture = _hmdPreviewFramebuffer->getRenderBuffer(0);
|
||||
if (texture) {
|
||||
texture->setSource(HMD_PREVIEW_FRAME_URL.toString().toStdString());
|
||||
|
@ -1375,3 +1384,27 @@ void TextureCache::updateSpectatorCameraNetworkTexture() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
NetworkTexturePointer TextureCache::getTextureByUUID(const QString& uuid) {
|
||||
QUuid quuid = QUuid(uuid);
|
||||
if (!quuid.isNull()) {
|
||||
// We mark this as a resource texture because it's just a reference to another texture. The source
|
||||
// texture will be marked properly
|
||||
NetworkTexturePointer toReturn = NetworkTexturePointer(new NetworkTexture(uuid, true));
|
||||
toReturn->setImageOperator(Texture::getTextureForUUIDOperator(uuid));
|
||||
return toReturn;
|
||||
}
|
||||
return NetworkTexturePointer();
|
||||
}
|
||||
|
||||
std::function<gpu::TexturePointer()> Texture::getTextureForUUIDOperator(const QUuid& uuid) {
|
||||
if (_unboundTextureForUUIDOperator) {
|
||||
return std::bind(_unboundTextureForUUIDOperator, uuid);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void Texture::setUnboundTextureForUUIDOperator(std::function<gpu::TexturePointer(const QUuid&)> textureForUUIDOperator) {
|
||||
_unboundTextureForUUIDOperator = textureForUUIDOperator;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,12 @@ class Texture {
|
|||
public:
|
||||
gpu::TexturePointer getGPUTexture() const { return _textureSource->getGPUTexture(); }
|
||||
gpu::TextureSourcePointer _textureSource;
|
||||
|
||||
static std::function<gpu::TexturePointer()> getTextureForUUIDOperator(const QUuid& uuid);
|
||||
static void setUnboundTextureForUUIDOperator(std::function<gpu::TexturePointer(const QUuid&)> textureForUUIDOperator);
|
||||
|
||||
private:
|
||||
static std::function<gpu::TexturePointer(const QUuid&)> _unboundTextureForUUIDOperator;
|
||||
};
|
||||
|
||||
/// A texture loaded from the network.
|
||||
|
@ -52,10 +58,10 @@ public:
|
|||
|
||||
QString getType() const override { return "NetworkTexture"; }
|
||||
|
||||
int getOriginalWidth() const { return _originalWidth; }
|
||||
int getOriginalHeight() const { return _originalHeight; }
|
||||
int getWidth() const { return _width; }
|
||||
int getHeight() const { return _height; }
|
||||
int getOriginalWidth() const { return _textureSource->getGPUTexture() ? _textureSource->getGPUTexture()->getOriginalWidth() : 0; }
|
||||
int getOriginalHeight() const { return _textureSource->getGPUTexture() ? _textureSource->getGPUTexture()->getOriginalHeight() : 0; }
|
||||
int getWidth() const { return _textureSource->getGPUTexture() ? _textureSource->getGPUTexture()->getWidth() : 0; }
|
||||
int getHeight() const { return _textureSource->getGPUTexture() ? _textureSource->getGPUTexture()->getHeight() : 0; }
|
||||
image::TextureUsage::Type getTextureType() const { return _type; }
|
||||
|
||||
gpu::TexturePointer getFallbackTexture() const;
|
||||
|
@ -86,6 +92,7 @@ protected:
|
|||
Q_INVOKABLE void loadTextureContent(const QByteArray& content);
|
||||
|
||||
Q_INVOKABLE void setImage(gpu::TexturePointer texture, int originalWidth, int originalHeight);
|
||||
void setImageOperator(std::function<gpu::TexturePointer()> textureOperator);
|
||||
|
||||
Q_INVOKABLE void startRequestForNextMipLevel();
|
||||
|
||||
|
@ -136,8 +143,6 @@ private:
|
|||
// mip offsets to change.
|
||||
ktx::KTXDescriptorPointer _originalKtxDescriptor;
|
||||
|
||||
int _originalWidth { 0 };
|
||||
int _originalHeight { 0 };
|
||||
int _width { 0 };
|
||||
int _height { 0 };
|
||||
int _maxNumPixels { ABSOLUTE_MAX_TEXTURE_NUM_PIXELS };
|
||||
|
@ -192,6 +197,8 @@ public:
|
|||
const gpu::FramebufferPointer& getSpectatorCameraFramebuffer(int width, int height);
|
||||
void updateSpectatorCameraNetworkTexture();
|
||||
|
||||
NetworkTexturePointer getTextureByUUID(const QString& uuid);
|
||||
|
||||
static const int DEFAULT_SPECTATOR_CAM_WIDTH { 2048 };
|
||||
static const int DEFAULT_SPECTATOR_CAM_HEIGHT { 1024 };
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ const size_t MAX_PROCEDURAL_TEXTURE_CHANNELS{ 4 };
|
|||
* If a procedural material contains a vertex shader, the bounding box of the material entity is used to cull the object to which the material is applied.
|
||||
* @property {string} fragmentShaderURL - A link to a fragment shader. Currently, only GLSL shaders are supported. The shader must implement a different method depending on the version.
|
||||
* <code>shaderUrl</code> is an alias.
|
||||
* @property {string[]} channels=[] - An array of input texture URLs. Currently, up to 4 are supported.
|
||||
* @property {string[]} channels=[] - An array of input texture URLs or entity IDs. Currently, up to 4 are supported. An entity ID may be that of an Image or Web entity.
|
||||
* @property {ProceduralUniforms} uniforms={} - A {@link ProceduralUniforms} object containing all the custom uniforms to be passed to the shader.
|
||||
*/
|
||||
|
||||
|
@ -212,26 +212,26 @@ public:
|
|||
ProceduralMaterial() : NetworkMaterial() { initializeProcedural(); }
|
||||
ProceduralMaterial(const NetworkMaterial& material) : NetworkMaterial(material) { initializeProcedural(); }
|
||||
|
||||
bool isProcedural() const override { return true; }
|
||||
bool isEnabled() const override { return _procedural.isEnabled(); }
|
||||
bool isReady() const override { return _procedural.isReady(); }
|
||||
QString getProceduralString() const override { return _proceduralString; }
|
||||
virtual bool isProcedural() const override { return true; }
|
||||
virtual bool isEnabled() const override { return _procedural.isEnabled(); }
|
||||
virtual bool isReady() const override { return _procedural.isReady(); }
|
||||
virtual QString getProceduralString() const override { return _proceduralString; }
|
||||
|
||||
void setProceduralData(const QString& data) {
|
||||
_proceduralString = data;
|
||||
_procedural.setProceduralData(ProceduralData::parse(data));
|
||||
}
|
||||
glm::vec4 getColor(const glm::vec4& color) const { return _procedural.getColor(color); }
|
||||
bool isFading() const { return _procedural.isFading(); }
|
||||
virtual glm::vec4 getColor(const glm::vec4& color) const { return _procedural.getColor(color); }
|
||||
virtual bool isFading() const { return _procedural.isFading(); }
|
||||
void setIsFading(bool isFading) { _procedural.setIsFading(isFading); }
|
||||
uint64_t getFadeStartTime() const { return _procedural.getFadeStartTime(); }
|
||||
bool hasVertexShader() const { return _procedural.hasVertexShader(); }
|
||||
void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation,
|
||||
virtual uint64_t getFadeStartTime() const { return _procedural.getFadeStartTime(); }
|
||||
virtual bool hasVertexShader() const { return _procedural.hasVertexShader(); }
|
||||
virtual void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation,
|
||||
const uint64_t& created, const ProceduralProgramKey key = ProceduralProgramKey()) {
|
||||
_procedural.prepare(batch, position, size, orientation, created, key);
|
||||
}
|
||||
|
||||
void initializeProcedural();
|
||||
virtual void initializeProcedural();
|
||||
|
||||
void setBoundOperator(const std::function<AABox(RenderArgs*)>& boundOperator) { _procedural.setBoundOperator(boundOperator); }
|
||||
bool hasBoundOperator() const { return _procedural.hasBoundOperator(); }
|
||||
|
@ -243,4 +243,4 @@ private:
|
|||
};
|
||||
typedef std::shared_ptr<ProceduralMaterial> ProceduralMaterialPointer;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "RegisteredMetaTypes.h"
|
||||
|
||||
#include "Procedural.h"
|
||||
#include "ReferenceMaterial.h"
|
||||
|
||||
NetworkMaterialResource::NetworkMaterialResource(const QUrl& url) :
|
||||
Resource(url) {}
|
||||
|
@ -75,7 +76,8 @@ bool NetworkMaterialResource::parseJSONColor(const QJsonValue& array, glm::vec3&
|
|||
* A material or set of materials used by a {@link Entities.EntityType|Material entity}.
|
||||
* @typedef {object} Entities.MaterialResource
|
||||
* @property {number} materialVersion=1 - The version of the material. <em>Currently not used.</em>
|
||||
* @property {Entities.Material|Entities.Material[]} materials - The details of the material or materials.
|
||||
* @property {Entities.Material|Entities.Material[]|string} materials - The details of the material or materials, or the ID of another
|
||||
* Material entity.
|
||||
*/
|
||||
NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMaterials(const QJsonDocument& materialJSON, const QUrl& baseUrl) {
|
||||
ParsedMaterials toReturn;
|
||||
|
@ -92,14 +94,14 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater
|
|||
if (materialsValue.isArray()) {
|
||||
QJsonArray materials = materialsValue.toArray();
|
||||
for (auto material : materials) {
|
||||
if (!material.isNull() && material.isObject()) {
|
||||
auto parsedMaterial = parseJSONMaterial(material.toObject(), baseUrl);
|
||||
if (!material.isNull() && (material.isObject() || material.isString())) {
|
||||
auto parsedMaterial = parseJSONMaterial(material, baseUrl);
|
||||
toReturn.networkMaterials[parsedMaterial.first] = parsedMaterial.second;
|
||||
toReturn.names.push_back(parsedMaterial.first);
|
||||
}
|
||||
}
|
||||
} else if (materialsValue.isObject()) {
|
||||
auto parsedMaterial = parseJSONMaterial(materialsValue.toObject(), baseUrl);
|
||||
} else if (materialsValue.isObject() || materialsValue.isString()) {
|
||||
auto parsedMaterial = parseJSONMaterial(materialsValue, baseUrl);
|
||||
toReturn.networkMaterials[parsedMaterial.first] = parsedMaterial.second;
|
||||
toReturn.names.push_back(parsedMaterial.first);
|
||||
}
|
||||
|
@ -110,6 +112,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
|
||||
|
@ -136,12 +149,14 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater
|
|||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {number|string} scattering - The scattering, range <code>0.0</code> – <code>1.0</code>.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} emissiveMap - The URL of the emissive texture image.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} albedoMap - The URL of the albedo texture image.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} opacityMap - The URL of the opacity texture image. Set the value the same as the <code>albedoMap</code>
|
||||
* value for transparency.
|
||||
* @property {string} emissiveMap - The URL of the emissive texture image, or an entity ID. An entity ID may be that of an
|
||||
* Image or Web entity. Set to <code>"fallthrough"</code> to fall through to the material below.
|
||||
* <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} albedoMap - The URL of the albedo texture image, or an entity ID. An entity ID may be that of an Image
|
||||
* or Web entity. Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code>
|
||||
* model only.
|
||||
* @property {string} opacityMap - The URL of the opacity texture image, or an entity ID. An entity ID may be that of an Image
|
||||
* or Web entity. Set the value the same as the <code>albedoMap</code> value for transparency.
|
||||
* <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} opacityMapMode - The mode defining the interpretation of the opacity map. Values can be:
|
||||
* <ul>
|
||||
|
@ -176,23 +191,27 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater
|
|||
* @property {string} glossMap - The URL of the gloss texture image. You can use this or <code>roughnessMap</code>, but not
|
||||
* both.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} metallicMap - The URL of the metallic texture image. You can use this or <code>specularMap</code>, but
|
||||
* not both.
|
||||
* @property {string} metallicMap - The URL of the metallic texture image, or an entity ID. An entity ID may be that of an
|
||||
* Image or Web entity. You can use this or <code>specularMap</code>, but not both.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} specularMap - The URL of the specular texture image. You can use this or <code>metallicMap</code>, but
|
||||
* not both.
|
||||
* @property {string} specularMap - The URL of the specular texture image, or an entity ID. An entity ID may be that of an
|
||||
* Image or Web entity. You can use this or <code>metallicMap</code>, but not both.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} normalMap - The URL of the normal texture image. You can use this or <code>bumpMap</code>, but not both.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} bumpMap - The URL of the bump texture image. You can use this or <code>normalMap</code>, but not both.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} occlusionMap - The URL of the occlusion texture image.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} scatteringMap - The URL of the scattering texture image. Only used if <code>normalMap</code> or
|
||||
* <code>bumpMap</code> is specified.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} lightMap - The URL of the light map texture image.
|
||||
* @property {string} normalMap - The URL of the normal texture image, or an entity ID. An entity ID may be that of an Image
|
||||
* or Web entity. You can use this or <code>bumpMap</code>, but not both. Set to <code>"fallthrough"</code> to fall
|
||||
* through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} bumpMap - The URL of the bump texture image, or an entity ID. An entity ID may be that of an Image
|
||||
* or Web entity. You can use this or <code>normalMap</code>, but not both. Set to <code>"fallthrough"</code> to
|
||||
* fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} occlusionMap - The URL of the occlusion texture image, or an entity ID. An entity ID may be that of
|
||||
* an Image or Web entity. Set to <code>"fallthrough"</code> to fall through to the material below.
|
||||
* <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} scatteringMap - The URL of the scattering texture image, or an entity ID. An entity ID may be that of an
|
||||
* Image or Web entity. Only used if <code>normalMap</code> or <code>bumpMap</code> is specified.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
* @property {string} lightMap - The URL of the light map texture image, or an entity ID. An entity ID may be that of an Image
|
||||
* or Web entity. Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code>
|
||||
* model only.
|
||||
* @property {Mat4|string} texCoordTransform0 - The transform to use for all of the maps apart from <code>occlusionMap</code>
|
||||
* and <code>lightMap</code>.
|
||||
* Set to <code>"fallthrough"</code> to fall through to the material below. <code>"hifi_pbr"</code> model only.
|
||||
|
@ -210,10 +229,22 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater
|
|||
* @property {ProceduralData} procedural - The definition of a procedural shader material. <code>"hifi_shader_simple"</code> model only.
|
||||
*/
|
||||
// Note: See MaterialEntityItem.h for default values used in practice.
|
||||
std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource::parseJSONMaterial(const QJsonObject& materialJSON, const QUrl& baseUrl) {
|
||||
std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource::parseJSONMaterial(const QJsonValue& materialJSONValue, const QUrl& baseUrl) {
|
||||
std::string name = "";
|
||||
std::shared_ptr<NetworkMaterial> networkMaterial;
|
||||
|
||||
if (materialJSONValue.isString()) {
|
||||
QString uuidString = materialJSONValue.toString();
|
||||
name = uuidString.toStdString();
|
||||
QUuid uuid = QUuid(uuidString);
|
||||
if (!uuid.isNull()) {
|
||||
networkMaterial = std::make_shared<ReferenceMaterial>(uuid);
|
||||
}
|
||||
return std::pair<std::string, std::shared_ptr<NetworkMaterial>>(name, networkMaterial);
|
||||
}
|
||||
|
||||
QJsonObject materialJSON = materialJSONValue.toObject();
|
||||
|
||||
std::string modelString = graphics::Material::HIFI_PBR;
|
||||
auto modelJSONIter = materialJSON.find("model");
|
||||
if (modelJSONIter != materialJSON.end() && modelJSONIter.value().isString()) {
|
||||
|
|
|
@ -33,8 +33,8 @@ public:
|
|||
void setScatteringMap(const QUrl& url);
|
||||
void setLightMap(const QUrl& url);
|
||||
|
||||
bool isMissingTexture();
|
||||
bool checkResetOpacityMap();
|
||||
virtual bool isMissingTexture();
|
||||
virtual bool checkResetOpacityMap();
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
|
@ -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 QJsonObject& materialJSON, 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);
|
||||
|
|
266
libraries/procedural/src/procedural/ReferenceMaterial.cpp
Normal file
266
libraries/procedural/src/procedural/ReferenceMaterial.cpp
Normal file
|
@ -0,0 +1,266 @@
|
|||
//
|
||||
// Created by HifiExperiments on 3/14/2021
|
||||
// Copyright 2021 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ReferenceMaterial.h"
|
||||
|
||||
std::function<graphics::MaterialPointer(QUuid)> ReferenceMaterial::_unboundMaterialForUUIDOperator = nullptr;
|
||||
|
||||
ReferenceMaterial::ReferenceMaterial(QUuid uuid) :
|
||||
graphics::ProceduralMaterial() {
|
||||
if (_unboundMaterialForUUIDOperator) {
|
||||
_materialForUUIDOperator = std::bind(_unboundMaterialForUUIDOperator, uuid);
|
||||
}
|
||||
}
|
||||
|
||||
// Material
|
||||
graphics::MaterialKey ReferenceMaterial::getKey() const {
|
||||
return resultWithLock<graphics::MaterialKey>([&] {
|
||||
auto material = getMaterial();
|
||||
return material ? material->getKey() : Parent::getKey();
|
||||
});
|
||||
}
|
||||
|
||||
glm::vec3 ReferenceMaterial::getEmissive(bool SRGB) const {
|
||||
return resultWithLock<glm::vec3>([&] {
|
||||
auto material = getMaterial();
|
||||
return material ? material->getEmissive(SRGB) : glm::vec3(DEFAULT_EMISSIVE);
|
||||
});
|
||||
}
|
||||
|
||||
float ReferenceMaterial::getOpacity() const {
|
||||
return resultWithLock<float>([&] {
|
||||
auto material = getMaterial();
|
||||
return material ? material->getOpacity() : DEFAULT_OPACITY;
|
||||
});
|
||||
}
|
||||
|
||||
graphics::MaterialKey::OpacityMapMode ReferenceMaterial::getOpacityMapMode() const {
|
||||
return resultWithLock<graphics::MaterialKey::OpacityMapMode>([&] {
|
||||
auto material = getMaterial();
|
||||
return material ? material->getOpacityMapMode() : DEFAULT_OPACITY_MAP_MODE;
|
||||
});
|
||||
}
|
||||
|
||||
float ReferenceMaterial::getOpacityCutoff() const {
|
||||
return resultWithLock<float>([&] {
|
||||
auto material = getMaterial();
|
||||
return material ? material->getOpacityCutoff() : DEFAULT_OPACITY_CUTOFF;
|
||||
});
|
||||
}
|
||||
|
||||
graphics::MaterialKey::CullFaceMode ReferenceMaterial::getCullFaceMode() const {
|
||||
return resultWithLock<graphics::MaterialKey::CullFaceMode>([&] {
|
||||
auto material = getMaterial();
|
||||
return material ? material->getCullFaceMode() : DEFAULT_CULL_FACE_MODE;
|
||||
});
|
||||
}
|
||||
|
||||
bool ReferenceMaterial::isUnlit() const {
|
||||
return resultWithLock<bool>([&] {
|
||||
auto material = getMaterial();
|
||||
return material ? material->isUnlit() : false;
|
||||
});
|
||||
}
|
||||
|
||||
glm::vec3 ReferenceMaterial::getAlbedo(bool SRGB) const {
|
||||
return resultWithLock<glm::vec3>([&] {
|
||||
auto material = getMaterial();
|
||||
return material ? material->getAlbedo(SRGB) : glm::vec3(DEFAULT_ALBEDO);
|
||||
});
|
||||
}
|
||||
|
||||
float ReferenceMaterial::getMetallic() const {
|
||||
return resultWithLock<float>([&] {
|
||||
auto material = getMaterial();
|
||||
return material ? material->getMetallic() : DEFAULT_METALLIC;
|
||||
});
|
||||
}
|
||||
|
||||
float ReferenceMaterial::getRoughness() const {
|
||||
return resultWithLock<float>([&] {
|
||||
auto material = getMaterial();
|
||||
return material ? material->getRoughness() : DEFAULT_ROUGHNESS;
|
||||
});
|
||||
}
|
||||
|
||||
float ReferenceMaterial::getScattering() const {
|
||||
return resultWithLock<float>([&] {
|
||||
auto material = getMaterial();
|
||||
return material ? material->getScattering() : DEFAULT_SCATTERING;
|
||||
});
|
||||
}
|
||||
|
||||
bool ReferenceMaterial::resetOpacityMap() const {
|
||||
return resultWithLock<bool>([&] {
|
||||
auto material = getMaterial();
|
||||
return material ? material->resetOpacityMap() : false;
|
||||
});
|
||||
}
|
||||
|
||||
graphics::Material::TextureMaps ReferenceMaterial::getTextureMaps() const {
|
||||
return resultWithLock<graphics::Material::TextureMaps>([&] {
|
||||
auto material = getMaterial();
|
||||
return material ? material->getTextureMaps() : Parent::getTextureMaps();
|
||||
});
|
||||
}
|
||||
|
||||
glm::vec2 ReferenceMaterial::getLightmapParams() const {
|
||||
return resultWithLock<glm::vec2>([&] {
|
||||
auto material = getMaterial();
|
||||
return material ? material->getLightmapParams() : glm::vec2(0.0f, 1.0f);
|
||||
});
|
||||
}
|
||||
|
||||
bool ReferenceMaterial::getDefaultFallthrough() const {
|
||||
return resultWithLock<bool>([&] {
|
||||
auto material = getMaterial();
|
||||
return material ? material->getDefaultFallthrough() : false;
|
||||
});
|
||||
}
|
||||
|
||||
// NetworkMaterial
|
||||
bool ReferenceMaterial::isMissingTexture() {
|
||||
return resultWithLock<bool>([&] {
|
||||
auto material = getNetworkMaterial();
|
||||
return material ? material->isMissingTexture() : false;
|
||||
});
|
||||
}
|
||||
|
||||
bool ReferenceMaterial::checkResetOpacityMap() {
|
||||
return resultWithLock<bool>([&] {
|
||||
auto material = getNetworkMaterial();
|
||||
return material ? material->checkResetOpacityMap() : false;
|
||||
});
|
||||
}
|
||||
|
||||
// ProceduralMaterial
|
||||
bool ReferenceMaterial::isProcedural() const {
|
||||
return resultWithLock<bool>([&] {
|
||||
auto material = getMaterial();
|
||||
return material ? material->isProcedural() : false;
|
||||
});
|
||||
}
|
||||
|
||||
bool ReferenceMaterial::isEnabled() const {
|
||||
return resultWithLock<bool>([&] {
|
||||
auto material = getMaterial();
|
||||
return material ? material->isEnabled() : false;
|
||||
});
|
||||
}
|
||||
|
||||
bool ReferenceMaterial::isReady() const {
|
||||
return resultWithLock<bool>([&] {
|
||||
auto material = getMaterial();
|
||||
return material ? material->isReady() : false;
|
||||
});
|
||||
}
|
||||
|
||||
QString ReferenceMaterial::getProceduralString() const {
|
||||
return resultWithLock<QString>([&] {
|
||||
auto material = getMaterial();
|
||||
return material ? material->getProceduralString() : QString();
|
||||
});
|
||||
}
|
||||
|
||||
glm::vec4 ReferenceMaterial::getColor(const glm::vec4& color) const {
|
||||
return resultWithLock<glm::vec4>([&] {
|
||||
auto material = getProceduralMaterial();
|
||||
return material ? material->getColor(color) : glm::vec4();
|
||||
});
|
||||
}
|
||||
|
||||
bool ReferenceMaterial::isFading() const {
|
||||
return resultWithLock<bool>([&] {
|
||||
auto material = getProceduralMaterial();
|
||||
return material ? material->isFading() : false;
|
||||
});
|
||||
}
|
||||
|
||||
uint64_t ReferenceMaterial::getFadeStartTime() const {
|
||||
return resultWithLock<uint64_t>([&] {
|
||||
auto material = getProceduralMaterial();
|
||||
return material ? material->getFadeStartTime() : 0;
|
||||
});
|
||||
}
|
||||
|
||||
bool ReferenceMaterial::hasVertexShader() const {
|
||||
return resultWithLock<bool>([&] {
|
||||
auto material = getProceduralMaterial();
|
||||
return material ? material->hasVertexShader() : false;
|
||||
});
|
||||
}
|
||||
|
||||
void ReferenceMaterial::prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation,
|
||||
const uint64_t& created, const ProceduralProgramKey key) {
|
||||
withLock([&] {
|
||||
if (auto material = getProceduralMaterial()) {
|
||||
material->prepare(batch, position, size, orientation, created, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ReferenceMaterial::initializeProcedural() {
|
||||
withLock([&] {
|
||||
if (auto material = getProceduralMaterial()) {
|
||||
material->initializeProcedural();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ReferenceMaterial::setMaterialForUUIDOperator(std::function<graphics::MaterialPointer(QUuid)> materialForUUIDOperator) {
|
||||
_unboundMaterialForUUIDOperator = materialForUUIDOperator;
|
||||
}
|
||||
|
||||
graphics::MaterialPointer ReferenceMaterial::getMaterial() const {
|
||||
if (_materialForUUIDOperator) {
|
||||
auto material = _materialForUUIDOperator();
|
||||
return material;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<NetworkMaterial> ReferenceMaterial::getNetworkMaterial() const {
|
||||
if (_materialForUUIDOperator) {
|
||||
std::shared_ptr<NetworkMaterial> result = nullptr;
|
||||
if (auto material = _materialForUUIDOperator()) {
|
||||
return std::static_pointer_cast<NetworkMaterial>(material);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
graphics::ProceduralMaterialPointer ReferenceMaterial::getProceduralMaterial() const {
|
||||
if (_materialForUUIDOperator) {
|
||||
auto material = _materialForUUIDOperator();
|
||||
if (material && material->isProcedural()) {
|
||||
return std::static_pointer_cast<graphics::ProceduralMaterial>(material);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename T, typename F>
|
||||
inline T ReferenceMaterial::resultWithLock(F&& f) const {
|
||||
if (_locked) {
|
||||
return T();
|
||||
} else {
|
||||
_locked = true;
|
||||
T result = f();
|
||||
_locked = false;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
inline void ReferenceMaterial::withLock(F&& f) const {
|
||||
if (!_locked) {
|
||||
_locked = true;
|
||||
f();
|
||||
_locked = false;
|
||||
}
|
||||
}
|
74
libraries/procedural/src/procedural/ReferenceMaterial.h
Normal file
74
libraries/procedural/src/procedural/ReferenceMaterial.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
//
|
||||
// Created by HifiExperiments on 3/14/2021
|
||||
// Copyright 2021 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Procedural.h"
|
||||
|
||||
class ReferenceMaterial : public graphics::ProceduralMaterial {
|
||||
public:
|
||||
using Parent = graphics::ProceduralMaterial;
|
||||
|
||||
ReferenceMaterial() {}
|
||||
ReferenceMaterial(QUuid uuid);
|
||||
|
||||
// Material
|
||||
graphics::MaterialKey getKey() const override;
|
||||
glm::vec3 getEmissive(bool SRGB = true) const override;
|
||||
float getOpacity() const override;
|
||||
graphics::MaterialKey::OpacityMapMode getOpacityMapMode() const override;
|
||||
float getOpacityCutoff() const override;
|
||||
graphics::MaterialKey::CullFaceMode getCullFaceMode() const override;
|
||||
bool isUnlit() const override;
|
||||
glm::vec3 getAlbedo(bool SRGB = true) const override;
|
||||
float getMetallic() const override;
|
||||
float getRoughness() const override;
|
||||
float getScattering() const override;
|
||||
bool resetOpacityMap() const override;
|
||||
graphics::Material::TextureMaps getTextureMaps() const override;
|
||||
glm::vec2 getLightmapParams() const override;
|
||||
bool getDefaultFallthrough() const override;
|
||||
|
||||
// NetworkMaterial
|
||||
bool isMissingTexture() override;
|
||||
bool checkResetOpacityMap() override;
|
||||
|
||||
// ProceduralMaterial
|
||||
bool isProcedural() const override;
|
||||
bool isEnabled() const override;
|
||||
bool isReady() const override;
|
||||
QString getProceduralString() const override;
|
||||
|
||||
glm::vec4 getColor(const glm::vec4& color) const override;
|
||||
bool isFading() const override;
|
||||
uint64_t getFadeStartTime() const override;
|
||||
bool hasVertexShader() const override;
|
||||
void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation,
|
||||
const uint64_t& created, const ProceduralProgramKey key = ProceduralProgramKey()) override;
|
||||
void initializeProcedural() override;
|
||||
|
||||
bool isReference() const override { return true; }
|
||||
std::function<graphics::MaterialPointer()> getReferenceOperator() const { return _materialForUUIDOperator; }
|
||||
|
||||
static void setMaterialForUUIDOperator(std::function<graphics::MaterialPointer(QUuid)> materialForUUIDOperator);
|
||||
|
||||
private:
|
||||
static std::function<graphics::MaterialPointer(QUuid)> _unboundMaterialForUUIDOperator;
|
||||
std::function<graphics::MaterialPointer()> _materialForUUIDOperator;
|
||||
mutable bool _locked { false };
|
||||
|
||||
graphics::MaterialPointer getMaterial() const;
|
||||
std::shared_ptr<NetworkMaterial> getNetworkMaterial() const;
|
||||
graphics::ProceduralMaterialPointer getProceduralMaterial() const;
|
||||
|
||||
template <typename T, typename F>
|
||||
T resultWithLock(F&& f) const;
|
||||
|
||||
template <typename F>
|
||||
void withLock(F&& f) const;
|
||||
};
|
|
@ -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"
|
||||
|
@ -378,6 +379,7 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
|
|||
|
||||
auto& drawMaterialTextures = multiMaterial.getTextureTable();
|
||||
multiMaterial.setTexturesLoading(false);
|
||||
multiMaterial.resetReferenceTexturesAndMaterials();
|
||||
|
||||
// The total list of things we need to look for
|
||||
static std::set<uint> allFlags;
|
||||
|
@ -408,9 +410,13 @@ 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();
|
||||
const auto materialKey = material->getKey();
|
||||
const auto textureMaps = material->getTextureMaps();
|
||||
|
||||
auto it = flagsToCheck.begin();
|
||||
while (it != flagsToCheck.end()) {
|
||||
|
@ -482,6 +488,9 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
|
|||
if (itr->second->isDefined()) {
|
||||
material->resetOpacityMap();
|
||||
drawMaterialTextures->setTexture(gr::Texture::MaterialAlbedo, itr->second->getTextureView());
|
||||
if (itr->second->getTextureView().isReference()) {
|
||||
multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator());
|
||||
}
|
||||
wasSet = true;
|
||||
} else {
|
||||
multiMaterial.setTexturesLoading(true);
|
||||
|
@ -501,6 +510,9 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
|
|||
if (itr != textureMaps.end()) {
|
||||
if (itr->second->isDefined()) {
|
||||
drawMaterialTextures->setTexture(gr::Texture::MaterialMetallic, itr->second->getTextureView());
|
||||
if (itr->second->getTextureView().isReference()) {
|
||||
multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator());
|
||||
}
|
||||
wasSet = true;
|
||||
} else {
|
||||
multiMaterial.setTexturesLoading(true);
|
||||
|
@ -518,6 +530,9 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
|
|||
if (itr != textureMaps.end()) {
|
||||
if (itr->second->isDefined()) {
|
||||
drawMaterialTextures->setTexture(gr::Texture::MaterialRoughness, itr->second->getTextureView());
|
||||
if (itr->second->getTextureView().isReference()) {
|
||||
multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator());
|
||||
}
|
||||
wasSet = true;
|
||||
} else {
|
||||
multiMaterial.setTexturesLoading(true);
|
||||
|
@ -535,6 +550,9 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
|
|||
if (itr != textureMaps.end()) {
|
||||
if (itr->second->isDefined()) {
|
||||
drawMaterialTextures->setTexture(gr::Texture::MaterialNormal, itr->second->getTextureView());
|
||||
if (itr->second->getTextureView().isReference()) {
|
||||
multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator());
|
||||
}
|
||||
wasSet = true;
|
||||
} else {
|
||||
multiMaterial.setTexturesLoading(true);
|
||||
|
@ -552,6 +570,9 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
|
|||
if (itr != textureMaps.end()) {
|
||||
if (itr->second->isDefined()) {
|
||||
drawMaterialTextures->setTexture(gr::Texture::MaterialOcclusion, itr->second->getTextureView());
|
||||
if (itr->second->getTextureView().isReference()) {
|
||||
multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator());
|
||||
}
|
||||
wasSet = true;
|
||||
} else {
|
||||
multiMaterial.setTexturesLoading(true);
|
||||
|
@ -569,6 +590,9 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
|
|||
if (itr != textureMaps.end()) {
|
||||
if (itr->second->isDefined()) {
|
||||
drawMaterialTextures->setTexture(gr::Texture::MaterialScattering, itr->second->getTextureView());
|
||||
if (itr->second->getTextureView().isReference()) {
|
||||
multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator());
|
||||
}
|
||||
wasSet = true;
|
||||
} else {
|
||||
multiMaterial.setTexturesLoading(true);
|
||||
|
@ -587,6 +611,9 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
|
|||
if (itr != textureMaps.end()) {
|
||||
if (itr->second->isDefined()) {
|
||||
drawMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, itr->second->getTextureView());
|
||||
if (itr->second->getTextureView().isReference()) {
|
||||
multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator());
|
||||
}
|
||||
wasSet = true;
|
||||
} else {
|
||||
multiMaterial.setTexturesLoading(true);
|
||||
|
@ -607,6 +634,9 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
|
|||
if (itr != textureMaps.end()) {
|
||||
if (itr->second->isDefined()) {
|
||||
drawMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, itr->second->getTextureView());
|
||||
if (itr->second->getTextureView().isReference()) {
|
||||
multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator());
|
||||
}
|
||||
wasSet = true;
|
||||
} else {
|
||||
multiMaterial.setTexturesLoading(true);
|
||||
|
|
|
@ -918,7 +918,6 @@ const GROUPS = [
|
|||
label: "Material Scale",
|
||||
type: "vec2",
|
||||
vec2Type: "xyz",
|
||||
min: 0,
|
||||
step: 0.1,
|
||||
decimals: 4,
|
||||
subLabels: [ "x", "y" ],
|
||||
|
|
Loading…
Reference in a new issue