From ff3545beab478ea1929e4d1dabb53cdf2d3cca4b Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 3 Jan 2019 15:28:02 -0800 Subject: [PATCH] working with texture transform fallthrough --- .../src/RenderableShapeEntityItem.cpp | 21 +++-- .../src/graphics-scripting/Forward.h | 6 +- .../GraphicsScriptingInterface.cpp | 14 +++ libraries/graphics/src/graphics/Material.cpp | 6 +- libraries/graphics/src/graphics/Material.h | 33 +++++-- .../src/model-networking/MaterialCache.cpp | 44 ++++++++++ .../render-utils/src/RenderPipelines.cpp | 85 ++++++++++++------- 7 files changed, 159 insertions(+), 50 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index d758a8769f..a78e4cebf0 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -125,13 +125,18 @@ void ShapeEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint } }); - _color = entity->getColor(); - _alpha = entity->getAlpha(); - _material->setAlbedo(toGlm(_color)); - _material->setOpacity(_alpha); - auto materials = _materials.find("0"); - if (materials != _materials.end()) { - materials->second.setNeedsUpdate(true); + glm::u8vec3 color = entity->getColor(); + float alpha = entity->getAlpha(); + if (_color != color || _alpha != alpha) { + _color = color; + _alpha = alpha; + _material->setAlbedo(toGlm(_color)); + _material->setOpacity(_alpha); + + auto materials = _materials.find("0"); + if (materials != _materials.end()) { + materials->second.setNeedsUpdate(true); + } } } @@ -279,7 +284,7 @@ scriptable::ScriptableModelBase ShapeEntityRenderer::getScriptableModel() { { std::lock_guard lock(_materialsLock); result.appendMaterials(_materials); - auto& materials = _materials.find("0"); + auto materials = _materials.find("0"); if (materials != _materials.end()) { vertexColor = materials->second.getSchemaBuffer().get()._albedo; } diff --git a/libraries/graphics-scripting/src/graphics-scripting/Forward.h b/libraries/graphics-scripting/src/graphics-scripting/Forward.h index 78d34a9dee..43b0daf407 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/Forward.h +++ b/libraries/graphics-scripting/src/graphics-scripting/Forward.h @@ -59,6 +59,10 @@ namespace scriptable { * @property {string} occlusionMap * @property {string} lightmapMap * @property {string} scatteringMap + * @property {string} texCoordTransform0 + * @property {string} texCoordTransform1 + * @property {string} lightmapParams + * @property {string} materialParams * @property {boolean} defaultFallthrough */ class ScriptableMaterial { @@ -91,7 +95,7 @@ namespace scriptable { QString scatteringMap; bool defaultFallthrough; - std::unordered_map propertyFallthroughs; // not actually exposed to script + std::unordered_map propertyFallthroughs; // not actually exposed to script }; /**jsdoc diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp index 51d805a0a5..3293d294d8 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp @@ -404,6 +404,20 @@ namespace scriptable { obj.setProperty("bumpMap", material.bumpMap); } + // These need to be implemented, but set the fallthrough for now + if (material.propertyFallthroughs.at(graphics::Material::TEXCOORDTRANSFORM0)) { + obj.setProperty("texCoordTransform0", FALLTHROUGH); + } + if (material.propertyFallthroughs.at(graphics::Material::TEXCOORDTRANSFORM1)) { + obj.setProperty("texCoordTransform1", FALLTHROUGH); + } + if (material.propertyFallthroughs.at(graphics::Material::LIGHTMAP_PARAMS)) { + obj.setProperty("lightmapParams", FALLTHROUGH); + } + if (material.propertyFallthroughs.at(graphics::Material::MATERIAL_PARAMS)) { + obj.setProperty("materialParams", FALLTHROUGH); + } + obj.setProperty("defaultFallthrough", material.defaultFallthrough); return obj; diff --git a/libraries/graphics/src/graphics/Material.cpp b/libraries/graphics/src/graphics/Material.cpp index 18f9c29a13..7befb7e053 100755 --- a/libraries/graphics/src/graphics/Material.cpp +++ b/libraries/graphics/src/graphics/Material.cpp @@ -25,8 +25,8 @@ const float Material::DEFAULT_ROUGHNESS { 1.0f }; const float Material::DEFAULT_SCATTERING { 0.0f }; Material::Material() { - for (int i = 0; i < graphics::MaterialKey::NUM_FLAGS; i++) { - _propertyFallthroughs[graphics::MaterialKey::FlagBit(i)] = false; + for (int i = 0; i < NUM_TOTAL_FLAGS; i++) { + _propertyFallthroughs[i] = false; } } @@ -201,7 +201,7 @@ void MultiMaterial::calculateMaterialInfo() const { _textureSize = 0; _textureCount = 0; - auto& textures = _textureTable->getTextures(); + auto textures = _textureTable->getTextures(); for (auto const &texture : textures) { if (texture && texture->isDefined()) { auto size = texture->getSize(); diff --git a/libraries/graphics/src/graphics/Material.h b/libraries/graphics/src/graphics/Material.h index 3287bf7825..e7f5ea8891 100755 --- a/libraries/graphics/src/graphics/Material.h +++ b/libraries/graphics/src/graphics/Material.h @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -176,7 +177,6 @@ public: bool isTexelOpaque() const { return isOpaque() && isOpacityMaskMap(); } }; - class MaterialFilter { public: MaterialKey::Flags _value{ 0 }; @@ -267,7 +267,7 @@ public: class Material { public: typedef MaterialKey::MapChannel MapChannel; - typedef std::unordered_map TextureMaps; + typedef std::map TextureMaps; Material(); Material(const Material& material); @@ -322,17 +322,30 @@ 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]; } + glm::vec2 getLightmapParams() const { return _lightmapParams; } + glm::vec2 getMaterialParams() const { return _materialParams; } + bool getDefaultFallthrough() const { return _defaultFallthrough; } void setDefaultFallthrough(bool defaultFallthrough) { _defaultFallthrough = defaultFallthrough; } - std::unordered_map getPropertyFallthroughs() { return _propertyFallthroughs; } - bool getPropertyFallthrough(MaterialKey::FlagBit property) { return _propertyFallthroughs[property]; } - void setPropertyDoesFallthrough(MaterialKey::FlagBit property) { _propertyFallthroughs[property] = true; } + enum ExtraFlagBit { + TEXCOORDTRANSFORM0 = MaterialKey::NUM_FLAGS, + TEXCOORDTRANSFORM1, + LIGHTMAP_PARAMS, + MATERIAL_PARAMS, + + NUM_TOTAL_FLAGS + }; + std::unordered_map getPropertyFallthroughs() { return _propertyFallthroughs; } + bool getPropertyFallthrough(uint property) { return _propertyFallthroughs[property]; } + void setPropertyDoesFallthrough(uint property) { _propertyFallthroughs[property] = true; } protected: std::string _name { "" }; private: + std::string _model { "hifi_pbr" }; mutable MaterialKey _key { 0 }; // Material properties @@ -348,11 +361,9 @@ private: TextureMaps _textureMaps; bool _defaultFallthrough { false }; - std::unordered_map _propertyFallthroughs; + std::unordered_map _propertyFallthroughs { NUM_TOTAL_FLAGS }; mutable QMutex _textureMapsMutex { QMutex::Recursive }; - - std::string _model { "hifi_pbr" }; }; typedef std::shared_ptr MaterialPointer; @@ -434,7 +445,11 @@ public: // y: 1 for texture repeat, 0 for discard outside of 0 - 1 glm::vec2 _materialParams { 0.0, 1.0 }; - Schema() {} + Schema() { + for (auto& transform : _texcoordTransforms) { + transform = glm::mat4(); + } + } }; gpu::BufferView& getSchemaBuffer() { return _schemaBuffer; } diff --git a/libraries/model-networking/src/model-networking/MaterialCache.cpp b/libraries/model-networking/src/model-networking/MaterialCache.cpp index 46d0cc291a..b6550a5e9e 100644 --- a/libraries/model-networking/src/model-networking/MaterialCache.cpp +++ b/libraries/model-networking/src/model-networking/MaterialCache.cpp @@ -153,6 +153,14 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater * bumpMap is specified. Set to "fallthrough" to fallthrough to the material below. "hifi_pbr" model only. * @property {string} lightMap - URL of light map texture image. Currently not used.. Set to "fallthrough" * to fallthrough to the material below. "hifi_pbr" model only. + * @property {string} texCoordTransform0 - The transform to use for all of the maps besides occlusionMap and lightMap. Currently unused. Set to + * "fallthrough" to fallthrough to the material below. "hifi_pbr" model only. + * @property {string} texCoordTransform1 - The transform to use for occlusionMap and lightMap. Currently unused. Set to "fallthrough" + * to fallthrough to the material below. "hifi_pbr" model only. + * @property {string} lightmapParams - Parameters for controlling how lightMap is used. Currently unused. Set to "fallthrough" + * to fallthrough to the material below. "hifi_pbr" model only. + * @property {string} materialParams - Parameters for controlling the material projection and repition. Currently unused. Set to "fallthrough" + * to fallthrough to the material below. "hifi_pbr" model only. * @property {bool} defaultFallthrough=false - If true, all properties will fallthrough to the material below unless they are set. If * false, they will respect the individual properties' fallthrough state. "hifi_pbr" model only. */ @@ -356,6 +364,42 @@ std::pair> NetworkMaterialResource material->setLightmapMap(baseUrl.resolved(valueString)); } } + } else if (key == "texCoordTransform0") { + auto value = materialJSON.value(key); + if (value.isString()) { + auto valueString = value.toString(); + if (valueString == FALLTHROUGH) { + material->setPropertyDoesFallthrough(graphics::Material::ExtraFlagBit::TEXCOORDTRANSFORM0); + } + } + // TODO: implement texCoordTransform0 + } else if (key == "texCoordTransform1") { + auto value = materialJSON.value(key); + if (value.isString()) { + auto valueString = value.toString(); + if (valueString == FALLTHROUGH) { + material->setPropertyDoesFallthrough(graphics::Material::ExtraFlagBit::TEXCOORDTRANSFORM1); + } + } + // TODO: implement texCoordTransform1 + } else if (key == "lightmapParams") { + auto value = materialJSON.value(key); + if (value.isString()) { + auto valueString = value.toString(); + if (valueString == FALLTHROUGH) { + material->setPropertyDoesFallthrough(graphics::Material::ExtraFlagBit::LIGHTMAP_PARAMS); + } + } + // TODO: implement lightmapParams + } else if (key == "materialParams") { + auto value = materialJSON.value(key); + if (value.isString()) { + auto valueString = value.toString(); + if (valueString == FALLTHROUGH) { + material->setPropertyDoesFallthrough(graphics::Material::ExtraFlagBit::MATERIAL_PARAMS); + } + } + // TODO: implement materialParams } else if (key == "defaultFallthrough") { auto value = materialJSON.value(key); if (value.isBool()) { diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 0d8f6bdd40..b6203c44f8 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -392,15 +392,14 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial auto& drawMaterialTextures = multiMaterial.getTextureTable(); // The total list of things we need to look for - static std::set allFlagBits; + static std::set allFlags; static std::once_flag once; std::call_once(once, [textureCache] { - for (int i = 0; i < graphics::MaterialKey::NUM_FLAGS; i++) { - auto flagBit = graphics::MaterialKey::FlagBit(i); + for (int i = 0; i < graphics::Material::NUM_TOTAL_FLAGS; i++) { // The opacity mask/map are derived from the albedo map - if (flagBit != graphics::MaterialKey::OPACITY_MASK_MAP_BIT && - flagBit != graphics::MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT) { - allFlagBits.insert(flagBit); + if (i != graphics::MaterialKey::OPACITY_MASK_MAP_BIT && + i != graphics::MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT) { + allFlags.insert(i); } } }); @@ -409,21 +408,28 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial graphics::MultiMaterial::Schema schema; graphics::MaterialKey schemaKey; - std::set flagBitsToCheck = allFlagBits; - std::set flagBitsToSetDefault; + std::set flagsToCheck = allFlags; + std::set flagsToSetDefault; + + while (!materials.empty()) { + auto material = materials.top().material; + if (!material) { + break; + } + materials.pop(); - auto material = materials.top().material; - while (material) { bool defaultFallthrough = material->getDefaultFallthrough(); const auto& materialKey = material->getKey(); const auto& textureMaps = material->getTextureMaps(); - auto it = flagBitsToCheck.begin(); - while (it != flagBitsToCheck.end()) { - auto flagBit = *it; + auto it = flagsToCheck.begin(); + while (it != flagsToCheck.end()) { + auto flag = *it; + bool fallthrough = defaultFallthrough || material->getPropertyFallthrough(flag); + bool wasSet = false; bool forceDefault = false; - switch (flagBit) { + switch (flag) { case graphics::MaterialKey::EMISSIVE_VAL_BIT: if (materialKey.isEmissive()) { schema._emissive = material->getEmissive(false); @@ -574,36 +580,56 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial schemaKey.setLightmapMap(true); } break; + case graphics::Material::TEXCOORDTRANSFORM0: + if (!fallthrough) { + schema._texcoordTransforms[0] = material->getTexCoordTransform(0); + wasSet = true; + } + break; + case graphics::Material::TEXCOORDTRANSFORM1: + if (!fallthrough) { + schema._texcoordTransforms[1] = material->getTexCoordTransform(1); + wasSet = true; + } + break; + case graphics::Material::LIGHTMAP_PARAMS: + if (!fallthrough) { + schema._lightmapParams = material->getLightmapParams(); + wasSet = true; + } + break; + case graphics::Material::MATERIAL_PARAMS: + if (!fallthrough) { + schema._materialParams = material->getMaterialParams(); + wasSet = true; + } + break; default: break; } - bool fallthrough = defaultFallthrough || material->getPropertyFallthrough(flagBit); if (wasSet) { - flagBitsToCheck.erase(it++); + flagsToCheck.erase(it++); } else if (forceDefault || !fallthrough) { - flagBitsToSetDefault.insert(flagBit); - flagBitsToCheck.erase(it++); + flagsToSetDefault.insert(flag); + flagsToCheck.erase(it++); } else { ++it; } } - if (flagBitsToCheck.empty()) { + if (flagsToCheck.empty()) { break; } - - materials.pop(); - material = materials.top().material; } - for (auto flagBit : flagBitsToCheck) { - flagBitsToSetDefault.insert(flagBit); + for (auto flagBit : flagsToCheck) { + flagsToSetDefault.insert(flagBit); } // Handle defaults - for (auto flagBit : flagBitsToSetDefault) { - switch (flagBit) { + for (auto flag : flagsToSetDefault) { + switch (flag) { case graphics::MaterialKey::EMISSIVE_VAL_BIT: case graphics::MaterialKey::UNLIT_VAL_BIT: case graphics::MaterialKey::ALBEDO_VAL_BIT: @@ -611,6 +637,10 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial case graphics::MaterialKey::GLOSSY_VAL_BIT: case graphics::MaterialKey::OPACITY_VAL_BIT: case graphics::MaterialKey::SCATTERING_VAL_BIT: + case graphics::Material::TEXCOORDTRANSFORM0: + case graphics::Material::TEXCOORDTRANSFORM1: + case graphics::Material::LIGHTMAP_PARAMS: + case graphics::Material::MATERIAL_PARAMS: // these are initialized to the correct default values in Schema() break; case graphics::MaterialKey::ALBEDO_MAP_BIT: @@ -658,9 +688,6 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial } } - // FIXME: - // set transforms and params - schema._key = (uint32_t)schemaKey._flags.to_ulong(); schemaBuffer.edit() = schema; multiMaterial.setNeedsUpdate(false);