First pass at simplifying glTFv2 PBR

Removed 'core' set of GLTF-specific properties
pull/3952/head
RichardTea 2021-06-10 18:13:46 +01:00
parent 199aa5dd66
commit 9f9d77f882
5 changed files with 138 additions and 52 deletions

View File

@ -645,7 +645,7 @@ void glTF2Exporter::ExportMaterials()
m->name = name;
GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE);
GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, aiTextureType_BASE_COLOR);
if (!m->pbrMetallicRoughness.baseColorTexture.texture) {
//if there wasn't a baseColorTexture defined in the source, fallback to any diffuse texture
@ -654,19 +654,19 @@ void glTF2Exporter::ExportMaterials()
GetMatTex(mat, m->pbrMetallicRoughness.metallicRoughnessTexture, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE);
if (GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR) != AI_SUCCESS) {
if (GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_BASE_COLOR) != AI_SUCCESS) {
// if baseColorFactor wasn't defined, then the source is likely not a metallic roughness material.
//a fallback to any diffuse color should be used instead
GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_COLOR_DIFFUSE);
}
if (mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR, m->pbrMetallicRoughness.metallicFactor) != AI_SUCCESS) {
if (mat->Get(AI_MATKEY_METALLIC_FACTOR, m->pbrMetallicRoughness.metallicFactor) != AI_SUCCESS) {
//if metallicFactor wasn't defined, then the source is likely not a PBR file, and the metallicFactor should be 0
m->pbrMetallicRoughness.metallicFactor = 0;
}
// get roughness if source is gltf2 file
if (mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR, m->pbrMetallicRoughness.roughnessFactor) != AI_SUCCESS) {
if (mat->Get(AI_MATKEY_ROUGHNESS_FACTOR, m->pbrMetallicRoughness.roughnessFactor) != AI_SUCCESS) {
// otherwise, try to derive and convert from specular + shininess values
aiColor4D specularColor;
ai_real shininess;
@ -712,36 +712,38 @@ void glTF2Exporter::ExportMaterials()
}
}
bool hasPbrSpecularGlossiness = false;
mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS, hasPbrSpecularGlossiness);
if (hasPbrSpecularGlossiness) {
if (!mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness) {
mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness = true;
}
{
// If has a Specular color, use the KHR_materials_pbrSpecularGlossiness extension
PbrSpecularGlossiness pbrSG;
GetMatColor(mat, pbrSG.diffuseFactor, AI_MATKEY_COLOR_DIFFUSE);
GetMatColor(mat, pbrSG.specularFactor, AI_MATKEY_COLOR_SPECULAR);
if (mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR, pbrSG.glossinessFactor) != AI_SUCCESS) {
float shininess;
if (mat->Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) {
pbrSG.glossinessFactor = shininess / 1000;
if (GetMatColor(mat, pbrSG.specularFactor, AI_MATKEY_COLOR_SPECULAR) == AI_SUCCESS) {
if (!mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness) {
mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness = true;
}
GetMatColor(mat, pbrSG.diffuseFactor, AI_MATKEY_COLOR_DIFFUSE);
// If don't have explicit glossiness then convert from roughness or shininess
if (mat->Get(AI_MATKEY_GLOSSINESS_FACTOR, pbrSG.glossinessFactor) != AI_SUCCESS) {
float shininess;
if (mat->Get(AI_MATKEY_ROUGHNESS_FACTOR, shininess) == AI_SUCCESS) {
pbrSG.glossinessFactor = 1.0f - shininess; // Extension defines this way
} else if (mat->Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) {
pbrSG.glossinessFactor = shininess / 1000;
}
}
// Add any appropriate textures
GetMatTex(mat, pbrSG.diffuseTexture, aiTextureType_DIFFUSE);
GetMatTex(mat, pbrSG.specularGlossinessTexture, aiTextureType_SPECULAR);
m->pbrSpecularGlossiness = Nullable<PbrSpecularGlossiness>(pbrSG);
}
GetMatTex(mat, pbrSG.diffuseTexture, aiTextureType_DIFFUSE);
GetMatTex(mat, pbrSG.specularGlossinessTexture, aiTextureType_SPECULAR);
m->pbrSpecularGlossiness = Nullable<PbrSpecularGlossiness>(pbrSG);
}
bool unlit;
if (mat->Get(AI_MATKEY_GLTF_UNLIT, unlit) == AI_SUCCESS && unlit) {
// glTFv2 is either PBR or Unlit
aiShadingMode shadingMode = aiShadingMode_PBR_BRDF;
mat->Get(AI_MATKEY_SHADING_MODEL, shadingMode);
if (shadingMode == aiShadingMode_Unlit) {
mAsset->extensionsUsed.KHR_materials_unlit = true;
m->unlit = true;
}

View File

@ -238,16 +238,18 @@ static aiMaterial *ImportMaterial(std::vector<int> &embeddedTexIdxs, Asset &r, M
aimat->AddProperty(&str, AI_MATKEY_NAME);
}
// Set Assimp DIFFUSE and BASE COLOR to the pbrMetallicRoughness base color and texture for backwards compatibility
// Technically should not load any pbrMetallicRoughness if extensionsRequired contains KHR_materials_pbrSpecularGlossiness
SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_COLOR_DIFFUSE);
SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR);
SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_BASE_COLOR);
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_DIFFUSE);
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE);
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_BASE_COLOR);
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE);
aimat->AddProperty(&mat.pbrMetallicRoughness.metallicFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR);
aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR);
aimat->AddProperty(&mat.pbrMetallicRoughness.metallicFactor, 1, AI_MATKEY_METALLIC_FACTOR);
aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, AI_MATKEY_ROUGHNESS_FACTOR);
float roughnessAsShininess = 1 - mat.pbrMetallicRoughness.roughnessFactor;
roughnessAsShininess *= roughnessAsShininess * 1000;
@ -268,22 +270,27 @@ static aiMaterial *ImportMaterial(std::vector<int> &embeddedTexIdxs, Asset &r, M
if (mat.pbrSpecularGlossiness.isPresent) {
PbrSpecularGlossiness &pbrSG = mat.pbrSpecularGlossiness.value;
aimat->AddProperty(&mat.pbrSpecularGlossiness.isPresent, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS);
SetMaterialColorProperty(r, pbrSG.diffuseFactor, aimat, AI_MATKEY_COLOR_DIFFUSE);
SetMaterialColorProperty(r, pbrSG.specularFactor, aimat, AI_MATKEY_COLOR_SPECULAR);
float glossinessAsShininess = pbrSG.glossinessFactor * 1000.0f;
aimat->AddProperty(&glossinessAsShininess, 1, AI_MATKEY_SHININESS);
aimat->AddProperty(&pbrSG.glossinessFactor, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR);
aimat->AddProperty(&pbrSG.glossinessFactor, 1, AI_MATKEY_GLOSSINESS_FACTOR);
SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.diffuseTexture, aimat, aiTextureType_DIFFUSE);
SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.specularGlossinessTexture, aimat, aiTextureType_SPECULAR);
}
// glTFv2 is either PBR or Unlit
aiShadingMode shadingMode = aiShadingMode_PBR_BRDF;
if (mat.unlit) {
aimat->AddProperty(&mat.unlit, 1, AI_MATKEY_GLTF_UNLIT);
shadingMode = aiShadingMode_Unlit;
}
aimat->AddProperty(&shadingMode, 1, AI_MATKEY_SHADING_MODEL);
//KHR_materials_sheen
if (mat.materialSheen.isPresent) {
MaterialSheen &sheen = mat.materialSheen.value;

View File

@ -202,11 +202,15 @@ enum aiTextureType {
/** The texture is combined with the result of the diffuse
* lighting equation.
* OR
* PBR Specular/Glossiness
*/
aiTextureType_DIFFUSE = 1,
/** The texture is combined with the result of the specular
* lighting equation.
* OR
* PBR Specular/Glossiness
*/
aiTextureType_SPECULAR = 2,
@ -309,7 +313,9 @@ ASSIMP_API const char *TextureTypeToString(enum aiTextureType in);
// ---------------------------------------------------------------------------
/** @brief Defines all shading models supported by the library
*
*
* #AI_MATKEY_SHADING_MODEL
*
* The list of shading modes has been taken from Blender.
* See Blender documentation for more information. The API does
* not distinguish between "specular" and "diffuse" shaders (thus the
@ -364,13 +370,27 @@ enum aiShadingMode {
aiShadingMode_CookTorrance = 0x8,
/** No shading at all. Constant light influence of 1.0.
* Also known as "Unlit"
*/
aiShadingMode_NoShading = 0x9,
aiShadingMode_Unlit = aiShadingMode_NoShading, // Alias
/** Fresnel shading
*/
aiShadingMode_Fresnel = 0xa,
/** Physically-Based Rendering (PBR) shading using
* Bidirectional scattering/reflectance distribution function (BSDF/BRDF)
* There are multiple methods under this banner, and model files may provide
* data for more than one PBR-BRDF method.
* Applications should use the set of provided properties to determine which
* of their preferred PBDR methods are available
* eg:
* - If AI_MATKEY_METALLIC_FACTOR is set, then a Metallic/Roughness is available
* - If AI_MATKEY_COLOR_SPECULAR is set, then a Specular/Glossiness is available
*/
aiShadingMode_PBR_BRDF = 0xb,
#ifndef SWIG
_aiShadingMode_Force32Bit = INT_MAX
#endif
@ -923,11 +943,29 @@ extern "C" {
// ---------------------------------------------------------------------------
// PBR material support
#define AI_MATKEY_USE_COLOR_MAP "$mat.useColorMap", 0, 0
// Metallic/Roughness Workflow
// ---------------------------
// Base color factor. Will be multiplied by final base color texture values if extant
#define AI_MATKEY_BASE_COLOR "$clr.base", 0, 0
#define AI_MATKEY_USE_METALLIC_MAP "$mat.useMetallicMap", 0, 0
// Metallic factor. 0.0 = Full Dielectric, 1.0 = Full Metal
#define AI_MATKEY_METALLIC_FACTOR "$mat.metallicFactor", 0, 0
#define AI_MATKEY_USE_ROUGHNESS_MAP "$mat.useRoughnessMap", 0, 0
// Roughness factor. 0.0 = Perfectly Smooth, 1.0 = Completely Rough
#define AI_MATKEY_ROUGHNESS_FACTOR "$mat.roughnessFactor", 0, 0
// Specular/Glossiness Workflow
// ---------------------------
// Diffuse/Albedo Color. Note: Pure Metals have a diffuse of {0,0,0}
// AI_MATKEY_COLOR_DIFFUSE
// Specular Color
// AI_MATKEY_COLOR_SPECULAR
// Glossiness factor. 0.0 = Completely Rough, 1.0 = Perfectly Smooth
#define AI_MATKEY_GLOSSINESS_FACTOR "$mat.glossinessFactor", 0, 0
// Emissive
// --------
#define AI_MATKEY_USE_EMISSIVE_MAP "$mat.useEmissiveMap", 0, 0
#define AI_MATKEY_EMISSIVE_INTENSITY "$mat.emissiveIntensity", 0, 0
#define AI_MATKEY_USE_AO_MAP "$mat.useAOMap", 0, 0

View File

@ -50,16 +50,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# pragma GCC system_header
#endif
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR "$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR "$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE aiTextureType_DIFFUSE, 1
//#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR "$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0
//#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0
//#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR "$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0
//#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE aiTextureType_DIFFUSE, 1
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 0
#define AI_MATKEY_GLTF_ALPHAMODE "$mat.gltf.alphaMode", 0, 0
#define AI_MATKEY_GLTF_ALPHACUTOFF "$mat.gltf.alphaCutoff", 0, 0
#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0
#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0, 0
#define AI_MATKEY_GLTF_UNLIT "$mat.gltf.unlit", 0, 0
//#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0
//#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0, 0
//#define AI_MATKEY_GLTF_UNLIT "$mat.gltf.unlit", 0, 0
#define AI_MATKEY_GLTF_MATERIAL_SHEEN "$mat.gltf.materialSheen", 0, 0
#define AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_FACTOR "$mat.gltf.materialSheen.sheenColorFactor", 0, 0
#define AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_FACTOR "$mat.gltf.materialSheen.sheenRoughnessFactor", 0, 0

View File

@ -57,10 +57,9 @@ using namespace Assimp;
class utglTF2ImportExport : public AbstractImportExportBase {
public:
virtual bool importerTest() {
virtual bool importerMatTest(const char *file, bool spec_gloss, std::array<aiTextureMapMode, 2> exp_modes = { aiTextureMapMode_Wrap, aiTextureMapMode_Wrap }) {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf",
aiProcess_ValidateDataStructure);
const aiScene *scene = importer.ReadFile(file, aiProcess_ValidateDataStructure);
EXPECT_NE(scene, nullptr);
if (!scene) {
return false;
@ -72,13 +71,49 @@ public:
}
const aiMaterial *material = scene->mMaterials[0];
// This Material should be a PBR
aiShadingMode shadingMode;
EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_SHADING_MODEL, shadingMode));
EXPECT_EQ(aiShadingMode_PBR_BRDF, shadingMode);
// Should import the texture as diffuse and as base color
aiString path;
aiTextureMapMode modes[2];
std::array<aiTextureMapMode,2> modes;
EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr,
nullptr, nullptr, modes));
nullptr, nullptr, modes.data()));
EXPECT_STREQ(path.C_Str(), "CesiumLogoFlat.png");
EXPECT_EQ(modes[0], aiTextureMapMode_Mirror);
EXPECT_EQ(modes[1], aiTextureMapMode_Clamp);
EXPECT_EQ(exp_modes, modes);
// Also as Base Color
EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(aiTextureType_BASE_COLOR, 0, &path, nullptr, nullptr,
nullptr, nullptr, modes.data()));
EXPECT_STREQ(path.C_Str(), "CesiumLogoFlat.png");
EXPECT_EQ(exp_modes, modes);
// Should have a MetallicFactor (default is 1.0)
ai_real metal_factor = ai_real(0.5);
EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_METALLIC_FACTOR, metal_factor));
EXPECT_EQ(ai_real(0.0), metal_factor);
// And a roughness factor (default is 1.0)
ai_real roughness_factor = ai_real(0.5);
EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_ROUGHNESS_FACTOR, roughness_factor));
EXPECT_EQ(ai_real(1.0), roughness_factor);
aiColor3D spec_color = { 0, 0, 0 };
ai_real glossiness = ai_real(0.5);
if (spec_gloss) {
EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_COLOR_SPECULAR, spec_color));
constexpr ai_real spec_val(0.20000000298023225); // From the file
EXPECT_EQ(spec_val, spec_color.r);
EXPECT_EQ(spec_val, spec_color.g);
EXPECT_EQ(spec_val, spec_color.b);
EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_GLOSSINESS_FACTOR, glossiness));
EXPECT_EQ(ai_real(1.0), glossiness);
} else {
EXPECT_EQ(aiReturn_FAILURE, material->Get(AI_MATKEY_COLOR_SPECULAR, spec_color));
EXPECT_EQ(aiReturn_FAILURE, material->Get(AI_MATKEY_GLOSSINESS_FACTOR, glossiness));
}
return true;
}
@ -105,13 +140,17 @@ public:
};
TEST_F(utglTF2ImportExport, importglTF2FromFileTest) {
EXPECT_TRUE(importerTest());
EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", false, {aiTextureMapMode_Mirror, aiTextureMapMode_Clamp}));
}
TEST_F(utglTF2ImportExport, importBinaryglTF2FromFileTest) {
EXPECT_TRUE(binaryImporterTest());
}
TEST_F(utglTF2ImportExport, importglTF2_KHR_materials_pbrSpecularGlossiness) {
EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured.gltf", true));
}
#ifndef ASSIMP_BUILD_NO_EXPORT
TEST_F(utglTF2ImportExport, importglTF2AndExportToOBJ) {
Assimp::Importer importer;