Files
filament/libs/gltfio/src/MaterialProvider.cpp
Romain Guy 94ff2ea6b1 Add support for KHR_materials_specular to glTF (#4046)
* Add support for KHR_materials_specular to glTF

* Add support for IOR to ubershaders

* Update release notes

* Remove unused variable, fix comment
2021-05-27 17:33:24 -07:00

174 lines
7.3 KiB
C++

/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gltfio/MaterialProvider.h>
#include <string>
namespace gltfio {
bool operator==(const MaterialKey& k1, const MaterialKey& k2) {
return
(k1.doubleSided == k2.doubleSided) &&
(k1.unlit == k2.unlit) &&
(k1.hasVertexColors == k2.hasVertexColors) &&
(k1.hasBaseColorTexture == k2.hasBaseColorTexture) &&
(k1.hasNormalTexture == k2.hasNormalTexture) &&
(k1.hasOcclusionTexture == k2.hasOcclusionTexture) &&
(k1.hasEmissiveTexture == k2.hasEmissiveTexture) &&
(k1.useSpecularGlossiness == k2.useSpecularGlossiness) &&
(k1.alphaMode == k2.alphaMode) &&
(k1.hasMetallicRoughnessTexture == k2.hasMetallicRoughnessTexture) &&
(k1.metallicRoughnessUV == k2.metallicRoughnessUV) &&
(k1.baseColorUV == k2.baseColorUV) &&
(k1.hasClearCoatTexture == k2.hasClearCoatTexture) &&
(k1.clearCoatUV == k2.clearCoatUV) &&
(k1.hasClearCoatRoughnessTexture == k2.hasClearCoatRoughnessTexture) &&
(k1.clearCoatRoughnessUV == k2.clearCoatRoughnessUV) &&
(k1.hasClearCoatNormalTexture == k2.hasClearCoatNormalTexture) &&
(k1.clearCoatNormalUV == k2.clearCoatNormalUV) &&
(k1.hasClearCoat == k2.hasClearCoat) &&
(k1.hasTransmission == k2.hasTransmission) &&
(k1.hasTextureTransforms == k2.hasTextureTransforms) &&
(k1.emissiveUV == k2.emissiveUV) &&
(k1.aoUV == k2.aoUV) &&
(k1.normalUV == k2.normalUV) &&
(k1.hasTransmissionTexture == k2.hasTransmissionTexture) &&
(k1.transmissionUV == k2.transmissionUV) &&
(k1.hasSheenColorTexture == k2.hasSheenColorTexture) &&
(k1.sheenColorUV == k2.sheenColorUV) &&
(k1.hasSheenRoughnessTexture == k2.hasSheenRoughnessTexture) &&
(k1.sheenRoughnessUV == k2.sheenRoughnessUV) &&
(k1.hasSheen == k2.hasSheen) &&
(k1.hasIOR == k2.hasIOR);
}
// Filament supports up to 2 UV sets. glTF has arbitrary texcoord set indices, but it allows
// implementations to support only 2 simultaneous sets. Here we build a mapping table with 1-based
// indices where 0 means unused. Note that the order in which we drop textures can affect the look
// of certain assets. This "order of degradation" is stipulated by the glTF 2.0 specification.
void constrainMaterial(MaterialKey* key, UvMap* uvmap) {
const int MAX_INDEX = 2;
UvMap retval {};
int index = 1;
if (key->hasBaseColorTexture) {
retval[key->baseColorUV] = (UvSet) index++;
}
if (key->hasMetallicRoughnessTexture && retval[key->metallicRoughnessUV] == UNUSED) {
retval[key->metallicRoughnessUV] = (UvSet) index++;
}
if (key->hasNormalTexture && retval[key->normalUV] == UNUSED) {
if (index > MAX_INDEX) {
key->hasNormalTexture = false;
} else {
retval[key->normalUV] = (UvSet) index++;
}
}
if (key->hasOcclusionTexture && retval[key->aoUV] == UNUSED) {
if (index > MAX_INDEX) {
key->hasOcclusionTexture = false;
} else {
retval[key->aoUV] = (UvSet) index++;
}
}
if (key->hasEmissiveTexture && retval[key->emissiveUV] == UNUSED) {
if (index > MAX_INDEX) {
key->hasEmissiveTexture = false;
} else {
retval[key->emissiveUV] = (UvSet) index++;
}
}
if (key->hasTransmissionTexture && retval[key->transmissionUV] == UNUSED) {
if (index > MAX_INDEX) {
key->hasTransmissionTexture = false;
} else {
retval[key->transmissionUV] = (UvSet) index++;
}
}
if (key->hasClearCoatTexture && retval[key->clearCoatUV] == UNUSED) {
if (index > MAX_INDEX) {
key->hasClearCoatTexture = false;
} else {
retval[key->clearCoatUV] = (UvSet) index++;
}
}
if (key->hasClearCoatRoughnessTexture && retval[key->clearCoatRoughnessUV] == UNUSED) {
if (index > MAX_INDEX) {
key->hasClearCoatRoughnessTexture = false;
} else {
retval[key->clearCoatRoughnessUV] = (UvSet) index++;
}
}
if (key->hasClearCoatNormalTexture && retval[key->clearCoatNormalUV] == UNUSED) {
if (index > MAX_INDEX) {
key->hasClearCoatNormalTexture = false;
} else {
retval[key->clearCoatNormalUV] = (UvSet) index++;
}
}
if (key->hasSheenColorTexture && retval[key->sheenColorUV] == UNUSED) {
if (index > MAX_INDEX) {
key->hasSheenColorTexture = false;
} else {
retval[key->sheenColorUV] = (UvSet) index++;
}
}
if (key->hasSheenRoughnessTexture && retval[key->sheenRoughnessUV] == UNUSED) {
if (index > MAX_INDEX) {
key->hasSheenRoughnessTexture = false;
} else {
retval[key->sheenRoughnessUV] = (UvSet) index++;
}
}
// NOTE: KHR_materials_clearcoat does not provide separate UVs, we'll assume UV0
*uvmap = retval;
}
void processShaderString(std::string* shader, const UvMap& uvmap, const MaterialKey& config) {
auto replaceAll = [shader](const std::string& from, const std::string& to) {
size_t pos = shader->find(from);
for (; pos != std::string::npos; pos = shader->find(from, pos)) {
shader->replace(pos, from.length(), to);
}
};
static const std::string uvstrings[] = { "vec2(0)", "getUV0()", "getUV1()" };
const auto& normalUV = uvstrings[uvmap[config.normalUV]];
const auto& baseColorUV = uvstrings[uvmap[config.baseColorUV]];
const auto& metallicRoughnessUV = uvstrings[uvmap[config.metallicRoughnessUV]];
const auto& emissiveUV = uvstrings[uvmap[config.emissiveUV]];
const auto& transmissionUV = uvstrings[uvmap[config.transmissionUV]];
const auto& aoUV = uvstrings[uvmap[config.aoUV]];
const auto& clearCoatUV = uvstrings[uvmap[config.clearCoatUV]];
const auto& clearCoatRoughnessUV = uvstrings[uvmap[config.clearCoatRoughnessUV]];
const auto& clearCoatNormalUV = uvstrings[uvmap[config.clearCoatNormalUV]];
const auto& sheenColorUV = uvstrings[uvmap[config.sheenColorUV]];
const auto& sheenRoughnessUV = uvstrings[uvmap[config.sheenRoughnessUV]];
replaceAll("${normal}", normalUV);
replaceAll("${color}", baseColorUV);
replaceAll("${metallic}", metallicRoughnessUV);
replaceAll("${ao}", aoUV);
replaceAll("${emissive}", emissiveUV);
replaceAll("${transmission}", transmissionUV);
replaceAll("${clearCoat}", clearCoatUV);
replaceAll("${clearCoatRoughness}", clearCoatRoughnessUV);
replaceAll("${clearCoatNormal}", clearCoatNormalUV);
replaceAll("${sheenColor}", sheenColorUV);
replaceAll("${sheenRoughness}", sheenRoughnessUV);
}
} // namespace gltfio