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();
_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<std::mutex> lock(_materialsLock);
result.appendMaterials(_materials);
auto& materials = _materials.find("0");
auto materials = _materials.find("0");
if (materials != _materials.end()) {
vertexColor = materials->second.getSchemaBuffer().get<graphics::MultiMaterial::Schema>()._albedo;
}

View file

@ -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<graphics::MaterialKey::FlagBit, bool> propertyFallthroughs; // not actually exposed to script
std::unordered_map<uint, bool> propertyFallthroughs; // not actually exposed to script
};
/**jsdoc

View file

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

View file

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

View file

@ -14,6 +14,7 @@
#include <QMutex>
#include <bitset>
#include <map>
#include <unordered_map>
#include <queue>
@ -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<MapChannel, TextureMapPointer> TextureMaps;
typedef std::map<MapChannel, TextureMapPointer> 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<MaterialKey::FlagBit, bool> 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<uint, bool> 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<MaterialKey::FlagBit, bool> _propertyFallthroughs;
std::unordered_map<uint, bool> _propertyFallthroughs { NUM_TOTAL_FLAGS };
mutable QMutex _textureMapsMutex { QMutex::Recursive };
std::string _model { "hifi_pbr" };
};
typedef std::shared_ptr<Material> 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; }

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.
* @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.
* @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
* <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));
}
}
} 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()) {

View file

@ -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<graphics::MaterialKey::FlagBit> allFlagBits;
static std::set<uint> 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<graphics::MaterialKey::FlagBit> flagBitsToCheck = allFlagBits;
std::set<graphics::MaterialKey::FlagBit> flagBitsToSetDefault;
std::set<uint> flagsToCheck = allFlags;
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();
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<graphics::MultiMaterial::Schema>() = schema;
multiMaterial.setNeedsUpdate(false);