This commit is contained in:
HifiExperiments 2021-07-05 16:49:17 -07:00
parent 7f99ddca2e
commit bdbb88084b
12 changed files with 180 additions and 85 deletions

View file

@ -635,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);
@ -662,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();
}

View file

@ -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(

View file

@ -954,7 +954,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
* @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
* 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
@ -1380,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

View file

@ -898,8 +898,11 @@ void SphericalHarmonics::evalFromTexture(const Texture& texture, gpu::BackendTar
// TextureSource
const gpu::TexturePointer TextureSource::getGPUTexture() const {
if (_gpuTextureOperator) {
return _gpuTextureOperator();
if (_gpuTextureOperator && !_locked) {
_locked = true;
auto gpuTexture = _gpuTextureOperator();
_locked = false;
return gpuTexture;
}
return _gpuTexture;
}
@ -915,8 +918,10 @@ void TextureSource::resetTextureOperator(const std::function<gpu::TexturePointer
}
bool TextureSource::isDefined() const {
if (_gpuTextureOperator) {
if (_gpuTextureOperator && !_locked) {
_locked = true;
auto gpuTexture = _gpuTextureOperator();
_locked = false;
return gpuTexture && gpuTexture->isDefined();
}
return _gpuTexture && _gpuTexture->isDefined();

View file

@ -727,6 +727,7 @@ public:
protected:
gpu::TexturePointer _gpuTexture;
std::function<gpu::TexturePointer()> _gpuTextureOperator { nullptr };
mutable bool _locked { false };
QUrl _imageUrl;
int _type { 0 };
};

View file

@ -341,7 +341,7 @@ public:
virtual ~Material() = default;
Material& operator= (const Material& material);
virtual 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);
@ -385,7 +385,7 @@ public:
// The texture map to channel association
static const int NUM_TEXCOORD_TRANSFORMS { 2 };
void setTextureMap(MapChannel channel, const TextureMapPointer& textureMap);
virtual 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

View file

@ -1402,4 +1402,9 @@ std::function<gpu::TexturePointer()> Texture::getTextureForUUIDOperator(const QU
return std::bind(_unboundTextureForUUIDOperator, uuid);
}
return nullptr;
}
}
void Texture::setUnboundTextureForUUIDOperator(std::function<gpu::TexturePointer(const QUuid&)> textureForUUIDOperator) {
_unboundTextureForUUIDOperator = textureForUUIDOperator;
}

View file

@ -41,7 +41,7 @@ public:
gpu::TextureSourcePointer _textureSource;
static std::function<gpu::TexturePointer()> getTextureForUUIDOperator(const QUuid& uuid);
static void setUnboundTextureForUUIDOperator(std::function<gpu::TexturePointer(const QUuid&)> textureForUUIDOperator) { _unboundTextureForUUIDOperator = textureForUUIDOperator; }
static void setUnboundTextureForUUIDOperator(std::function<gpu::TexturePointer(const QUuid&)> textureForUUIDOperator);
private:
static std::function<gpu::TexturePointer(const QUuid&)> _unboundTextureForUUIDOperator;

View file

@ -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 or entity IDs. 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 a Web entity.
* @property {ProceduralUniforms} uniforms={} - A {@link ProceduralUniforms} object containing all the custom uniforms to be passed to the shader.
*/

View file

@ -18,157 +18,216 @@ ReferenceMaterial::ReferenceMaterial(QUuid uuid) :
}
// Material
const graphics::MaterialKey& ReferenceMaterial::getKey() const {
auto material = getMaterial();
return material ? material->getKey() : Parent::getKey();
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 {
auto material = getMaterial();
return material ? material->getEmissive(SRGB) : glm::vec3(DEFAULT_EMISSIVE);
return resultWithLock<glm::vec3>([&] {
auto material = getMaterial();
return material ? material->getEmissive(SRGB) : glm::vec3(DEFAULT_EMISSIVE);
});
}
float ReferenceMaterial::getOpacity() const {
auto material = getMaterial();
return material ? material->getOpacity() : DEFAULT_OPACITY;
return resultWithLock<float>([&] {
auto material = getMaterial();
return material ? material->getOpacity() : DEFAULT_OPACITY;
});
}
graphics::MaterialKey::OpacityMapMode ReferenceMaterial::getOpacityMapMode() const {
auto material = getMaterial();
return material ? material->getOpacityMapMode() : DEFAULT_OPACITY_MAP_MODE;
return resultWithLock<graphics::MaterialKey::OpacityMapMode>([&] {
auto material = getMaterial();
return material ? material->getOpacityMapMode() : DEFAULT_OPACITY_MAP_MODE;
});
}
float ReferenceMaterial::getOpacityCutoff() const {
auto material = getMaterial();
return material ? material->getOpacityCutoff() : DEFAULT_OPACITY_CUTOFF;
return resultWithLock<float>([&] {
auto material = getMaterial();
return material ? material->getOpacityCutoff() : DEFAULT_OPACITY_CUTOFF;
});
}
graphics::MaterialKey::CullFaceMode ReferenceMaterial::getCullFaceMode() const {
auto material = getMaterial();
return material ? material->getCullFaceMode() : DEFAULT_CULL_FACE_MODE;
return resultWithLock<graphics::MaterialKey::CullFaceMode>([&] {
auto material = getMaterial();
return material ? material->getCullFaceMode() : DEFAULT_CULL_FACE_MODE;
});
}
bool ReferenceMaterial::isUnlit() const {
auto material = getMaterial();
return material ? material->isUnlit() : false;
return resultWithLock<bool>([&] {
auto material = getMaterial();
return material ? material->isUnlit() : false;
});
}
glm::vec3 ReferenceMaterial::getAlbedo(bool SRGB) const {
auto material = getMaterial();
return material ? material->getAlbedo(SRGB) : glm::vec3(DEFAULT_ALBEDO);
return resultWithLock<glm::vec3>([&] {
auto material = getMaterial();
return material ? material->getAlbedo(SRGB) : glm::vec3(DEFAULT_ALBEDO);
});
}
float ReferenceMaterial::getMetallic() const {
auto material = getMaterial();
return material ? material->getMetallic() : DEFAULT_METALLIC;
return resultWithLock<float>([&] {
auto material = getMaterial();
return material ? material->getMetallic() : DEFAULT_METALLIC;
});
}
float ReferenceMaterial::getRoughness() const {
auto material = getMaterial();
return material ? material->getRoughness() : DEFAULT_ROUGHNESS;
return resultWithLock<float>([&] {
auto material = getMaterial();
return material ? material->getRoughness() : DEFAULT_ROUGHNESS;
});
}
float ReferenceMaterial::getScattering() const {
auto material = getMaterial();
return material ? material->getScattering() : DEFAULT_SCATTERING;
return resultWithLock<float>([&] {
auto material = getMaterial();
return material ? material->getScattering() : DEFAULT_SCATTERING;
});
}
bool ReferenceMaterial::resetOpacityMap() const {
auto material = getMaterial();
return material ? material->resetOpacityMap() : false;
return resultWithLock<bool>([&] {
auto material = getMaterial();
return material ? material->resetOpacityMap() : false;
});
}
const graphics::Material::TextureMaps& ReferenceMaterial::getTextureMaps() const {
auto material = getMaterial();
return material ? material->getTextureMaps() : Parent::getTextureMaps();
}
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 {
auto material = getMaterial();
return material ? material->getLightmapParams() : glm::vec2(0.0f, 1.0f);
return resultWithLock<glm::vec2>([&] {
auto material = getMaterial();
return material ? material->getLightmapParams() : glm::vec2(0.0f, 1.0f);
});
}
bool ReferenceMaterial::getDefaultFallthrough() const {
auto material = getMaterial();
return material ? material->getDefaultFallthrough() : false;
return resultWithLock<bool>([&] {
auto material = getMaterial();
return material ? material->getDefaultFallthrough() : false;
});
}
// NetworkMaterial
bool ReferenceMaterial::isMissingTexture() {
auto material = getNetworkMaterial();
return material ? material->isMissingTexture() : false;
return resultWithLock<bool>([&] {
auto material = getNetworkMaterial();
return material ? material->isMissingTexture() : false;
});
}
bool ReferenceMaterial::checkResetOpacityMap() {
auto material = getNetworkMaterial();
return material ? material->checkResetOpacityMap() : false;
return resultWithLock<bool>([&] {
auto material = getNetworkMaterial();
return material ? material->checkResetOpacityMap() : false;
});
}
// ProceduralMaterial
bool ReferenceMaterial::isProcedural() const {
auto material = getMaterial();
return material ? material->isProcedural() : false;
return resultWithLock<bool>([&] {
auto material = getMaterial();
return material ? material->isProcedural() : false;
});
}
bool ReferenceMaterial::isEnabled() const {
auto material = getMaterial();
return material ? material->isEnabled() : false;
return resultWithLock<bool>([&] {
auto material = getMaterial();
return material ? material->isEnabled() : false;
});
}
bool ReferenceMaterial::isReady() const {
auto material = getMaterial();
return material ? material->isReady() : false;
return resultWithLock<bool>([&] {
auto material = getMaterial();
return material ? material->isReady() : false;
});
}
QString ReferenceMaterial::getProceduralString() const {
auto material = getMaterial();
return material ? material->getProceduralString() : QString();
return resultWithLock<QString>([&] {
auto material = getMaterial();
return material ? material->getProceduralString() : QString();
});
}
glm::vec4 ReferenceMaterial::getColor(const glm::vec4& color) const {
auto material = getProceduralMaterial();
return material ? material->getColor(color) : glm::vec4();
return resultWithLock<glm::vec4>([&] {
auto material = getProceduralMaterial();
return material ? material->getColor(color) : glm::vec4();
});
}
bool ReferenceMaterial::isFading() const {
auto material = getProceduralMaterial();
return material ? material->isFading() : false;
return resultWithLock<bool>([&] {
auto material = getProceduralMaterial();
return material ? material->isFading() : false;
});
}
uint64_t ReferenceMaterial::getFadeStartTime() const {
auto material = getProceduralMaterial();
return material ? material->getFadeStartTime() : 0;
return resultWithLock<uint64_t>([&] {
auto material = getProceduralMaterial();
return material ? material->getFadeStartTime() : 0;
});
}
bool ReferenceMaterial::hasVertexShader() const {
auto material = getProceduralMaterial();
return material ? material->hasVertexShader() : false;
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) {
if (auto material = getProceduralMaterial()) {
material->prepare(batch, position, size, orientation, created, key);
}
const uint64_t& created, const ProceduralProgramKey key) {
withLock([&] {
if (auto material = getProceduralMaterial()) {
material->prepare(batch, position, size, orientation, created, key);
}
});
}
void ReferenceMaterial::initializeProcedural() {
if (auto material = getProceduralMaterial()) {
material->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) {
return _materialForUUIDOperator();
auto material = _materialForUUIDOperator();
return material;
}
return nullptr;
}
std::shared_ptr<NetworkMaterial> ReferenceMaterial::getNetworkMaterial() const {
if (_materialForUUIDOperator) {
auto material = _materialForUUIDOperator();
if (material && material->isProcedural()) {
std::shared_ptr<NetworkMaterial> result = nullptr;
if (auto material = _materialForUUIDOperator()) {
return std::static_pointer_cast<NetworkMaterial>(material);
}
}
@ -184,3 +243,24 @@ graphics::ProceduralMaterialPointer ReferenceMaterial::getProceduralMaterial() c
}
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;
}
}

View file

@ -18,7 +18,7 @@ public:
ReferenceMaterial(QUuid uuid);
// Material
const graphics::MaterialKey& getKey() const override;
graphics::MaterialKey getKey() const override;
glm::vec3 getEmissive(bool SRGB = true) const override;
float getOpacity() const override;
graphics::MaterialKey::OpacityMapMode getOpacityMapMode() const override;
@ -30,10 +30,8 @@ public:
float getRoughness() const override;
float getScattering() const override;
bool resetOpacityMap() const override;
const graphics::Material::TextureMaps& getTextureMaps() const override;
//glm::mat4 getTexCoordTransform(uint i) const override; // use my actual transform, instead of the original
graphics::Material::TextureMaps getTextureMaps() const override;
glm::vec2 getLightmapParams() const override;
//glm::vec2 getMaterialParams() const override; // use my actual params, instead of the original
bool getDefaultFallthrough() const override;
// NetworkMaterial
@ -57,13 +55,20 @@ public:
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; }
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;
};

View file

@ -415,8 +415,8 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
}
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()) {