134 lines
5.6 KiB
C++
134 lines
5.6 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>
|
|
|
|
using namespace gltfio;
|
|
|
|
bool gltfio::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.hasMetallicRoughnessTexture == k2.hasMetallicRoughnessTexture) &&
|
|
(k1.hasNormalTexture == k2.hasNormalTexture) &&
|
|
(k1.hasOcclusionTexture == k2.hasOcclusionTexture) &&
|
|
(k1.hasEmissiveTexture == k2.hasEmissiveTexture) &&
|
|
(k1.alphaMode == k2.alphaMode) &&
|
|
(k1.baseColorUV == k2.baseColorUV) &&
|
|
(k1.metallicRoughnessUV == k2.metallicRoughnessUV) &&
|
|
(k1.emissiveUV == k2.emissiveUV) &&
|
|
(k1.aoUV == k2.aoUV) &&
|
|
(k1.normalUV == k2.normalUV) &&
|
|
(k1.hasClearCoat == k2.hasClearCoat) &&
|
|
(k1.hasClearCoatTexture == k2.hasClearCoatTexture) &&
|
|
(k1.hasClearCoatRoughnessTexture == k2.hasClearCoatRoughnessTexture) &&
|
|
(k1.hasClearCoatNormalTexture == k2.hasClearCoatNormalTexture) &&
|
|
(k1.clearCoatUV == k2.clearCoatUV) &&
|
|
(k1.clearCoatRoughnessUV == k2.clearCoatRoughnessUV) &&
|
|
(k1.clearCoatNormalUV == k2.clearCoatNormalUV);
|
|
}
|
|
|
|
// 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 details::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->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++;
|
|
}
|
|
}
|
|
// NOTE: KHR_materials_clearcoat does not provide separate UVs, we'll assume UV0
|
|
*uvmap = retval;
|
|
}
|
|
|
|
void details::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& 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]];
|
|
replaceAll("${normal}", normalUV);
|
|
replaceAll("${color}", baseColorUV);
|
|
replaceAll("${metallic}", metallicRoughnessUV);
|
|
replaceAll("${ao}", aoUV);
|
|
replaceAll("${emissive}", emissiveUV);
|
|
replaceAll("${clearCoat}", clearCoatUV);
|
|
replaceAll("${clearCoatRoughness}", clearCoatRoughnessUV);
|
|
replaceAll("${clearCoatNormal}", clearCoatNormalUV);
|
|
}
|