First cleaned-up, consistent physical material implementation.
There's still work to be done here, mainly: - Convert BUMP to NORMAL - Apply "roughness inversion" to roughness map But it now informs the user of unsupported properties their model uses, and generally works correctly!
This commit is contained in:
parent
a3bee2e42a
commit
d0883136d3
|
@ -10,11 +10,14 @@
|
||||||
#include "RoughnessMetallicMaterials.hpp"
|
#include "RoughnessMetallicMaterials.hpp"
|
||||||
|
|
||||||
std::unique_ptr<FbxRoughMetMaterialInfo> Fbx3dsMaxPhysicalMaterialResolver::resolve() const {
|
std::unique_ptr<FbxRoughMetMaterialInfo> Fbx3dsMaxPhysicalMaterialResolver::resolve() const {
|
||||||
const FbxProperty topProp = fbxMaterial->FindProperty("3dsMax");
|
const FbxProperty topProp = fbxMaterial->FindProperty("3dsMax", false);
|
||||||
if (topProp.GetPropertyDataType() != FbxCompoundDT) {
|
if (topProp.GetPropertyDataType() != FbxCompoundDT) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
const FbxProperty props = fbxMaterial->FindProperty("Parameters");
|
const FbxProperty props = topProp.Find("Parameters", false);
|
||||||
|
if (!props.IsValid()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
FbxString shadingModel = fbxMaterial->ShadingModel.Get();
|
FbxString shadingModel = fbxMaterial->ShadingModel.Get();
|
||||||
if (!shadingModel.IsEmpty() && shadingModel != "unknown") {
|
if (!shadingModel.IsEmpty() && shadingModel != "unknown") {
|
||||||
|
@ -26,29 +29,21 @@ std::unique_ptr<FbxRoughMetMaterialInfo> Fbx3dsMaxPhysicalMaterialResolver::reso
|
||||||
|
|
||||||
auto getTex = [&](std::string propName) -> const FbxFileTexture* {
|
auto getTex = [&](std::string propName) -> const FbxFileTexture* {
|
||||||
const FbxFileTexture* ptr = nullptr;
|
const FbxFileTexture* ptr = nullptr;
|
||||||
|
const FbxProperty texProp = props.Find((propName + "_map").c_str(), false);
|
||||||
const FbxProperty useProp = props.FindHierarchical((propName + "_map_on").c_str());
|
if (texProp.IsValid()) {
|
||||||
if (useProp.IsValid() && useProp.Get<bool>()) {
|
const FbxProperty useProp = props.Find((propName + "_map_on").c_str(), false);
|
||||||
const FbxProperty texProp = useProp.FindHierarchical((propName + "_map").c_str());
|
if (useProp.IsValid() && !useProp.Get<FbxBool>()) {
|
||||||
if (texProp.IsValid()) {
|
// skip this texture if the _on property exists *and* is explicitly false
|
||||||
ptr = texProp.GetSrcObject<FbxFileTexture>();
|
return nullptr;
|
||||||
if (ptr != nullptr && textureLocations.find(ptr) == textureLocations.end()) {
|
}
|
||||||
ptr = nullptr;
|
ptr = texProp.GetSrcObject<FbxFileTexture>();
|
||||||
}
|
if (ptr != nullptr && textureLocations.find(ptr) == textureLocations.end()) {
|
||||||
|
ptr = nullptr;
|
||||||
}
|
}
|
||||||
} else if (verboseOutput && useProp.IsValid()) {
|
|
||||||
fmt::printf(
|
|
||||||
"Note: property '%s' of 3dsMax Physical material '%s' exists, but is flagged as 'off'.\n",
|
|
||||||
propName,
|
|
||||||
fbxMaterial->GetName());
|
|
||||||
}
|
}
|
||||||
return ptr;
|
return ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
int materialMode = getValue(props, "material_mode", 0);
|
|
||||||
fmt::printf("Note: 3dsMax Physical material has material_mode = %d.\n", materialMode);
|
|
||||||
|
|
||||||
// baseWeight && baseColor
|
|
||||||
FbxDouble baseWeight = getValue(props, "base_weight", 1.0);
|
FbxDouble baseWeight = getValue(props, "base_weight", 1.0);
|
||||||
const auto* baseWeightMap = getTex("base_weight");
|
const auto* baseWeightMap = getTex("base_weight");
|
||||||
FbxDouble4 baseCol = getValue(props, "base_color", FbxDouble4(0.5, 0.5, 0.5, 1.0));
|
FbxDouble4 baseCol = getValue(props, "base_color", FbxDouble4(0.5, 0.5, 0.5, 1.0));
|
||||||
|
@ -58,49 +53,97 @@ std::unique_ptr<FbxRoughMetMaterialInfo> Fbx3dsMaxPhysicalMaterialResolver::reso
|
||||||
const auto* emissiveWeightMap = getTex("emission");
|
const auto* emissiveWeightMap = getTex("emission");
|
||||||
FbxDouble4 emissiveColor = getValue(props, "emit_color", FbxDouble4(1, 1, 1, 1));
|
FbxDouble4 emissiveColor = getValue(props, "emit_color", FbxDouble4(1, 1, 1, 1));
|
||||||
const auto* emissiveColorMap = getTex("emit_color");
|
const auto* emissiveColorMap = getTex("emit_color");
|
||||||
// TODO: emit_luminance, emit_kelvin?
|
|
||||||
|
|
||||||
// roughness & metalness: supported
|
|
||||||
double roughness = getValue(props, "roughness", 0.0);
|
double roughness = getValue(props, "roughness", 0.0);
|
||||||
const auto* roughnessMap = getTex("roughness");
|
const auto* roughnessMap = getTex("roughness");
|
||||||
double metalness = getValue(props, "metalness", 0.0);
|
double metalness = getValue(props, "metalness", 0.0);
|
||||||
const auto* metalnessMap = getTex("metalness");
|
const auto* metalnessMap = getTex("metalness");
|
||||||
|
|
||||||
// TODO: does invertRoughness affect roughness_map too?
|
// TODO: we need this to affect roughness map, too.
|
||||||
bool invertRoughness = getValue(props, "inv_roughness", false);
|
bool invertRoughness = getValue(props, "inv_roughness", false);
|
||||||
if (invertRoughness) {
|
if (invertRoughness) {
|
||||||
roughness = 1.0f - roughness;
|
roughness = 1.0f - roughness;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: attempt to bake transparency > 0.0f into the alpha of baseColour?
|
// TODO: turn this into a normal map through simple numerial differentiation
|
||||||
// double transparency = getValue(props, "transparency", 0.0);
|
|
||||||
// const auto* transparencyMap = getTex("transparency");
|
|
||||||
|
|
||||||
// SSS: not supported
|
|
||||||
// double scattering = getValue(props, "scattering", 0.0);
|
|
||||||
// const auto* scatteringMap = getTex("scattering");
|
|
||||||
|
|
||||||
// reflectivity: not supported
|
|
||||||
// double reflectivityWeight = getValue(props, "reflectivity", 1.);
|
|
||||||
// const auto* reflectivityWeightMap = getTex("reflectivity");
|
|
||||||
// FbxDouble4 reflectivityColor = getValue(props, "refl_color", FbxDouble4(1, 1, 1, 1));
|
|
||||||
// const auto* reflectivityColorMap = getTex("refl_color");
|
|
||||||
|
|
||||||
// coatings: not supported
|
|
||||||
// double coating = getValue(props, "coating", 0.0);
|
|
||||||
|
|
||||||
// diffuse roughness: not supported
|
|
||||||
// double diffuseRoughness = getValue(props, "diff_roughness", 0.);
|
|
||||||
|
|
||||||
// explicit brdf curve control: not supported
|
|
||||||
// bool isBrdfMode = getValue(props, "brdf_mode", false);
|
|
||||||
|
|
||||||
// anisotrophy: not supported
|
|
||||||
// double anisotropy = getValue(props, "anisotropy", 1.0);
|
|
||||||
|
|
||||||
// TODO: how the heck do we combine these to generate a normal map?
|
|
||||||
const auto* bumpMap = getTex("bump");
|
const auto* bumpMap = getTex("bump");
|
||||||
// const auto* displacementMap = getTex("displacement");
|
|
||||||
|
std::string unsupported;
|
||||||
|
const auto addUnsupported = [&](const std::string bit) {
|
||||||
|
if (!unsupported.empty()) {
|
||||||
|
unsupported += ", ";
|
||||||
|
}
|
||||||
|
unsupported += bit;
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: bake transparency > 0.0f into the alpha of baseColor?
|
||||||
|
double transparency = getValue(props, "transparency", 0.0);
|
||||||
|
const auto* transparencyMap = getTex("transparency");
|
||||||
|
if (transparency != 0.0 || transparencyMap != nullptr) {
|
||||||
|
addUnsupported("transparency");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: if/when we bake transparency, we'll need this
|
||||||
|
// double transparencyDepth = getValue(props, "trans_depth", 0.0);
|
||||||
|
// if (transparencyDepth != 0.0) {
|
||||||
|
// addUnsupported("transparency depth");
|
||||||
|
// }
|
||||||
|
// double transparencyColor = getValue(props, "trans_color", 0.0);
|
||||||
|
// const auto* transparencyColorMap = getTex("trans_color");
|
||||||
|
// if (transparencyColor != 0.0 || transparencyColorMap != nullptr) {
|
||||||
|
// addUnsupported("transparency color");
|
||||||
|
// }
|
||||||
|
// double thinWalledTransparency = getValue(props, "thin_walled", false);
|
||||||
|
// if (thinWalledTransparency) {
|
||||||
|
// addUnsupported("thin-walled transparency");
|
||||||
|
// }
|
||||||
|
|
||||||
|
const auto* displacementMap = getTex("displacement");
|
||||||
|
if (displacementMap != nullptr) {
|
||||||
|
addUnsupported("displacement");
|
||||||
|
}
|
||||||
|
|
||||||
|
double reflectivityWeight = getValue(props, "reflectivity", 1.0);
|
||||||
|
const auto* reflectivityWeightMap = getTex("reflectivity");
|
||||||
|
FbxDouble4 reflectivityColor = getValue(props, "refl_color", FbxDouble4(1, 1, 1, 1));
|
||||||
|
const auto* reflectivityColorMap = getTex("refl_color");
|
||||||
|
if (reflectivityWeight != 1.0 || reflectivityWeightMap != nullptr ||
|
||||||
|
reflectivityColor != FbxDouble4(1, 1, 1, 1) || reflectivityColorMap != nullptr) {
|
||||||
|
addUnsupported("reflectivity");
|
||||||
|
}
|
||||||
|
|
||||||
|
double scattering = getValue(props, "scattering", 0.0);
|
||||||
|
const auto* scatteringMap = getTex("scattering");
|
||||||
|
if (scattering != 0.0 || scatteringMap != nullptr) {
|
||||||
|
addUnsupported("sub-surface scattering");
|
||||||
|
}
|
||||||
|
|
||||||
|
double coating = getValue(props, "coating", 0.0);
|
||||||
|
if (coating != 0.0) {
|
||||||
|
addUnsupported("coating");
|
||||||
|
}
|
||||||
|
|
||||||
|
double diffuseRoughness = getValue(props, "diff_roughness", 0.0);
|
||||||
|
if (diffuseRoughness != 0.0) {
|
||||||
|
addUnsupported("diffuse roughness");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isBrdfMode = getValue(props, "brdf_mode", false);
|
||||||
|
if (isBrdfMode) {
|
||||||
|
addUnsupported("advanced reflectance custom curve");
|
||||||
|
}
|
||||||
|
|
||||||
|
double anisotropy = getValue(props, "anisotropy", 1.0);
|
||||||
|
if (anisotropy != 1.0) {
|
||||||
|
addUnsupported("anisotropy");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verboseOutput && !unsupported.empty()) {
|
||||||
|
fmt::printf(
|
||||||
|
"Warning: 3dsMax Physical Material %s uses features glTF cannot express:\n %s\n",
|
||||||
|
fbxMaterial->GetName(),
|
||||||
|
unsupported);
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<FbxRoughMetMaterialInfo> res(new FbxRoughMetMaterialInfo(
|
std::unique_ptr<FbxRoughMetMaterialInfo> res(new FbxRoughMetMaterialInfo(
|
||||||
fbxMaterial->GetName(),
|
fbxMaterial->GetName(),
|
||||||
|
@ -115,8 +158,6 @@ std::unique_ptr<FbxRoughMetMaterialInfo> Fbx3dsMaxPhysicalMaterialResolver::reso
|
||||||
res->texMetallic = metalnessMap;
|
res->texMetallic = metalnessMap;
|
||||||
res->texRoughness = roughnessMap;
|
res->texRoughness = roughnessMap;
|
||||||
|
|
||||||
res->texNormal = bumpMap; // TODO LOL NO NONO
|
|
||||||
|
|
||||||
res->emissive = emissiveColor;
|
res->emissive = emissiveColor;
|
||||||
res->emissiveIntensity = emissiveWeight;
|
res->emissiveIntensity = emissiveWeight;
|
||||||
res->texEmissive = emissiveColorMap;
|
res->texEmissive = emissiveColorMap;
|
||||||
|
|
Loading…
Reference in New Issue