浏览代码

Standardise Clearcoat, Sheen and Transmission

Also cleanup glTFv2 defaults, don't import/export if disabled
RichardTea 4 年之前
父节点
当前提交
4a66ec25d0

+ 136 - 100
code/AssetLib/glTF2/glTF2Exporter.cpp

@@ -436,11 +436,11 @@ inline void SetSamplerWrap(SamplerWrap& wrap, aiTextureMapMode map)
     };
     };
 }
 }
 
 
-void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref<Texture> texture, aiTextureType tt, unsigned int slot)
+void glTF2Exporter::GetTexSampler(const aiMaterial& mat, Ref<Texture> texture, aiTextureType tt, unsigned int slot)
 {
 {
     aiString aId;
     aiString aId;
     std::string id;
     std::string id;
-    if (aiGetMaterialString(mat, AI_MATKEY_GLTF_MAPPINGID(tt, slot), &aId) == AI_SUCCESS) {
+    if (aiGetMaterialString(&mat, AI_MATKEY_GLTF_MAPPINGID(tt, slot), &aId) == AI_SUCCESS) {
         id = aId.C_Str();
         id = aId.C_Str();
     }
     }
 
 
@@ -455,49 +455,49 @@ void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref<Texture> texture, a
         SamplerMagFilter filterMag;
         SamplerMagFilter filterMag;
         SamplerMinFilter filterMin;
         SamplerMinFilter filterMin;
 
 
-        if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_U(tt, slot), (int*)&mapU) == AI_SUCCESS) {
+        if (aiGetMaterialInteger(&mat, AI_MATKEY_MAPPINGMODE_U(tt, slot), (int*)&mapU) == AI_SUCCESS) {
             SetSamplerWrap(texture->sampler->wrapS, mapU);
             SetSamplerWrap(texture->sampler->wrapS, mapU);
         }
         }
 
 
-        if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_V(tt, slot), (int*)&mapV) == AI_SUCCESS) {
+        if (aiGetMaterialInteger(&mat, AI_MATKEY_MAPPINGMODE_V(tt, slot), (int*)&mapV) == AI_SUCCESS) {
             SetSamplerWrap(texture->sampler->wrapT, mapV);
             SetSamplerWrap(texture->sampler->wrapT, mapV);
         }
         }
 
 
-        if (aiGetMaterialInteger(mat, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(tt, slot), (int*)&filterMag) == AI_SUCCESS) {
+        if (aiGetMaterialInteger(&mat, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(tt, slot), (int*)&filterMag) == AI_SUCCESS) {
             texture->sampler->magFilter = filterMag;
             texture->sampler->magFilter = filterMag;
         }
         }
 
 
-        if (aiGetMaterialInteger(mat, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(tt, slot), (int*)&filterMin) == AI_SUCCESS) {
+        if (aiGetMaterialInteger(&mat, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(tt, slot), (int*)&filterMin) == AI_SUCCESS) {
             texture->sampler->minFilter = filterMin;
             texture->sampler->minFilter = filterMin;
         }
         }
 
 
         aiString name;
         aiString name;
-        if (aiGetMaterialString(mat, AI_MATKEY_GLTF_MAPPINGNAME(tt, slot), &name) == AI_SUCCESS) {
+        if (aiGetMaterialString(&mat, AI_MATKEY_GLTF_MAPPINGNAME(tt, slot), &name) == AI_SUCCESS) {
             texture->sampler->name = name.C_Str();
             texture->sampler->name = name.C_Str();
         }
         }
     }
     }
 }
 }
 
 
-void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int slot)
+void glTF2Exporter::GetMatTexProp(const aiMaterial& mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int slot)
 {
 {
     std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName;
     std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName;
 
 
-    mat->Get(textureKey.c_str(), tt, slot, prop);
+    mat.Get(textureKey.c_str(), tt, slot, prop);
 }
 }
 
 
-void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int slot)
+void glTF2Exporter::GetMatTexProp(const aiMaterial& mat, float& prop, const char* propName, aiTextureType tt, unsigned int slot)
 {
 {
     std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName;
     std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName;
 
 
-    mat->Get(textureKey.c_str(), tt, slot, prop);
+    mat.Get(textureKey.c_str(), tt, slot, prop);
 }
 }
 
 
-void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTextureType tt, unsigned int slot = 0)
+void glTF2Exporter::GetMatTex(const aiMaterial& mat, Ref<Texture>& texture, aiTextureType tt, unsigned int slot = 0)
 {
 {
-    if (mat->GetTextureCount(tt) > 0) {
+    if (mat.GetTextureCount(tt) > 0) {
         aiString tex;
         aiString tex;
 
 
-        if (mat->Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) {
+        if (mat.Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) {
             std::string path = tex.C_Str();
             std::string path = tex.C_Str();
 
 
             if (path.size() > 0) {
             if (path.size() > 0) {
@@ -568,7 +568,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTe
     }
     }
 }
 }
 
 
-void glTF2Exporter::GetMatTex(const aiMaterial* mat, TextureInfo& prop, aiTextureType tt, unsigned int slot = 0)
+void glTF2Exporter::GetMatTex(const aiMaterial& mat, TextureInfo& prop, aiTextureType tt, unsigned int slot = 0)
 {
 {
     Ref<Texture>& texture = prop.texture;
     Ref<Texture>& texture = prop.texture;
 
 
@@ -579,7 +579,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, TextureInfo& prop, aiTextur
     }
     }
 }
 }
 
 
-void glTF2Exporter::GetMatTex(const aiMaterial* mat, NormalTextureInfo& prop, aiTextureType tt, unsigned int slot = 0)
+void glTF2Exporter::GetMatTex(const aiMaterial& mat, NormalTextureInfo& prop, aiTextureType tt, unsigned int slot = 0)
 {
 {
     Ref<Texture>& texture = prop.texture;
     Ref<Texture>& texture = prop.texture;
 
 
@@ -591,7 +591,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, NormalTextureInfo& prop, ai
     }
     }
 }
 }
 
 
