working with texture transform fallthrough

This commit is contained in:
SamGondelman 2019-01-03 15:28:02 -08:00
parent a2fe8ef9e7
commit ff3545beab
7 changed files with 159 additions and 50 deletions

View file

@ -125,13 +125,18 @@ void ShapeEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint
} }
}); });
_color = entity->getColor(); glm::u8vec3 color = entity->getColor();
_alpha = entity->getAlpha(); float alpha = entity->getAlpha();
_material->setAlbedo(toGlm(_color)); if (_color != color || _alpha != alpha) {
_material->setOpacity(_alpha); _color = color;
auto materials = _materials.find("0"); _alpha = alpha;
if (materials != _materials.end()) { _material->setAlbedo(toGlm(_color));
materials->second.setNeedsUpdate(true); _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<std::mutex> lock(_materialsLock); std::lock_guard<std::mutex> lock(_materialsLock);
result.appendMaterials(_materials); result.appendMaterials(_materials);
auto& materials = _materials.find("0"); auto materials = _materials.find("0");
if (materials != _materials.end()) { if (materials != _materials.end()) {
vertexColor = materials->second.getSchemaBuffer().get<graphics::MultiMaterial::Schema>()._albedo; vertexColor = materials->second.getSchemaBuffer().get<graphics::MultiMaterial::Schema>()._albedo;
} }

View file

@ -59,6 +59,10 @@ namespace scriptable {
* @property {string} occlusionMap * @property {string} occlusionMap
* @property {string} lightmapMap * @property {string} lightmapMap
* @property {string} scatteringMap * @property {string} scatteringMap
* @property {string} texCoordTransform0
* @property {string} texCoordTransform1
* @property {string} lightmapParams
* @property {string} materialParams
* @property {boolean} defaultFallthrough * @property {boolean} defaultFallthrough
*/ */
class ScriptableMaterial { class ScriptableMaterial {
@ -91,7 +95,7 @@ namespace scriptable {
QString scatteringMap; QString scatteringMap;
bool defaultFallthrough; bool defaultFallthrough;
std::unordered_map<graphics::MaterialKey::FlagBit, bool> propertyFallthroughs; // not actually exposed to script std::unordered_map<uint, bool> propertyFallthroughs; // not actually exposed to script
}; };
/**jsdoc /**jsdoc

View file

@ -404,6 +404,20 @@ namespace scriptable {
obj.setProperty("bumpMap", material.bumpMap); 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); obj.setProperty("defaultFallthrough", material.defaultFallthrough);
return obj; return obj;

View file

@ -25,8 +25,8 @@ const float Material::DEFAULT_ROUGHNESS { 1.0f };
const float Material::DEFAULT_SCATTERING { 0.0f }; const float Material::DEFAULT_SCATTERING { 0.0f };
Material::Material() { Material::Material() {
for (int i = 0; i < graphics::MaterialKey::NUM_FLAGS; i++) { for (int i = 0; i < NUM_TOTAL_FLAGS; i++) {
_propertyFallthroughs[graphics::MaterialKey::FlagBit(i)] = false; _propertyFallthroughs[i] = false;
} }
} }
@ -201,7 +201,7 @@ void MultiMaterial::calculateMaterialInfo() const {
_textureSize = 0; _textureSize = 0;
_textureCount = 0; _textureCount = 0;
auto& textures = _textureTable->getTextures(); auto textures = _textureTable->getTextures();
for (auto const &texture : textures) { for (auto const &texture : textures) {
if (texture && texture->isDefined()) { if (texture && texture->isDefined()) {
auto size = texture->getSize(); auto size = texture->getSize();

View file

@ -14,6 +14,7 @@
#include <QMutex> #include <QMutex>
#include <bitset> #include <bitset>
#include <map>
#include <unordered_map> #include <unordered_map>
#include <queue> #include <queue>
@ -176,7 +177,6 @@ public:
bool isTexelOpaque() const { return isOpaque() && isOpacityMaskMap(); } bool isTexelOpaque() const { return isOpaque() && isOpacityMaskMap(); }
}; };
class MaterialFilter { class MaterialFilter {
public: public:
MaterialKey::Flags _value{ 0 }; MaterialKey::Flags _value{ 0 };
@ -267,7 +267,7 @@ public:
class Material { class Material {
public: public:
typedef MaterialKey::MapChannel MapChannel; typedef MaterialKey::MapChannel MapChannel;
typedef std::unordered_map<MapChannel, TextureMapPointer> TextureMaps; typedef std::map<MapChannel, TextureMapPointer> TextureMaps;
Material(); Material();
Material(const Material& material); Material(const Material& material);
@ -322,17 +322,30 @@ public:
const std::string& getModel() const { return _model; } const std::string& getModel() const { return _model; }
void setModel(const std::string& model) { _model = 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; } bool getDefaultFallthrough() const { return _defaultFallthrough; }
void setDefaultFallthrough(bool defaultFallthrough) { _defaultFallthrough = defaultFallthrough; } void setDefaultFallthrough(bool defaultFallthrough) { _defaultFallthrough = defaultFallthrough; }
std::unordered_map<MaterialKey::FlagBit, bool> getPropertyFallthroughs() { return _propertyFallthroughs; } enum ExtraFlagBit {
bool getPropertyFallthrough(MaterialKey::FlagBit property) { return _propertyFallthroughs[property]; } TEXCOORDTRANSFORM0 = MaterialKey::NUM_FLAGS,
void setPropertyDoesFallthrough(MaterialKey::FlagBit property) { _propertyFallthroughs[property] = true; } TEXCOORDTRANSFORM1,
LIGHTMAP_PARAMS,
MATERIAL_PARAMS,
NUM_TOTAL_FLAGS
};
std::unordered_map<uint, bool> getPropertyFallthroughs() { return _propertyFallthroughs; }
bool getPropertyFallthrough(uint property) { return _propertyFallthroughs[property]; }
void setPropertyDoesFallthrough(uint property) { _propertyFallthroughs[property] = true; }
protected: protected:
std::string _name { "" }; std::string _name { "" };
private: private:
std::string _model { "hifi_pbr" };
mutable MaterialKey _key { 0 }; mutable MaterialKey _key { 0 };
// Material properties // Material properties
@ -348,11 +361,9 @@ private:
TextureMaps _textureMaps; TextureMaps _textureMaps;
bool _defaultFallthrough { false }; bool _defaultFallthrough { false };
std::unordered_map<MaterialKey::FlagBit, bool> _propertyFallthroughs; std::unordered_map<uint, bool> _propertyFallthroughs { NUM_TOTAL_FLAGS };
mutable QMutex _textureMapsMutex { QMutex::Recursive }; mutable QMutex _textureMapsMutex { QMutex::Recursive };
std::string _model { "hifi_pbr" };
}; };
typedef std::shared_ptr<Material> MaterialPointer; typedef std::shared_ptr<Material> MaterialPointer;
@ -434,7 +445,11 @@ public:
// y: 1 for texture repeat, 0 for discard outside of 0 - 1 // y: 1 for texture repeat, 0 for discard outside of 0 - 1
glm::vec2 _materialParams { 0.0, 1.0 }; glm::vec2 _materialParams { 0.0, 1.0 };
Schema() {} Schema() {
for (auto& transform : _texcoordTransforms) {
transform = glm::mat4();
}
}
}; };
gpu::BufferView& getSchemaBuffer() { return _schemaBuffer; } gpu::BufferView& getSchemaBuffer() { return _schemaBuffer; }

View file

@ -153,6 +153,14 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater
* <code>bumpMap</code> is specified. Set to <code>"fallthrough"</code> to fallthrough to the material below. "hifi_pbr" model only. * <code>bumpMap</code> is specified. Set to <code>"fallthrough"</code> to fallthrough to the material below. "hifi_pbr" model only.
* @property {string} lightMap - URL of light map texture image. <em>Currently not used.</em>. Set to <code>"fallthrough"</code> * @property {string} lightMap - URL of light map texture image. <em>Currently not used.</em>. Set to <code>"fallthrough"</code>
* to fallthrough to the material below. "hifi_pbr" model only. * 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
* <code>"fallthrough"</code> 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 <code>"fallthrough"</code>
* to fallthrough to the material below. "hifi_pbr" model only.
* @property {string} lightmapParams - Parameters for controlling how lightMap is used. Currently unused. Set to <code>"fallthrough"</code>
* 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 <code>"fallthrough"</code>
* to fallthrough to the material below. "hifi_pbr" model only.
* @property {bool} defaultFallthrough=false - If <code>true</code>, all properties will fallthrough to the material below unless they are set. If * @property {bool} defaultFallthrough=false - If <code>true</code>, all properties will fallthrough to the material below unless they are set. If
* <code>false</code>, they will respect the individual properties' fallthrough state. "hifi_pbr" model only. * <code>false</code>, they will respect the individual properties' fallthrough state. "hifi_pbr" model only.
*/ */
@ -356,6 +364,42 @@ std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource
material->setLightmapMap(baseUrl.resolved(valueString)); 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") { } else if (key == "defaultFallthrough") {
auto value = materialJSON.value(key); auto value = materialJSON.value(key);
if (value.isBool()) { if (value.isBool()) {

View file

@ -392,15 +392,14 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
auto& drawMaterialTextures = multiMaterial.getTextureTable(); auto& drawMaterialTextures = multiMaterial.getTextureTable();
// The total list of things we need to look for // The total list of things we need to look for
static std::set<graphics::MaterialKey::FlagBit> allFlagBits; static std::set<uint> allFlags;
static std::once_flag once; static std::once_flag once;
std::call_once(once, [textureCache] { std::call_once(once, [textureCache] {
for (int i = 0; i < graphics::MaterialKey::NUM_FLAGS; i++) { for (int i = 0; i < graphics::Material::NUM_TOTAL_FLAGS; i++) {
auto flagBit = graphics::MaterialKey::FlagBit(i);
// The opacity mask/map are derived from the albedo map // The opacity mask/map are derived from the albedo map
if (flagBit != graphics::MaterialKey::OPACITY_MASK_MAP_BIT && if (i != graphics::MaterialKey::OPACITY_MASK_MAP_BIT &&
flagBit != graphics::MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT) { i != graphics::MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT) {
allFlagBits.insert(flagBit); allFlags.insert(i);
} }
} }
}); });
@ -409,21 +408,28 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
graphics::MultiMaterial::Schema schema; graphics::MultiMaterial::Schema schema;
graphics::MaterialKey schemaKey; graphics::MaterialKey schemaKey;
std::set<graphics::MaterialKey::FlagBit> flagBitsToCheck = allFlagBits; std::set<uint> flagsToCheck = allFlags;
std::set<graphics::MaterialKey::FlagBit> flagBitsToSetDefault; std::set<uint> 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(); bool defaultFallthrough = material->getDefaultFallthrough();
const auto& materialKey = material->getKey(); const auto& materialKey = material->getKey();
const auto& textureMaps = material->getTextureMaps(); const auto& textureMaps = material->getTextureMaps();
auto it = flagBitsToCheck.begin(); auto it = flagsToCheck.begin();
while (it != flagBitsToCheck.end()) { while (it != flagsToCheck.end()) {
auto flagBit = *it; auto flag = *it;
bool fallthrough = defaultFallthrough || material->getPropertyFallthrough(flag);
bool wasSet = false; bool wasSet = false;
bool forceDefault = false; bool forceDefault = false;
switch (flagBit) { switch (flag) {
case graphics::MaterialKey::EMISSIVE_VAL_BIT: case graphics::MaterialKey::EMISSIVE_VAL_BIT:
if (materialKey.isEmissive()) { if (materialKey.isEmissive()) {
schema._emissive = material->getEmissive(false); schema._emissive = material->getEmissive(false);
@ -574,36 +580,56 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
schemaKey.setLightmapMap(true); schemaKey.setLightmapMap(true);
} }
break; 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: default:
break; break;
} }
bool fallthrough = defaultFallthrough || material->getPropertyFallthrough(flagBit);
if (wasSet) { if (wasSet) {
flagBitsToCheck.erase(it++); flagsToCheck.erase(it++);
} else if (forceDefault || !fallthrough) { } else if (forceDefault || !fallthrough) {
flagBitsToSetDefault.insert(flagBit); flagsToSetDefault.insert(flag);
flagBitsToCheck.erase(it++); flagsToCheck.erase(it++);
} else { } else {
++it; ++it;
} }
} }
if (flagBitsToCheck.empty()) { if (flagsToCheck.empty()) {
break; break;
} }
materials.pop();
material = materials.top().material;
} }
for (auto flagBit : flagBitsToCheck) { for (auto flagBit : flagsToCheck) {
flagBitsToSetDefault.insert(flagBit); flagsToSetDefault.insert(flagBit);
} }
// Handle defaults // Handle defaults
for (auto flagBit : flagBitsToSetDefault) { for (auto flag : flagsToSetDefault) {
switch (flagBit) { switch (flag) {
case graphics::MaterialKey::EMISSIVE_VAL_BIT: case graphics::MaterialKey::EMISSIVE_VAL_BIT:
case graphics::MaterialKey::UNLIT_VAL_BIT: case graphics::MaterialKey::UNLIT_VAL_BIT:
case graphics::MaterialKey::ALBEDO_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::GLOSSY_VAL_BIT:
case graphics::MaterialKey::OPACITY_VAL_BIT: case graphics::MaterialKey::OPACITY_VAL_BIT:
case graphics::MaterialKey::SCATTERING_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() // these are initialized to the correct default values in Schema()
break; break;
case graphics::MaterialKey::ALBEDO_MAP_BIT: 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(); schema._key = (uint32_t)schemaKey._flags.to_ulong();
schemaBuffer.edit<graphics::MultiMaterial::Schema>() = schema; schemaBuffer.edit<graphics::MultiMaterial::Schema>() = schema;
multiMaterial.setNeedsUpdate(false); multiMaterial.setNeedsUpdate(false);