Browse Source

Merge pull request #4112 from diharaw/master

[GLTF2] Add read and write support for KHR_materials_volume and KHR_materials_ior extensions.
Kim Kulling 3 years ago
parent
commit
f81d7c0b3e

+ 28 - 0
code/AssetLib/glTF2/glTF2Asset.h

@@ -49,6 +49,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *   KHR_materials_sheen full
  *   KHR_materials_clearcoat full
  *   KHR_materials_transmission full
+ *   KHR_materials_volume full
+ *   KHR_materials_ior full
  */
 #ifndef GLTF2ASSET_H_INC
 #define GLTF2ASSET_H_INC
@@ -713,6 +715,7 @@ const vec3 defaultEmissiveFactor = { 0, 0, 0 };
 const vec4 defaultDiffuseFactor = { 1, 1, 1, 1 };
 const vec3 defaultSpecularFactor = { 1, 1, 1 };
 const vec3 defaultSheenFactor = { 0, 0, 0 };
+const vec3 defaultAttenuationColor = { 1, 1, 1 };
 
 struct TextureInfo {
     Ref<Texture> texture;
@@ -777,6 +780,23 @@ struct MaterialTransmission {
     float transmissionFactor = 0.f;
 };
 
+struct MaterialVolume {
+    float thicknessFactor = 0.f;
+    TextureInfo thicknessTexture;
+    float attenuationDistance = 0.f;
+    vec3 attenuationColor;
+
+    MaterialVolume() { SetDefaults(); }
+    void SetDefaults();
+};
+
+struct MaterialIOR {
+    float ior = 0.f;
+
+    MaterialIOR() { SetDefaults(); }
+    void SetDefaults();
+};
+
 //! The material appearance of a primitive.
 struct Material : public Object {
     //PBR metallic roughness properties
@@ -803,6 +823,12 @@ struct Material : public Object {
     //extension: KHR_materials_transmission
     Nullable<MaterialTransmission> materialTransmission;
 
+    //extension: KHR_materials_volume
+    Nullable<MaterialVolume> materialVolume;
+
+    //extension: KHR_materials_ior
+    Nullable<MaterialIOR> materialIOR;
+    
     //extension: KHR_materials_unlit
     bool unlit;
 
@@ -1091,6 +1117,8 @@ public:
         bool KHR_materials_sheen;
         bool KHR_materials_clearcoat;
         bool KHR_materials_transmission;
+        bool KHR_materials_volume;
+        bool KHR_materials_ior;
         bool KHR_draco_mesh_compression;
         bool FB_ngon_encoding;
         bool KHR_texture_basisu;

+ 37 - 0
code/AssetLib/glTF2/glTF2Asset.inl

@@ -1215,6 +1215,29 @@ inline void Material::Read(Value &material, Asset &r) {
             }
         }
 
+        if (r.extensionsUsed.KHR_materials_volume) {
+            if (Value *curMaterialVolume = FindObject(*extensions, "KHR_materials_volume")) {
+                MaterialVolume volume;
+
+                ReadMember(*curMaterialVolume, "thicknessFactor", volume.thicknessFactor);
+                ReadTextureProperty(r, *curMaterialVolume, "thicknessTexture", volume.thicknessTexture);
+                ReadMember(*curMaterialVolume, "attenuationDistance", volume.attenuationDistance);
+                ReadMember(*curMaterialVolume, "attenuationColor", volume.attenuationColor);
+
+                this->materialVolume = Nullable<MaterialVolume>(volume);
+            }
+        }
+
+        if (r.extensionsUsed.KHR_materials_ior) {
+            if (Value *curMaterialIOR = FindObject(*extensions, "KHR_materials_ior")) {
+                MaterialIOR ior;
+
+                ReadMember(*curMaterialIOR, "ior", ior.ior);
+          
+                this->materialIOR = Nullable<MaterialIOR>(ior);
+            }
+        }
+
         unlit = nullptr != FindObject(*extensions, "KHR_materials_unlit");
     }
 }
@@ -1260,6 +1283,18 @@ inline void MaterialSheen::SetDefaults() {
     sheenRoughnessFactor = 0.f;
 }
 
