Przeglądaj źródła

Fixed MaterialBuilder's conversion to glTF not copying the IOR value.

Fixes #246
vpenades 1 rok temu
rodzic
commit
2073cf3cd6

+ 9 - 1
src/SharpGLTF.Toolkit/Schema2/MaterialExtensions.cs

@@ -390,7 +390,7 @@ namespace SharpGLTF.Schema2
             dstMaterial.Alpha = srcMaterial.AlphaMode.ToSchema2();
             dstMaterial.Alpha = srcMaterial.AlphaMode.ToSchema2();
             dstMaterial.AlphaCutoff = srcMaterial.AlphaCutoff;
             dstMaterial.AlphaCutoff = srcMaterial.AlphaCutoff;
             dstMaterial.DoubleSided = srcMaterial.DoubleSided;
             dstMaterial.DoubleSided = srcMaterial.DoubleSided;
-            dstMaterial.IndexOfRefraction = srcMaterial.IndexOfRefraction;
+            
 
 
             var hasClearCoat
             var hasClearCoat
                 = srcMaterial.GetChannel("ClearCoat") != null
                 = srcMaterial.GetChannel("ClearCoat") != null
@@ -442,6 +442,10 @@ namespace SharpGLTF.Schema2
                 defMaterial = srcMaterial.CompatibilityFallback;
                 defMaterial = srcMaterial.CompatibilityFallback;
             }
             }
 
 
+            // IOR must be set after dst material initialization,
+            // otherwise it's erased since it's stored in an extension
+            dstMaterial.IndexOfRefraction = srcMaterial.IndexOfRefraction;
+
             if (defMaterial != null)
             if (defMaterial != null)
             {
             {
                 if (defMaterial.ShaderStyle != "PBRMetallicRoughness") throw new ArgumentException(nameof(srcMaterial.CompatibilityFallback.ShaderStyle));
                 if (defMaterial.ShaderStyle != "PBRMetallicRoughness") throw new ArgumentException(nameof(srcMaterial.CompatibilityFallback.ShaderStyle));
@@ -452,6 +456,10 @@ namespace SharpGLTF.Schema2
                 defMaterial.CopyChannelsTo(dstMaterial, "SpecularColor", "SpecularFactor");
                 defMaterial.CopyChannelsTo(dstMaterial, "SpecularColor", "SpecularFactor");
                 defMaterial.CopyChannelsTo(dstMaterial, "VolumeThickness", "VolumeAttenuation");
                 defMaterial.CopyChannelsTo(dstMaterial, "VolumeThickness", "VolumeAttenuation");
             }
             }
+
+            // final validation
+
+            System.Diagnostics.Debug.Assert(dstMaterial.IndexOfRefraction == srcMaterial.IndexOfRefraction, "set IOR after dst material initialization");            
         }
         }
 
 
         public static void CopyChannelsTo(this MaterialBuilder srcMaterial, Material dstMaterial, params string[] channelKeys)
         public static void CopyChannelsTo(this MaterialBuilder srcMaterial, Material dstMaterial, params string[] channelKeys)

+ 16 - 3
tests/SharpGLTF.Toolkit.Tests/Materials/MaterialBuilderTests.cs

@@ -6,6 +6,7 @@ using System.Text;
 
 
 using NUnit.Framework;
 using NUnit.Framework;
 
 
+using SharpGLTF.Scenes;
 using SharpGLTF.Schema2;
 using SharpGLTF.Schema2;
 using SharpGLTF.Validation;
 using SharpGLTF.Validation;
 
 
@@ -23,8 +24,8 @@ namespace SharpGLTF.Materials
             // ... And we could use it for general equality checks, but then, since
             // ... And we could use it for general equality checks, but then, since
             // MaterialBuilder is NOT inmutable, it can mean that two materials can be equal
             // MaterialBuilder is NOT inmutable, it can mean that two materials can be equal
             // at a given time, and non equal at another. Furthermore, it would imply having
             // at a given time, and non equal at another. Furthermore, it would imply having
-            // a hash code that changes over time. As a consequence, it could be impossible
-            // to use MaterialBuilder as a dictionary Key.
+            // a hash code that changes over time. As a consequence, using MaterialBuilder as
+            // a dictionary key is possible, but dangerous if not carefully handled.
 
 
             var srcMaterial = _CreateUnlitMaterial();
             var srcMaterial = _CreateUnlitMaterial();
 
 
@@ -100,6 +101,18 @@ namespace SharpGLTF.Materials
             Assert.That(MaterialBuilder.AreEqualByContent(material, material.Clone()), Is.True);
             Assert.That(MaterialBuilder.AreEqualByContent(material, material.Clone()), Is.True);
         }
         }
 
 
+        [Test]
+        public void CreateIORWithFallback()
+        {
+            // https://github.com/vpenades/SharpGLTF/issues/246
+
+            var material = new MaterialBuilder("MaterialWithIOR");
+            material.IndexOfRefraction = 7;
+
+            Assert.That(MaterialBuilder.AreEqualByContent(material, material.Clone()), Is.True);
+            Assert.That(MaterialBuilder.AreEqualByContent(material, _Schema2Roundtrip(material)), Is.True);            
+        }
+
         private static MaterialBuilder _CreateUnlitMaterial()
         private static MaterialBuilder _CreateUnlitMaterial()
         {
         {
             var tex1 = ResourceInfo.From("shannon.png").FilePath;
             var tex1 = ResourceInfo.From("shannon.png").FilePath;
@@ -192,7 +205,7 @@ namespace SharpGLTF.Materials
                 .WithClearCoatRoughness(tex1, 1);
                 .WithClearCoatRoughness(tex1, 1);
 
 
             return material;
             return material;
-        }
+        }        
 
 
         [Obsolete("SpecularGlossiness has been deprecated by Khronos")]
         [Obsolete("SpecularGlossiness has been deprecated by Khronos")]
         private static MaterialBuilder _CreateSpecularGlossinessMaterialWithFallback()
         private static MaterialBuilder _CreateSpecularGlossinessMaterialWithFallback()