Merge 2b94b87a96
into 739ee5db94
This commit is contained in:
commit
47b95eabe0
|
@ -5,3 +5,8 @@ npm/fbx2gltf/node_modules/
|
|||
npm/tests/node_modules/
|
||||
npm/tests/test/*.js
|
||||
npm/tests/test/*.js.map
|
||||
build
|
||||
sdk
|
||||
.vscode
|
||||
Pipfile
|
||||
Pipfile.lock
|
||||
|
|
13
README.md
13
README.md
|
@ -308,6 +308,19 @@ that route should be digested propertly by FBX2glTF.
|
|||
(A happy note: Allegorithmic's Substance Painter also exports Stingray PBS,
|
||||
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
|
||||
|
||||
The tool will optionally apply [Draco](https://github.com/google/draco)
|
||||
|
|
|
@ -261,41 +261,96 @@ ModelData* Raw2Gltf(
|
|||
*/
|
||||
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 hasRoughnessMap = material.textures[RAW_TEXTURE_USAGE_ROUGHNESS] >= 0;
|
||||
bool hasOcclusionMap = material.textures[RAW_TEXTURE_USAGE_OCCLUSION] >= 0;
|
||||
bool atLeastTwoMaps = hasMetallicMap ? (hasRoughnessMap || hasOcclusionMap)
|
||||
: (hasRoughnessMap && hasMetallicMap);
|
||||
if (!atLeastTwoMaps) {
|
||||
// this handles the case of 0 or 1 maps supplied
|
||||
|
||||
auto texturesAreSame = [&](RawTextureUsage a, RawTextureUsage b) -> bool {
|
||||
// note: at this point the usages will be different, so we can't just compare indexes
|
||||
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
|
||||
? simpleTex(RAW_TEXTURE_USAGE_METALLIC)
|
||||
: (hasRoughnessMap
|
||||
? 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 {
|
||||
// otherwise merge occlusion into the red channel, metallic into blue channel, and
|
||||
// roughness into the green, of a new combinatory texture
|
||||
fmt::printf("Material %s: no ORM textures detected\n", material.name.c_str() );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* otherwise we always have to create a new texture that merges
|
||||
* occlusion into the red channel
|
||||
* roughness into the green
|
||||
* metallic into blue channel
|
||||
* with defaults for any unspecified channels
|
||||
*/
|
||||
aoMetRoughTex = textureBuilder.combine(
|
||||
{
|
||||
material.textures[RAW_TEXTURE_USAGE_OCCLUSION],
|
||||
material.textures[RAW_TEXTURE_USAGE_METALLIC],
|
||||
material.textures[RAW_TEXTURE_USAGE_ROUGHNESS],
|
||||
material.textures[RAW_TEXTURE_USAGE_METALLIC],
|
||||
},
|
||||
"ao_met_rough",
|
||||
[&](const std::vector<const TextureBuilder::pixel*> pixels)
|
||||
-> TextureBuilder::pixel {
|
||||
const float occlusion = (*pixels[0])[0];
|
||||
const float metallic = (*pixels[1])[0] * (hasMetallicMap ? 1 : props->metallic);
|
||||
const float roughness =
|
||||
(*pixels[2])[0] * (hasRoughnessMap ? 1 : props->roughness);
|
||||
/**
|
||||
* note: we're picking the channels from the sources aligned with where they're going
|
||||
* just in case they were authored that way. This makes an existing ORM texture
|
||||
* "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,
|
||||
props->invertRoughnessMap ? 1.0f - roughness : roughness,
|
||||
metallic,
|
||||
1}};
|
||||
},
|
||||
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);
|
||||
diffuseFactor = props->diffuseFactor;
|
||||
|
|
Loading…
Reference in New Issue