-void glTF2Exporter::GetMatTex(const aiMaterial* mat, OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot = 0)
+void glTF2Exporter::GetMatTex(const aiMaterial& mat, OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot = 0)
 {
 {
     Ref<Texture>& texture = prop.texture;
     Ref<Texture>& texture = prop.texture;
 
 
@@ -603,10 +603,10 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, OcclusionTextureInfo& prop,
     }
     }
 }
 }
 
 
-aiReturn glTF2Exporter::GetMatColor(const aiMaterial* mat, vec4& prop, const char* propName, int type, int idx)
+aiReturn glTF2Exporter::GetMatColor(const aiMaterial& mat, vec4& prop, const char* propName, int type, int idx) const
 {
 {
     aiColor4D col;
     aiColor4D col;
-    aiReturn result = mat->Get(propName, type, idx, col);
+    aiReturn result = mat.Get(propName, type, idx, col);
 
 
     if (result == AI_SUCCESS) {
     if (result == AI_SUCCESS) {
         prop[0] = col.r; prop[1] = col.g; prop[2] = col.b; prop[3] = col.a;
         prop[0] = col.r; prop[1] = col.g; prop[2] = col.b; prop[3] = col.a;
@@ -615,30 +615,109 @@ aiReturn glTF2Exporter::GetMatColor(const aiMaterial* mat, vec4& prop, const cha
     return result;
     return result;
 }
 }
 
 
-aiReturn glTF2Exporter::GetMatColor(const aiMaterial* mat, vec3& prop, const char* propName, int type, int idx)
+aiReturn glTF2Exporter::GetMatColor(const aiMaterial& mat, vec3& prop, const char* propName, int type, int idx) const
 {
 {
     aiColor3D col;
     aiColor3D col;
-    aiReturn result = mat->Get(propName, type, idx, col);
+    aiReturn result = mat.Get(propName, type, idx, col);
 
 
     if (result == AI_SUCCESS) {
     if (result == AI_SUCCESS) {
-        prop[0] = col.r; prop[1] = col.g; prop[2] = col.b;
+        prop[0] = col.r;
+        prop[1] = col.g;
+        prop[2] = col.b;
     }
     }
 
 
     return result;
     return result;
 }
 }
 
 
+bool glTF2Exporter::GetMatSpecGloss(const aiMaterial &mat, glTF2::PbrSpecularGlossiness &pbrSG) {
+    bool result = false;
+    // If has Glossiness, a Specular Color or Specular Texture, use the KHR_materials_pbrSpecularGlossiness extension
+    // NOTE: This extension is being considered for deprecation (Dec 2020), may be replaced by KHR_material_specular
+
+    if (mat.Get(AI_MATKEY_GLOSSINESS_FACTOR, pbrSG.glossinessFactor) == AI_SUCCESS) {
+        result = true;
+    } else {
+        // Don't have explicit glossiness, convert from pbr roughness or legacy shininess
+        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;
+        }
+    }
+
+    if (GetMatColor(mat, pbrSG.specularFactor, AI_MATKEY_COLOR_SPECULAR) == AI_SUCCESS) {
+        result = true;
+    }
+    // Add any appropriate textures
+    GetMatTex(mat, pbrSG.specularGlossinessTexture, aiTextureType_SPECULAR);
+
+    result == result || pbrSG.specularGlossinessTexture.texture;
+
+    if (result) {
+        // Likely to always have diffuse
+        GetMatTex(mat, pbrSG.diffuseTexture, aiTextureType_DIFFUSE);
+        GetMatColor(mat, pbrSG.diffuseFactor, AI_MATKEY_COLOR_DIFFUSE);
+    }
+
+    return result;
+}
+
+bool glTF2Exporter::GetMatSheen(const aiMaterial &mat, glTF2::MaterialSheen &sheen) {
+    // Return true if got any valid Sheen properties or textures
+    if (GetMatColor(mat, sheen.sheenColorFactor, AI_MATKEY_SHEEN_COLOR_FACTOR) != aiReturn_SUCCESS)
+        return false;
+
+    // Default Sheen color factor {0,0,0} disables Sheen, so do not export
+    if (sheen.sheenColorFactor == defaultSheenFactor)
+        return false;
+
+    mat.Get(AI_MATKEY_SHEEN_ROUGHNESS_FACTOR, sheen.sheenRoughnessFactor);
+
+    GetMatTex(mat, sheen.sheenColorTexture, AI_MATKEY_SHEEN_COLOR_TEXTURE);
+    GetMatTex(mat, sheen.sheenRoughnessTexture, AI_MATKEY_SHEEN_ROUGHNESS_TEXTURE);
+
+    return true;
+}
+
+bool glTF2Exporter::GetMatClearcoat(const aiMaterial &mat, glTF2::MaterialClearcoat &clearcoat) {
+    if (mat.Get(AI_MATKEY_CLEARCOAT_FACTOR, clearcoat.clearcoatFactor) != aiReturn_SUCCESS) {
+        return false;
+    }
+
+    // Clearcoat factor of zero disables Clearcoat, so do not export
+    if (clearcoat.clearcoatFactor == 0.0f)
+        return false;
+
+    mat.Get(AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR, clearcoat.clearcoatRoughnessFactor);
+
+    GetMatTex(mat, clearcoat.clearcoatTexture, AI_MATKEY_CLEARCOAT_TEXTURE);
+    GetMatTex(mat, clearcoat.clearcoatRoughnessTexture, AI_MATKEY_CLEARCOAT_ROUGHNESS_TEXTURE);
+    GetMatTex(mat, clearcoat.clearcoatNormalTexture, AI_MATKEY_CLEARCOAT_NORMAL_TEXTURE);
+
+    return true;
+}
+
+bool glTF2Exporter::GetMatTransmission(const aiMaterial &mat, glTF2::MaterialTransmission &transmission) {
+    bool result = mat.Get(AI_MATKEY_TRANSMISSION_FACTOR, transmission.transmissionFactor) == aiReturn_SUCCESS;
+    GetMatTex(mat, transmission.transmissionTexture, AI_MATKEY_TRANSMISSION_TEXTURE);
+    return result || transmission.transmissionTexture.texture;
+}
+
 void glTF2Exporter::ExportMaterials()
 void glTF2Exporter::ExportMaterials()
 {
 {
     aiString aiName;
     aiString aiName;
     for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) {
     for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) {
-        const aiMaterial* mat = mScene->mMaterials[i];
+        ai_assert(mScene->mMaterials[i] != nullptr);
+
+        const aiMaterial & mat = *(mScene->mMaterials[i]);
 
 
         std::string id = "material_" + ai_to_string(i);
         std::string id = "material_" + ai_to_string(i);
 
 
         Ref<Material> m = mAsset->materials.Create(id);
         Ref<Material> m = mAsset->materials.Create(id);
 
 
         std::string name;
         std::string name;
-        if (mat->Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) {
+        if (mat.Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) {
             name = aiName.C_Str();
             name = aiName.C_Str();
         }
         }
         name = mAsset->FindUniqueID(name, "material");
         name = mAsset->FindUniqueID(name, "material");
@@ -660,20 +739,20 @@ void glTF2Exporter::ExportMaterials()
             GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_COLOR_DIFFUSE);
             GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_COLOR_DIFFUSE);
         }
         }
 
 
