This commit is contained in:
Chris Subagio 2020-06-03 00:46:32 +00:00 committed by GitHub
commit 47b95eabe0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 87 additions and 14 deletions

5
.gitignore vendored
View File

@ -5,3 +5,8 @@ npm/fbx2gltf/node_modules/
npm/tests/node_modules/ npm/tests/node_modules/
npm/tests/test/*.js npm/tests/test/*.js
npm/tests/test/*.js.map npm/tests/test/*.js.map
build
sdk
.vscode
Pipfile
Pipfile.lock

View File

@ -308,6 +308,19 @@ that route should be digested propertly by FBX2glTF.
(A happy note: Allegorithmic's Substance Painter also exports Stingray PBS, (A happy note: Allegorithmic's Substance Painter also exports Stingray PBS,
when hooked up to Maya.) when hooked up to Maya.)
When processing PBR materials, this converter will always pack Occlusion,
Roughness, and Metallness into a single combined ORM texture, with each parameter
being in the R, G and, B channels respectively. If you specify a texture in any
of the Stingray material slots, a full ORM will be generated; if you leave all 3
blank, then no ORM texture will be assigned.
* Should you specify different textures for each, then they will
be merged into their respective channels. Any missing textures will be
defaulted to: Occlusion 1, Roughness 0, and Metallness 0. Note, all textures
must have the same dimensions.
* Should you specify the same texture in all 3 slots, then the texture will
be assumed to already be a packed ORM, and will be used as-is.
## Draco Compression ## Draco Compression
The tool will optionally apply [Draco](https://github.com/google/draco) The tool will optionally apply [Draco](https://github.com/google/draco)

View File

@ -261,41 +261,96 @@ ModelData* Raw2Gltf(
*/ */
RawMetRoughMatProps* props = (RawMetRoughMatProps*)material.info.get(); RawMetRoughMatProps* props = (RawMetRoughMatProps*)material.info.get();
// determine if we need to generate a combined map // determine if we need to generate a combined map, or if we only have 1 map to pass through
bool hasMetallicMap = material.textures[RAW_TEXTURE_USAGE_METALLIC] >= 0; bool hasMetallicMap = material.textures[RAW_TEXTURE_USAGE_METALLIC] >= 0;
bool hasRoughnessMap = material.textures[RAW_TEXTURE_USAGE_ROUGHNESS] >= 0; bool hasRoughnessMap = material.textures[RAW_TEXTURE_USAGE_ROUGHNESS] >= 0;
bool hasOcclusionMap = material.textures[RAW_TEXTURE_USAGE_OCCLUSION] >= 0; bool hasOcclusionMap = material.textures[RAW_TEXTURE_USAGE_OCCLUSION] >= 0;
bool atLeastTwoMaps = hasMetallicMap ? (hasRoughnessMap || hasOcclusionMap)
: (hasRoughnessMap && hasMetallicMap); auto texturesAreSame = [&](RawTextureUsage a, RawTextureUsage b) -> bool {
if (!atLeastTwoMaps) { // note: at this point the usages will be different, so we can't just compare indexes
// this handles the case of 0 or 1 maps supplied return StringUtils::CompareNoCase(
raw.GetTexture(material.textures[a]).fileLocation,
raw.GetTexture(material.textures[b]).fileLocation ) == 0;
};
bool isPassThroughTexture = hasOcclusionMap && hasRoughnessMap && hasMetallicMap;
if (isPassThroughTexture) {
isPassThroughTexture =
texturesAreSame(RAW_TEXTURE_USAGE_METALLIC, RAW_TEXTURE_USAGE_ROUGHNESS) &&
texturesAreSame(RAW_TEXTURE_USAGE_METALLIC, RAW_TEXTURE_USAGE_OCCLUSION);
}
auto textureName = [&](RawTextureUsage usage){
int index = material.textures[usage];
if (index >= 0) {
return raw.GetTexture(index).name.c_str();
} else {
return "<empty>";
}
};
if (!(hasMetallicMap || hasRoughnessMap || hasOcclusionMap)) {
// no data, assume it's a material that just relies on the uniform properties
aoMetRoughTex = nullptr;
if (verboseOutput) {
fmt::printf("Material %s: no ORM textures detected\n", material.name.c_str() );
}
}
else if (isPassThroughTexture) {
// this handles the case where the same map is assigned to all the channels
aoMetRoughTex = hasMetallicMap aoMetRoughTex = hasMetallicMap
? simpleTex(RAW_TEXTURE_USAGE_METALLIC) ? simpleTex(RAW_TEXTURE_USAGE_METALLIC)
: (hasRoughnessMap : (hasRoughnessMap
? simpleTex(RAW_TEXTURE_USAGE_ROUGHNESS) ? simpleTex(RAW_TEXTURE_USAGE_ROUGHNESS)
: (hasOcclusionMap ? simpleTex(RAW_TEXTURE_USAGE_OCCLUSION) : nullptr)); : (hasOcclusionMap
? simpleTex(RAW_TEXTURE_USAGE_OCCLUSION)
: nullptr));
if (verboseOutput) {
if (aoMetRoughTex) {
fmt::printf("Material %s: detected single ORM texture: %s\n", material.name.c_str(), aoMetRoughTex->name.c_str());
} else {
fmt::printf("Material %s: no ORM textures detected\n", material.name.c_str() );
}
}
} else { } else {
// otherwise merge occlusion into the red channel, metallic into blue channel, and /* otherwise we always have to create a new texture that merges
// roughness into the green, of a new combinatory texture * occlusion into the red channel
* roughness into the green
* metallic into blue channel
* with defaults for any unspecified channels
*/
aoMetRoughTex = textureBuilder.combine( aoMetRoughTex = textureBuilder.combine(
{ {
material.textures[RAW_TEXTURE_USAGE_OCCLUSION], material.textures[RAW_TEXTURE_USAGE_OCCLUSION],
material.textures[RAW_TEXTURE_USAGE_METALLIC],
material.textures[RAW_TEXTURE_USAGE_ROUGHNESS], material.textures[RAW_TEXTURE_USAGE_ROUGHNESS],
material.textures[RAW_TEXTURE_USAGE_METALLIC],
}, },
"ao_met_rough", "ao_met_rough",
[&](const std::vector<const TextureBuilder::pixel*> pixels) [&](const std::vector<const TextureBuilder::pixel*> pixels)
-> TextureBuilder::pixel { -> TextureBuilder::pixel {
const float occlusion = (*pixels[0])[0]; /**
const float metallic = (*pixels[1])[0] * (hasMetallicMap ? 1 : props->metallic); * note: we're picking the channels from the sources aligned with where they're going
const float roughness = * just in case they were authored that way. This makes an existing ORM texture
(*pixels[2])[0] * (hasRoughnessMap ? 1 : props->roughness); * "pass through", and has no effect on a grey single type texture.
*/
const float occlusion = hasOcclusionMap ? (*pixels[0])[0] : 1;
const float roughness = (*pixels[1])[1] * (hasRoughnessMap ? 1 : props->roughness);
const float metallic = (*pixels[2])[2] * (hasMetallicMap ? 1 : props->metallic);
return {{occlusion, return {{occlusion,
props->invertRoughnessMap ? 1.0f - roughness : roughness, props->invertRoughnessMap ? 1.0f - roughness : roughness,
metallic, metallic,
1}}; 1}};
}, },
false); false);
if ( aoMetRoughTex && verboseOutput ) {
fmt::printf("Material %s: detected multiple ORM textures, combined: [%s, %s, %s] into [%s]\n",
material.name.c_str(),
textureName(RAW_TEXTURE_USAGE_OCCLUSION),
textureName(RAW_TEXTURE_USAGE_ROUGHNESS),
textureName(RAW_TEXTURE_USAGE_METALLIC),
aoMetRoughTex->name.c_str()
);
}
} }
baseColorTex = simpleTex(RAW_TEXTURE_USAGE_ALBEDO); baseColorTex = simpleTex(RAW_TEXTURE_USAGE_ALBEDO);
diffuseFactor = props->diffuseFactor; diffuseFactor = props->diffuseFactor;