+inline void MaterialVolume::SetDefaults() {
+    //KHR_materials_volume properties
+    thicknessFactor = 0.f;
+    attenuationDistance = INFINITY;
+    SetVector(attenuationColor, defaultAttenuationColor);
+}
+
+inline void MaterialIOR::SetDefaults() {
+    //KHR_materials_ior properties
+    ior = 1.5f;
+}
+
 namespace {
 
 template <int N>
@@ -1931,6 +1966,8 @@ inline void Asset::ReadExtensionsUsed(Document &doc) {
     CHECK_EXT(KHR_materials_sheen);
     CHECK_EXT(KHR_materials_clearcoat);
     CHECK_EXT(KHR_materials_transmission);
+    CHECK_EXT(KHR_materials_volume);
+    CHECK_EXT(KHR_materials_ior);
     CHECK_EXT(KHR_draco_mesh_compression);
     CHECK_EXT(KHR_texture_basisu);
 

+ 2 - 0
code/AssetLib/glTF2/glTF2AssetWriter.h

@@ -49,6 +49,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *   KHR_materials_sheen: full
  *   KHR_materials_clearcoat: full
  *   KHR_materials_transmission: full
+ *   KHR_materials_volume: full
+ *   KHR_materials_ior: full
  */
 #ifndef GLTF2ASSETWRITER_H_INC
 #define GLTF2ASSETWRITER_H_INC

+ 44 - 0
code/AssetLib/glTF2/glTF2AssetWriter.inl

@@ -474,6 +474,42 @@ namespace glTF2 {
             }
         }
 
+        if (m.materialVolume.isPresent) {
+            Value materialVolume(rapidjson::Type::kObjectType);
+
+            MaterialVolume &volume = m.materialVolume.value;
+
+            if (volume.thicknessFactor != 0.f) {
+                WriteFloat(materialVolume, volume.thicknessFactor, "thicknessFactor", w.mAl);
+            }
+
+            WriteTex(materialVolume, volume.thicknessTexture, "thicknessTexture", w.mAl);
+
+            if (volume.attenuationDistance != INFINITY) {
+                WriteFloat(materialVolume, volume.attenuationDistance, "attenuationDistance", w.mAl);
+            }
+
+            WriteVec(materialVolume, volume.attenuationColor, "attenuationColor", defaultAttenuationColor, w.mAl);
+
+            if (!materialVolume.ObjectEmpty()) {
+                exts.AddMember("KHR_materials_volume", materialVolume, w.mAl);
+            }
+        }
+
+        if (m.materialIOR.isPresent) {
+            Value materialIOR(rapidjson::Type::kObjectType);
+
+            MaterialIOR &ior = m.materialIOR.value;
+
+            if (ior.ior != 1.5f) {
+                WriteFloat(materialIOR, ior.ior, "ior", w.mAl);
+            }
+
+            if (!materialIOR.ObjectEmpty()) {
+                exts.AddMember("KHR_materials_ior", materialIOR, w.mAl);
+            }
+        }
+
         if (!exts.ObjectEmpty()) {
             obj.AddMember("extensions", exts, w.mAl);
         }
@@ -890,6 +926,14 @@ namespace glTF2 {
                 exts.PushBack(StringRef("KHR_materials_transmission"), mAl);
             }
 
+            if (this->mAsset.extensionsUsed.KHR_materials_volume) {
+                exts.PushBack(StringRef("KHR_materials_volume"), mAl);
+            }
+
+            if (this->mAsset.extensionsUsed.KHR_materials_ior) {
+                exts.PushBack(StringRef("KHR_materials_ior"), mAl);
+            }
+
             if (this->mAsset.extensionsUsed.FB_ngon_encoding) {
                 exts.PushBack(StringRef("FB_ngon_encoding"), mAl);
             }

+ 28 - 0
code/AssetLib/glTF2/glTF2Exporter.cpp

@@ -704,6 +704,22 @@ bool glTF2Exporter::GetMatTransmission(const aiMaterial &mat, glTF2::MaterialTra
     return result || transmission.transmissionTexture.texture;
 }
 
+bool glTF2Exporter::GetMatVolume(const aiMaterial &mat, glTF2::MaterialVolume &volume) {
+    bool result = mat.Get(AI_MATKEY_VOLUME_THICKNESS_FACTOR, volume.thicknessFactor) != aiReturn_SUCCESS;
+
+    GetMatTex(mat, volume.thicknessTexture, AI_MATKEY_VOLUME_THICKNESS_TEXTURE);
+
+    result = result || mat.Get(AI_MATKEY_VOLUME_ATTENUATION_DISTANCE, volume.attenuationDistance);
+    result = result || GetMatColor(mat, volume.attenuationColor, AI_MATKEY_VOLUME_ATTENUATION_COLOR) != aiReturn_SUCCESS;
+
+    // Valid if any of these properties are available
+    return result || volume.thicknessTexture.texture;
+}
+
+bool glTF2Exporter::GetMatIOR(const aiMaterial &mat, glTF2::MaterialIOR &ior) {
+    return mat.Get(AI_MATKEY_REFRACTI, ior.ior) == aiReturn_SUCCESS;
+}
+
 void glTF2Exporter::ExportMaterials() {
     aiString aiName;
     for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) {
@@ -824,6 +840,18 @@ void glTF2Exporter::ExportMaterials() {
                     mAsset->extensionsUsed.KHR_materials_transmission = true;
                     m->materialTransmission = Nullable<MaterialTransmission>(transmission);
                 }
+                
+                MaterialVolume volume;
+                if (GetMatVolume(mat, volume)) {
+                    mAsset->extensionsUsed.KHR_materials_volume = true;
+                    m->materialVolume = Nullable<MaterialVolume>(volume);
+                }
+                                
+                MaterialIOR ior;
+                if (GetMatIOR(mat, ior)) {
+                    mAsset->extensionsUsed.KHR_materials_ior = true;
+                    m->materialIOR = Nullable<MaterialIOR>(ior);
+                }
             }
         }
     }