-        if (mat->Get(AI_MATKEY_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
             //if metallicFactor wasn't defined, then the source is likely not a PBR file, and the metallicFactor should be 0
             m->pbrMetallicRoughness.metallicFactor = 0;
             m->pbrMetallicRoughness.metallicFactor = 0;
         }
         }
 
 
         // get roughness if source is gltf2 file
         // get roughness if source is gltf2 file
-        if (mat->Get(AI_MATKEY_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
             // otherwise, try to derive and convert from specular + shininess values
             aiColor4D specularColor;
             aiColor4D specularColor;
             ai_real shininess;
             ai_real shininess;
 
 
             if (
             if (
-                mat->Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS &&
-                mat->Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS
+                mat.Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS &&
+                mat.Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS
             ) {
             ) {
                 // convert specular color to luminance
                 // convert specular color to luminance
                 float specularIntensity = specularColor[0] * 0.2125f + specularColor[1] * 0.7154f + specularColor[2] * 0.0721f;
                 float specularIntensity = specularColor[0] * 0.2125f + specularColor[1] * 0.7154f + specularColor[2] * 0.0721f;
@@ -694,17 +773,17 @@ void glTF2Exporter::ExportMaterials()
         GetMatTex(mat, m->emissiveTexture, aiTextureType_EMISSIVE);
         GetMatTex(mat, m->emissiveTexture, aiTextureType_EMISSIVE);
         GetMatColor(mat, m->emissiveFactor, AI_MATKEY_COLOR_EMISSIVE);
         GetMatColor(mat, m->emissiveFactor, AI_MATKEY_COLOR_EMISSIVE);
 
 
-        mat->Get(AI_MATKEY_TWOSIDED, m->doubleSided);
-        mat->Get(AI_MATKEY_GLTF_ALPHACUTOFF, m->alphaCutoff);
+        mat.Get(AI_MATKEY_TWOSIDED, m->doubleSided);
+        mat.Get(AI_MATKEY_GLTF_ALPHACUTOFF, m->alphaCutoff);
 
 
         aiString alphaMode;
         aiString alphaMode;
 
 
-        if (mat->Get(AI_MATKEY_GLTF_ALPHAMODE, alphaMode) == AI_SUCCESS) {
+        if (mat.Get(AI_MATKEY_GLTF_ALPHAMODE, alphaMode) == AI_SUCCESS) {
             m->alphaMode = alphaMode.C_Str();
             m->alphaMode = alphaMode.C_Str();
         } else {
         } else {
             float opacity;
             float opacity;
 
 
-            if (mat->Get(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS) {
+            if (mat.Get(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS) {
                 if (opacity < 1) {
                 if (opacity < 1) {
                     m->alphaMode = "BLEND";
                     m->alphaMode = "BLEND";
                     m->pbrMetallicRoughness.baseColorFactor[3] *= opacity;
                     m->pbrMetallicRoughness.baseColorFactor[3] *= opacity;
@@ -713,86 +792,43 @@ void glTF2Exporter::ExportMaterials()
         }
         }
 
 
         {
         {
-            // If has a Specular color, use the KHR_materials_pbrSpecularGlossiness extension
+            // KHR_materials_pbrSpecularGlossiness extension
+            // NOTE: This extension is being considered for deprecation (Dec 2020)
             PbrSpecularGlossiness pbrSG;
             PbrSpecularGlossiness pbrSG;
-            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);
-
+            if (GetMatSpecGloss(mat, pbrSG)) {
+                mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness = true;
                 m->pbrSpecularGlossiness = Nullable<PbrSpecularGlossiness>(pbrSG);
                 m->pbrSpecularGlossiness = Nullable<PbrSpecularGlossiness>(pbrSG);
             }
             }
         }
         }
 
 
         // glTFv2 is either PBR or Unlit
         // glTFv2 is either PBR or Unlit
         aiShadingMode shadingMode = aiShadingMode_PBR_BRDF;
         aiShadingMode shadingMode = aiShadingMode_PBR_BRDF;
-        mat->Get(AI_MATKEY_SHADING_MODEL, shadingMode);
+        mat.Get(AI_MATKEY_SHADING_MODEL, shadingMode);
         if (shadingMode == aiShadingMode_Unlit) {
         if (shadingMode == aiShadingMode_Unlit) {
             mAsset->extensionsUsed.KHR_materials_unlit = true;
             mAsset->extensionsUsed.KHR_materials_unlit = true;
             m->unlit = true;
             m->unlit = true;
-        }
-
-        bool hasMaterialSheen = false;
-        mat->Get(AI_MATKEY_GLTF_MATERIAL_SHEEN, hasMaterialSheen);
-
-        if (hasMaterialSheen) {
-            mAsset->extensionsUsed.KHR_materials_sheen = true;
-
-            MaterialSheen sheen;
-
-            GetMatColor(mat, sheen.sheenColorFactor, AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_FACTOR);
-            mat->Get(AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_FACTOR, sheen.sheenRoughnessFactor);
-            GetMatTex(mat, sheen.sheenColorTexture, AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_TEXTURE);
-            GetMatTex(mat, sheen.sheenRoughnessTexture, AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_TEXTURE);
-
-            m->materialSheen = Nullable<MaterialSheen>(sheen);
-        }
-
-        bool hasMaterialClearcoat = false;
-        mat->Get(AI_MATKEY_GLTF_MATERIAL_CLEARCOAT, hasMaterialClearcoat);
-
-        if (hasMaterialClearcoat) {
-            mAsset->extensionsUsed.KHR_materials_clearcoat= true;
-
-            MaterialClearcoat clearcoat;
-
-            mat->Get(AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_FACTOR, clearcoat.clearcoatFactor);
-            mat->Get(AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_FACTOR, clearcoat.clearcoatRoughnessFactor);
-            GetMatTex(mat, clearcoat.clearcoatTexture, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_TEXTURE);
-            GetMatTex(mat, clearcoat.clearcoatRoughnessTexture, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_TEXTURE);
-            GetMatTex(mat, clearcoat.clearcoatNormalTexture, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_NORMAL_TEXTURE);
-
-            m->materialClearcoat = Nullable<MaterialClearcoat>(clearcoat);
-        }
-
-        bool hasMaterialTransmission = false;
-        mat->Get(AI_MATKEY_GLTF_MATERIAL_TRANSMISSION, hasMaterialTransmission);
-
-        if (hasMaterialTransmission) {
-            mAsset->extensionsUsed.KHR_materials_transmission = true;
-
-            MaterialTransmission transmission;
+        } else {
+            // These extensions are not compatible with KHR_materials_unlit or KHR_materials_pbrSpecularGlossiness
+            if (!m->pbrSpecularGlossiness.isPresent) {
+                // Sheen
+                MaterialSheen sheen;
+                if (GetMatSheen(mat, sheen)) {
+                    mAsset->extensionsUsed.KHR_materials_sheen = true;
+                    m->materialSheen = Nullable<MaterialSheen>(sheen);
+                }
 
 
-            mat->Get(AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_FACTOR, transmission.transmissionFactor);
-            GetMatTex(mat, transmission.transmissionTexture, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_TEXTURE);
+                MaterialClearcoat clearcoat;
+                if (GetMatClearcoat(mat, clearcoat)) {
+                    mAsset->extensionsUsed.KHR_materials_clearcoat = true;
+                    m->materialClearcoat = Nullable<MaterialClearcoat>(clearcoat);
+                }
 
 
-            m->materialTransmission = Nullable<MaterialTransmission>(transmission);
+                MaterialTransmission transmission;
+                if (GetMatTransmission(mat, transmission)) {
+                    mAsset->extensionsUsed.KHR_materials_transmission = true;
+                    m->materialTransmission = Nullable<MaterialTransmission>(transmission);
+                }
+            }
         }
         }
     }
     }
 }
 }

+ 17 - 9
code/AssetLib/glTF2/glTF2Exporter.h

@@ -72,6 +72,10 @@ namespace glTF2
     struct OcclusionTextureInfo;
     struct OcclusionTextureInfo;
     struct Node;
     struct Node;
     struct Texture;
     struct Texture;
+    struct PbrSpecularGlossiness;
+    struct MaterialSheen;
+    struct MaterialClearcoat;
+    struct MaterialTransmission;
 
 
     // Vec/matrix types, as raw float arrays
     // Vec/matrix types, as raw float arrays
 	typedef float (vec2)[2];
 	typedef float (vec2)[2];
@@ -97,15 +101,19 @@ namespace Assimp
 
 
     protected:
     protected:
         void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
         void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
-        void GetTexSampler(const aiMaterial* mat, glTF2::Ref<glTF2::Texture> texture, aiTextureType tt, unsigned int slot);
-        void GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int idx);
-        void GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int idx);
-        void GetMatTex(const aiMaterial* mat, glTF2::Ref<glTF2::Texture>& texture, aiTextureType tt, unsigned int slot);
-        void GetMatTex(const aiMaterial* mat, glTF2::TextureInfo& prop, aiTextureType tt, unsigned int slot);
-        void GetMatTex(const aiMaterial* mat, glTF2::NormalTextureInfo& prop, aiTextureType tt, unsigned int slot);
-        void GetMatTex(const aiMaterial* mat, glTF2::OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot);
-        aiReturn GetMatColor(const aiMaterial* mat, glTF2::vec4& prop, const char* propName, int type, int idx);
-        aiReturn GetMatColor(const aiMaterial* mat, glTF2::vec3& prop, const char* propName, int type, int idx);
+        void GetTexSampler(const aiMaterial& mat, glTF2::Ref<glTF2::Texture> texture, aiTextureType tt, unsigned int slot);
+        void GetMatTexProp(const aiMaterial& mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int idx);
+        void GetMatTexProp(const aiMaterial& mat, float& prop, const char* propName, aiTextureType tt, unsigned int idx);
+        void GetMatTex(const aiMaterial& mat, glTF2::Ref<glTF2::Texture>& texture, aiTextureType tt, unsigned int slot);
+        void GetMatTex(const aiMaterial& mat, glTF2::TextureInfo& prop, aiTextureType tt, unsigned int slot);
+        void GetMatTex(const aiMaterial& mat, glTF2::NormalTextureInfo& prop, aiTextureType tt, unsigned int slot);
+        void GetMatTex(const aiMaterial& mat, glTF2::OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot);
+        aiReturn GetMatColor(const aiMaterial& mat, glTF2::vec4& prop, const char* propName, int type, int idx) const;
+        aiReturn GetMatColor(const aiMaterial& mat, glTF2::vec3& prop, const char* propName, int type, int idx) const;
+        bool GetMatSpecGloss(const aiMaterial& mat, glTF2::PbrSpecularGlossiness& pbrSG);
+        bool GetMatSheen(const aiMaterial& mat, glTF2::MaterialSheen& sheen);
+        bool GetMatClearcoat(const aiMaterial& mat, glTF2::MaterialClearcoat& clearcoat);
+        bool GetMatTransmission(const aiMaterial& mat, glTF2::MaterialTransmission& transmission);
         void ExportMetadata();
         void ExportMetadata();
         void ExportMaterials();
         void ExportMaterials();
         void ExportMeshes();
         void ExportMeshes();

+ 20 - 19
code/AssetLib/glTF2/glTF2Importer.cpp

@@ -291,36 +291,37 @@ static aiMaterial *ImportMaterial(std::vector<int> &embeddedTexIdxs, Asset &r, M
         aimat->AddProperty(&shadingMode, 1, AI_MATKEY_SHADING_MODEL);
         aimat->AddProperty(&shadingMode, 1, AI_MATKEY_SHADING_MODEL);
 
 
 
 
-        //KHR_materials_sheen
+        // KHR_materials_sheen
         if (mat.materialSheen.isPresent) {
         if (mat.materialSheen.isPresent) {
             MaterialSheen &sheen = mat.materialSheen.value;
             MaterialSheen &sheen = mat.materialSheen.value;
-
-            aimat->AddProperty(&mat.materialSheen.isPresent, 1, AI_MATKEY_GLTF_MATERIAL_SHEEN);
-            SetMaterialColorProperty(r, sheen.sheenColorFactor, aimat, AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_FACTOR);
-            aimat->AddProperty(&sheen.sheenRoughnessFactor, 1, AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_FACTOR);
-            SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenColorTexture, aimat, AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_TEXTURE);
-            SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenRoughnessTexture, aimat, AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_TEXTURE);
+            // Default value {0,0,0} disables Sheen
+            if (sheen.sheenColorFactor != defaultSheenFactor) {
+                SetMaterialColorProperty(r, sheen.sheenColorFactor, aimat, AI_MATKEY_SHEEN_COLOR_FACTOR);
+                aimat->AddProperty(&sheen.sheenRoughnessFactor, 1, AI_MATKEY_SHEEN_ROUGHNESS_FACTOR);
+                SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenColorTexture, aimat, AI_MATKEY_SHEEN_COLOR_TEXTURE);
+                SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenRoughnessTexture, aimat, AI_MATKEY_SHEEN_ROUGHNESS_TEXTURE);
+            }
         }
         }
 
 