+ 4 - 0
code/AssetLib/glTF2/glTF2Exporter.h

@@ -77,6 +77,8 @@ struct PbrSpecularGlossiness;
 struct MaterialSheen;
 struct MaterialClearcoat;
 struct MaterialTransmission;
+struct MaterialVolume;
+struct MaterialIOR;
 
 // Vec/matrix types, as raw float arrays
 typedef float(vec2)[2];
@@ -114,6 +116,8 @@ protected:
     bool GetMatSheen(const aiMaterial &mat, glTF2::MaterialSheen &sheen);
     bool GetMatClearcoat(const aiMaterial &mat, glTF2::MaterialClearcoat &clearcoat);
     bool GetMatTransmission(const aiMaterial &mat, glTF2::MaterialTransmission &transmission);
+    bool GetMatVolume(const aiMaterial &mat, glTF2::MaterialVolume &volume);
+    bool GetMatIOR(const aiMaterial &mat, glTF2::MaterialIOR &ior);
     void ExportMetadata();
     void ExportMaterials();
     void ExportMeshes();

+ 17 - 0
code/AssetLib/glTF2/glTF2Importer.cpp

@@ -341,6 +341,23 @@ static aiMaterial *ImportMaterial(std::vector<int> &embeddedTexIdxs, Asset &r, M
             SetMaterialTextureProperty(embeddedTexIdxs, r, transmission.transmissionTexture, aimat, AI_MATKEY_TRANSMISSION_TEXTURE);
         }
 
+        // KHR_materials_volume
+        if (mat.materialVolume.isPresent) {
+            MaterialVolume &volume = mat.materialVolume.value;
+
+            aimat->AddProperty(&volume.thicknessFactor, 1, AI_MATKEY_VOLUME_THICKNESS_FACTOR);
+            SetMaterialTextureProperty(embeddedTexIdxs, r, volume.thicknessTexture, aimat, AI_MATKEY_VOLUME_THICKNESS_TEXTURE);
+            aimat->AddProperty(&volume.attenuationDistance, 1, AI_MATKEY_VOLUME_ATTENUATION_DISTANCE);
+            SetMaterialColorProperty(r, volume.attenuationColor, aimat, AI_MATKEY_VOLUME_ATTENUATION_COLOR);
+        }
+
+        // KHR_materials_ior
+        if (mat.materialIOR.isPresent) {
+            MaterialIOR &ior = mat.materialIOR.value;
+
+            aimat->AddProperty(&ior.ior, 1, AI_MATKEY_REFRACTI);
+        }
+
         return aimat;
     } catch (...) {
         delete aimat;

+ 13 - 0
include/assimp/material.h

@@ -1028,6 +1028,19 @@ extern "C" {
 // Multiplied by AI_MATKEY_TRANSMISSION_FACTOR
 #define AI_MATKEY_TRANSMISSION_TEXTURE aiTextureType_TRANSMISSION, 0
 
+// Volume
+// ------------
+// https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_volume
+// The thickness of the volume beneath the surface. If the value is 0 the material is thin-walled. Otherwise the material is a volume boundary.
+#define AI_MATKEY_VOLUME_THICKNESS_FACTOR "$mat.volume.thicknessFactor", 0, 0
+// Texture that defines the thickness.
+// Multiplied by AI_MATKEY_THICKNESS_FACTOR
+#define AI_MATKEY_VOLUME_THICKNESS_TEXTURE aiTextureType_TRANSMISSION, 1
+// Density of the medium given as the average distance that light travels in the medium before interacting with a particle.
+#define AI_MATKEY_VOLUME_ATTENUATION_DISTANCE "$mat.volume.attenuationDistance", 0, 0
+// The color that white light turns into due to absorption when reaching the attenuation distance.
+#define AI_MATKEY_VOLUME_ATTENUATION_COLOR "$mat.volume.attenuationColor", 0, 0
+
 // Emissive
 // --------
 #define AI_MATKEY_USE_EMISSIVE_MAP "$mat.useEmissiveMap", 0, 0