-        //KHR_materials_clearcoat
+        // KHR_materials_clearcoat
         if (mat.materialClearcoat.isPresent) {
         if (mat.materialClearcoat.isPresent) {
             MaterialClearcoat &clearcoat = mat.materialClearcoat.value;
             MaterialClearcoat &clearcoat = mat.materialClearcoat.value;
-
-            aimat->AddProperty(&mat.materialClearcoat.isPresent, 1, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT);
-            aimat->AddProperty(&clearcoat.clearcoatFactor, 1, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_FACTOR);
-            aimat->AddProperty(&clearcoat.clearcoatRoughnessFactor, 1, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_FACTOR);
-            SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatTexture, aimat, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_TEXTURE);
-            SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatRoughnessTexture, aimat, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_TEXTURE);
-            SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatNormalTexture, aimat, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_NORMAL_TEXTURE);
+            // Default value 0.0 disables clearcoat
+            if (clearcoat.clearcoatFactor != 0.0f) {
+                aimat->AddProperty(&clearcoat.clearcoatFactor, 1, AI_MATKEY_CLEARCOAT_FACTOR);
+                aimat->AddProperty(&clearcoat.clearcoatRoughnessFactor, 1, AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR);
+                SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatTexture, aimat, AI_MATKEY_CLEARCOAT_TEXTURE);
+                SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatRoughnessTexture, aimat, AI_MATKEY_CLEARCOAT_ROUGHNESS_TEXTURE);
+                SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatNormalTexture, aimat, AI_MATKEY_CLEARCOAT_NORMAL_TEXTURE);
+            }
         }
         }
 
 
-        //KHR_materials_transmission
+        // KHR_materials_transmission
         if (mat.materialTransmission.isPresent) {
         if (mat.materialTransmission.isPresent) {
             MaterialTransmission &transmission = mat.materialTransmission.value;
             MaterialTransmission &transmission = mat.materialTransmission.value;
 
 
-            aimat->AddProperty(&mat.materialTransmission.isPresent, 1, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION);
-            aimat->AddProperty(&transmission.transmissionFactor, 1, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_FACTOR);
-            SetMaterialTextureProperty(embeddedTexIdxs, r, transmission.transmissionTexture, aimat, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_TEXTURE);
+            aimat->AddProperty(&transmission.transmissionFactor, 1, AI_MATKEY_TRANSMISSION_FACTOR);
+            SetMaterialTextureProperty(embeddedTexIdxs, r, transmission.transmissionTexture, aimat, AI_MATKEY_TRANSMISSION_TEXTURE);
         }
         }
 
 
         return aimat;
         return aimat;

+ 8 - 4
code/Common/material.cpp

@@ -47,10 +47,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/material.h>
 #include <assimp/material.h>
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
-const char* TextureTypeToString(aiTextureType in)
-{
-    switch (in)
-    {
+const char *TextureTypeToString(aiTextureType in) {
+    switch (in) {
     case aiTextureType_NONE:
     case aiTextureType_NONE:
         return "n/a";
         return "n/a";
     case aiTextureType_DIFFUSE:
     case aiTextureType_DIFFUSE:
@@ -87,6 +85,12 @@ const char* TextureTypeToString(aiTextureType in)
         return "DiffuseRoughness";
         return "DiffuseRoughness";
     case aiTextureType_AMBIENT_OCCLUSION:
     case aiTextureType_AMBIENT_OCCLUSION:
         return "AmbientOcclusion";
         return "AmbientOcclusion";
+    case aiTextureType_SHEEN:
+        return "Sheen";
+    case aiTextureType_CLEARCOAT:
+        return "Clearcoat";
+    case aiTextureType_TRANSMISSION:
+        return "Transmission";
     case aiTextureType_UNKNOWN:
     case aiTextureType_UNKNOWN:
         return "Unknown";
         return "Unknown";
     default:
     default:

+ 71 - 6
include/assimp/material.h

@@ -144,7 +144,9 @@ enum aiTextureMapMode {
 enum aiTextureMapping {
 enum aiTextureMapping {
     /** The mapping coordinates are taken from an UV channel.
     /** The mapping coordinates are taken from an UV channel.
      *
      *
-     *  The #AI_MATKEY_UVWSRC key specifies from which UV channel
+     *  #AI_MATKEY_UVWSRC property
+     * 
+     *  Specifies from which UV channel
      *  the texture coordinates are to be taken from (remember,
      *  the texture coordinates are to be taken from (remember,
      *  meshes can have more than one UV channel).
      *  meshes can have more than one UV channel).
     */
     */
@@ -292,6 +294,32 @@ enum aiTextureType {
     aiTextureType_DIFFUSE_ROUGHNESS = 16,
     aiTextureType_DIFFUSE_ROUGHNESS = 16,
     aiTextureType_AMBIENT_OCCLUSION = 17,
     aiTextureType_AMBIENT_OCCLUSION = 17,
 
 
+    /** PBR Material Modifiers
+    * Some modern renderers have further PBR modifiers that may be overlaid
+    * on top of the 'base' PBR materials for additional realism.
+    * These use multiple texture maps, so only the base type is directly defined
+    */
+
+    /** Sheen
+    * Generally used to simulate textiles that are covered in a layer of microfibers
+    * eg velvet
+    * https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_sheen
+    */
+    aiTextureType_SHEEN = 19,
+
+    /** Clearcoat
+    * Simulates a layer of 'polish' or 'laquer' layered on top of a PBR substrate
+    * https://autodesk.github.io/standard-surface/#closures/coating
+    * https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_clearcoat
+    */
+    aiTextureType_CLEARCOAT = 20,
+
+    /** Transmission
+    * Simulates transmission through the surface
+    * May include further information such as wall thickness
+    */
+    aiTextureType_TRANSMISSION = 21,
+
     /** Unknown texture
     /** Unknown texture
      *
      *
      *  A texture reference that does not match any of the definitions
      *  A texture reference that does not match any of the definitions
@@ -314,7 +342,7 @@ ASSIMP_API const char *TextureTypeToString(enum aiTextureType in);
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 /** @brief Defines all shading models supported by the library
 /** @brief Defines all shading models supported by the library
  * 
  * 
- *  #AI_MATKEY_SHADING_MODEL
+ *  Property: #AI_MATKEY_SHADING_MODEL
  * 
  * 
  *  The list of shading modes has been taken from Blender.
  *  The list of shading modes has been taken from Blender.
  *  See Blender documentation for more information. The API does
  *  See Blender documentation for more information. The API does
@@ -324,6 +352,7 @@ ASSIMP_API const char *TextureTypeToString(enum aiTextureType in);
  *  Again, this value is just a hint. Assimp tries to select the shader whose
  *  Again, this value is just a hint. Assimp tries to select the shader whose
  *  most common implementation matches the original rendering results of the
  *  most common implementation matches the original rendering results of the
  *  3D modeler which wrote a particular model as closely as possible.
  *  3D modeler which wrote a particular model as closely as possible.
+ *
  */
  */
 enum aiShadingMode {
 enum aiShadingMode {
     /** Flat shading. Shading is done on per-face base,
     /** Flat shading. Shading is done on per-face base,
@@ -384,10 +413,11 @@ enum aiShadingMode {
     * There are multiple methods under this banner, and model files may provide
     * There are multiple methods under this banner, and model files may provide
     * data for more than one PBR-BRDF method.
     * data for more than one PBR-BRDF method.
     * Applications should use the set of provided properties to determine which
     * Applications should use the set of provided properties to determine which
-    * of their preferred PBDR methods are available
+    * of their preferred PBR rendering methods are likely to be available
     * eg:
     * eg:
     * - If AI_MATKEY_METALLIC_FACTOR is set, then a Metallic/Roughness is available
     * - 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
+    * - If AI_MATKEY_GLOSSINESS_FACTOR is set, then a Specular/Glossiness is available
+    * Note that some PBR methods allow layering of techniques
     */
     */
     aiShadingMode_PBR_BRDF = 0xb,
     aiShadingMode_PBR_BRDF = 0xb,
 
 
@@ -942,28 +972,63 @@ extern "C" {
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 // PBR material support
 // PBR material support
+// --------------------
+// Properties defining PBR rendering techniques
 #define AI_MATKEY_USE_COLOR_MAP "$mat.useColorMap", 0, 0
 #define AI_MATKEY_USE_COLOR_MAP "$mat.useColorMap", 0, 0
 
 
 // Metallic/Roughness Workflow
 // Metallic/Roughness Workflow
 // ---------------------------
 // ---------------------------
-// Base color factor. Will be multiplied by final base color texture values if extant
+// Base RGBA color factor. Will be multiplied by final base color texture values if extant
+// Note: Importers may choose to copy this into AI_MATKEY_COLOR_DIFFUSE for compatibility
+// with renderers and formats that do not support Metallic/Roughness PBR
 #define AI_MATKEY_BASE_COLOR "$clr.base", 0, 0
 #define AI_MATKEY_BASE_COLOR "$clr.base", 0, 0
+#define AI_MATKEY_BASE_COLOR_TEXTURE aiTextureType_BASE_COLOR, 0
 #define AI_MATKEY_USE_METALLIC_MAP "$mat.useMetallicMap", 0, 0
 #define AI_MATKEY_USE_METALLIC_MAP "$mat.useMetallicMap", 0, 0
 // Metallic factor. 0.0 = Full Dielectric, 1.0 = Full Metal
 // Metallic factor. 0.0 = Full Dielectric, 1.0 = Full Metal
 #define AI_MATKEY_METALLIC_FACTOR "$mat.metallicFactor", 0, 0
 #define AI_MATKEY_METALLIC_FACTOR "$mat.metallicFactor", 0, 0
+#define AI_MATKEY_METALLIC_TEXTURE aiTextureType_METALNESS, 0
 #define AI_MATKEY_USE_ROUGHNESS_MAP "$mat.useRoughnessMap", 0, 0
 #define AI_MATKEY_USE_ROUGHNESS_MAP "$mat.useRoughnessMap", 0, 0
 // Roughness factor. 0.0 = Perfectly Smooth, 1.0 = Completely Rough
 // Roughness factor. 0.0 = Perfectly Smooth, 1.0 = Completely Rough
 #define AI_MATKEY_ROUGHNESS_FACTOR "$mat.roughnessFactor", 0, 0
 #define AI_MATKEY_ROUGHNESS_FACTOR "$mat.roughnessFactor", 0, 0
+#define AI_MATKEY_ROUGHNESS_TEXTURE aiTextureType_DIFFUSE_ROUGHNESS, 0
 
 
 // Specular/Glossiness Workflow
 // Specular/Glossiness Workflow
 // ---------------------------
 // ---------------------------
 // Diffuse/Albedo Color. Note: Pure Metals have a diffuse of {0,0,0}
 // Diffuse/Albedo Color. Note: Pure Metals have a diffuse of {0,0,0}
 // AI_MATKEY_COLOR_DIFFUSE
 // AI_MATKEY_COLOR_DIFFUSE
-// Specular Color
+// Specular Color.
+// Note: Metallic/Roughness may also have a Specular Color
 // AI_MATKEY_COLOR_SPECULAR
 // AI_MATKEY_COLOR_SPECULAR
+#define AI_MATKEY_SPECULAR_FACTOR "$mat.specularFactor", 0, 0
 // Glossiness factor. 0.0 = Completely Rough, 1.0 = Perfectly Smooth
 // Glossiness factor. 0.0 = Completely Rough, 1.0 = Perfectly Smooth
 #define AI_MATKEY_GLOSSINESS_FACTOR "$mat.glossinessFactor", 0, 0
 #define AI_MATKEY_GLOSSINESS_FACTOR "$mat.glossinessFactor", 0, 0
 
 
+// Sheen
+// -----
+// Sheen base RGB color. Default {0,0,0}
+#define AI_MATKEY_SHEEN_COLOR_FACTOR "$clr.sheen.factor", 0, 0
+// Sheen Roughness Factor.
+#define AI_MATKEY_SHEEN_ROUGHNESS_FACTOR "$mat.sheen.roughnessFactor", 0, 0
+#define AI_MATKEY_SHEEN_COLOR_TEXTURE aiTextureType_SHEEN, 0
+#define AI_MATKEY_SHEEN_ROUGHNESS_TEXTURE aiTextureType_SHEEN, 1
+
+// Clearcoat
+// ---------
+#define AI_MATKEY_CLEARCOAT_FACTOR "$clr.clearcoat.factor", 0, 0
+#define AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR "$mat.clearcoat.roughnessFactor", 0, 0
+#define AI_MATKEY_CLEARCOAT_TEXTURE aiTextureType_CLEARCOAT, 0
+#define AI_MATKEY_CLEARCOAT_ROUGHNESS_TEXTURE aiTextureType_CLEARCOAT, 1
+#define AI_MATKEY_CLEARCOAT_NORMAL_TEXTURE aiTextureType_CLEARCOAT, 2
+
+// Transmission
+// ------------
+// https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_transmission
+// Base percentage of light transmitted through the surface. 0.0 = Opaque, 1.0 = Fully transparent
+#define AI_MATKEY_TRANSMISSION_FACTOR "$mat.transmission.factor", 0, 0
+// Texture defining percentage of light transmitted through the surface.
+// Multiplied by AI_MATKEY_TRANSMISSION_FACTOR
+#define AI_MATKEY_TRANSMISSION_TEXTURE aiTextureType_TRANSMISSION, 0
+
 // Emissive
 // Emissive
 // --------
 // --------
 #define AI_MATKEY_USE_EMISSIVE_MAP "$mat.useEmissiveMap", 0, 0
 #define AI_MATKEY_USE_EMISSIVE_MAP "$mat.useEmissiveMap", 0, 0

+ 14 - 14
include/assimp/pbrmaterial.h

@@ -60,20 +60,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 //#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 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_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0, 0
 //#define AI_MATKEY_GLTF_UNLIT "$mat.gltf.unlit", 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
-#define AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_TEXTURE aiTextureType_UNKNOWN, 1
-#define AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 2
-#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT "$mat.gltf.materialClearcoat", 0, 0
-#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_FACTOR "$mat.gltf.materialClearcoat.clearcoatFactor", 0, 0
-#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_FACTOR "$mat.gltf.materialClearcoat.clearcoatRoughnessFactor", 0, 0
-#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_TEXTURE aiTextureType_UNKNOWN, 3
-#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 4
-#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_NORMAL_TEXTURE aiTextureType_NORMALS, 1
-#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION "$mat.gltf.materialTransmission", 0, 0
-#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_FACTOR "$mat.gltf.materialTransmission.transmissionFactor", 0, 0
-#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_TEXTURE aiTextureType_UNKNOWN, 5
+//#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
+//#define AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_TEXTURE aiTextureType_UNKNOWN, 1
+//#define AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 2
+//#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT "$mat.gltf.materialClearcoat", 0, 0
+//#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_FACTOR "$mat.gltf.materialClearcoat.clearcoatFactor", 0, 0
+//#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_FACTOR "$mat.gltf.materialClearcoat.clearcoatRoughnessFactor", 0, 0
+//#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_TEXTURE aiTextureType_UNKNOWN, 3
+//#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 4
+//#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_NORMAL_TEXTURE aiTextureType_NORMALS, 1
+//#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION "$mat.gltf.materialTransmission", 0, 0
+//#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_FACTOR "$mat.gltf.materialTransmission.transmissionFactor", 0, 0
+//#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_TEXTURE aiTextureType_UNKNOWN, 5
 
 
 #define _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE "$tex.file.texCoord"
 #define _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE "$tex.file.texCoord"
 #define _AI_MATKEY_GLTF_MAPPINGNAME_BASE "$tex.mappingname"
 #define _AI_MATKEY_GLTF_MAPPINGNAME_BASE "$tex.mappingname"

+ 15 - 0
test/unit/utglTF2ImportExport.cpp

@@ -152,6 +152,20 @@ TEST_F(utglTF2ImportExport, importglTF2_KHR_materials_pbrSpecularGlossiness) {
 }
 }
 
 
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_EXPORT
+
+TEST_F(utglTF2ImportExport, importglTF2AndExport_KHR_materials_pbrSpecularGlossiness) {
+    Assimp::Importer importer;
+    Assimp::Exporter exporter;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured.gltf",
+            aiProcess_ValidateDataStructure);
+    EXPECT_NE(nullptr, scene);
+    // Export
+    EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "glb2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured_out.glb"));
+
+    // And re-import
+    EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured_out.glb", true));
+}
+
 TEST_F(utglTF2ImportExport, importglTF2AndExportToOBJ) {
 TEST_F(utglTF2ImportExport, importglTF2AndExportToOBJ) {
     Assimp::Importer importer;
     Assimp::Importer importer;
     Assimp::Exporter exporter;
     Assimp::Exporter exporter;
@@ -169,6 +183,7 @@ TEST_F(utglTF2ImportExport, importglTF2EmbeddedAndExportToOBJ) {
     EXPECT_NE(nullptr, scene);
     EXPECT_NE(nullptr, scene);
     EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "obj", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-Embedded/BoxTextured_out.obj"));
     EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "obj", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-Embedded/BoxTextured_out.obj"));
 }
 }
+
 #endif // ASSIMP_BUILD_NO_EXPORT
 #endif // ASSIMP_BUILD_NO_EXPORT
 
 
 TEST_F(utglTF2ImportExport, importglTF2PrimitiveModePointsWithoutIndices) {
 TEST_F(utglTF2ImportExport, importglTF2PrimitiveModePointsWithoutIndices) {