Browse Source

Added KHR_materials_iridescence (WIP)

Vicente Penades 3 years ago
parent
commit
7e41fc72b5

+ 30 - 0
build/SharpGLTF.CodeGen/Ext.KHR_Iridescence.cs

@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    class IridescenceExtension : SchemaProcessor
+    {
+        private static string SchemaUri => Constants.KhronosExtensionPath("KHR_materials_iridescence", "glTF.KHR_materials_iridescence.schema.json");
+        public override IEnumerable<(string, SchemaType.Context)> Process()
+        {
+            var ctx = SchemaProcessing.LoadSchemaContext(SchemaUri);
+            ctx.IgnoredByCodeEmitter("glTF Property");
+            ctx.IgnoredByCodeEmitter("glTF Child of Root Property");
+            ctx.IgnoredByCodeEmitter("Texture Info");
+            ctx.IgnoredByCodeEmitter("Material Normal Texture Info");            
+
+            yield return ("ext.Iridescence.g", ctx);
+        }
+
+        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetRuntimeName("KHR_materials_iridescence glTF extension", "MaterialIridescence");
+        }
+    }
+}

+ 1 - 0
build/SharpGLTF.CodeGen/Program.cs

@@ -37,6 +37,7 @@ namespace SharpGLTF
             processors.Add(new VolumeExtension());
             processors.Add(new VolumeExtension());
             processors.Add(new SpecularExtension());
             processors.Add(new SpecularExtension());
             processors.Add(new ClearCoatExtension());
             processors.Add(new ClearCoatExtension());
+            processors.Add(new IridescenceExtension());
             processors.Add(new TransmissionExtension());
             processors.Add(new TransmissionExtension());
             processors.Add(new EmissiveStrengthExtension());
             processors.Add(new EmissiveStrengthExtension());
             processors.Add(new SpecularGlossinessExtension());
             processors.Add(new SpecularGlossinessExtension());

+ 85 - 0
src/SharpGLTF.Core/Schema2/Generated/ext.Iridescence.g.cs

@@ -0,0 +1,85 @@
+// <auto-generated/>
+
+//------------------------------------------------------------------------------------------------
+//      This file has been programatically generated; DON´T EDIT!
+//------------------------------------------------------------------------------------------------
+
+#pragma warning disable SA1001
+#pragma warning disable SA1027
+#pragma warning disable SA1028
+#pragma warning disable SA1121
+#pragma warning disable SA1205
+#pragma warning disable SA1309
+#pragma warning disable SA1402
+#pragma warning disable SA1505
+#pragma warning disable SA1507
+#pragma warning disable SA1508
+#pragma warning disable SA1652
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Numerics;
+using System.Text.Json;
+
+namespace SharpGLTF.Schema2
+{
+	using Collections;
+
+	/// <summary>
+	/// glTF extension that defines an iridescence effect.
+	/// </summary>
+	partial class MaterialIridescence : ExtraProperties
+	{
+	
+		private const Double _iridescenceFactorDefault = 0;
+		private const Double _iridescenceFactorMinimum = 0;
+		private const Double _iridescenceFactorMaximum = 1;
+		private Double? _iridescenceFactor = _iridescenceFactorDefault;
+		
+		private const Double _iridescenceIorDefault = 1.3;
+		private const Double _iridescenceIorMinimum = 1;
+		private Double? _iridescenceIor = _iridescenceIorDefault;
+		
+		private TextureInfo _iridescenceTexture;
+		
+		private const Double _iridescenceThicknessMaximumDefault = 400;
+		private const Double _iridescenceThicknessMaximumMinimum = 0;
+		private Double? _iridescenceThicknessMaximum = _iridescenceThicknessMaximumDefault;
+		
+		private const Double _iridescenceThicknessMinimumDefault = 100;
+		private const Double _iridescenceThicknessMinimumMinimum = 0;
+		private Double? _iridescenceThicknessMinimum = _iridescenceThicknessMinimumDefault;
+		
+		private TextureInfo _iridescenceThicknessTexture;
+		
+	
+		protected override void SerializeProperties(Utf8JsonWriter writer)
+		{
+			base.SerializeProperties(writer);
+			SerializeProperty(writer, "iridescenceFactor", _iridescenceFactor, _iridescenceFactorDefault);
+			SerializeProperty(writer, "iridescenceIor", _iridescenceIor, _iridescenceIorDefault);
+			SerializePropertyObject(writer, "iridescenceTexture", _iridescenceTexture);
+			SerializeProperty(writer, "iridescenceThicknessMaximum", _iridescenceThicknessMaximum, _iridescenceThicknessMaximumDefault);
+			SerializeProperty(writer, "iridescenceThicknessMinimum", _iridescenceThicknessMinimum, _iridescenceThicknessMinimumDefault);
+			SerializePropertyObject(writer, "iridescenceThicknessTexture", _iridescenceThicknessTexture);
+		}
+	
+		protected override void DeserializeProperty(string jsonPropertyName, ref Utf8JsonReader reader)
+		{
+			switch (jsonPropertyName)
+			{
+				case "iridescenceFactor": _iridescenceFactor = DeserializePropertyValue<Double?>(ref reader); break;
+				case "iridescenceIor": _iridescenceIor = DeserializePropertyValue<Double?>(ref reader); break;
+				case "iridescenceTexture": _iridescenceTexture = DeserializePropertyValue<TextureInfo>(ref reader); break;
+				case "iridescenceThicknessMaximum": _iridescenceThicknessMaximum = DeserializePropertyValue<Double?>(ref reader); break;
+				case "iridescenceThicknessMinimum": _iridescenceThicknessMinimum = DeserializePropertyValue<Double?>(ref reader); break;
+				case "iridescenceThicknessTexture": _iridescenceThicknessTexture = DeserializePropertyValue<TextureInfo>(ref reader); break;
+				default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
+			}
+		}
+	
+	}
+
+}

+ 1 - 0
src/SharpGLTF.Core/Schema2/gltf.ExtensionsFactory.cs

@@ -37,6 +37,7 @@ namespace SharpGLTF.Schema2
             RegisterExtension<Material, MaterialVolume>("KHR_materials_volume");
             RegisterExtension<Material, MaterialVolume>("KHR_materials_volume");
             RegisterExtension<Material, MaterialEmissiveStrength>("KHR_materials_emissive_strength");
             RegisterExtension<Material, MaterialEmissiveStrength>("KHR_materials_emissive_strength");
             RegisterExtension<Material, MaterialPBRSpecularGlossiness>("KHR_materials_pbrSpecularGlossiness");
             RegisterExtension<Material, MaterialPBRSpecularGlossiness>("KHR_materials_pbrSpecularGlossiness");
+            RegisterExtension<Material, MaterialIridescence>("KHR_materials_iridescence");
 
 
             RegisterExtension<TextureInfo, TextureTransform>("KHR_texture_transform");
             RegisterExtension<TextureInfo, TextureTransform>("KHR_texture_transform");
 
 

+ 5 - 0
src/SharpGLTF.Core/Schema2/gltf.MaterialParameter.cs

@@ -31,6 +31,10 @@ namespace SharpGLTF.Schema2
         OcclusionStrength,
         OcclusionStrength,
         EmissiveStrength,
         EmissiveStrength,
 
 
+        Minimum, Maximum,
+
+        IndexOfRefraction,
+
         MetallicFactor,
         MetallicFactor,
         RoughnessFactor,
         RoughnessFactor,
         SpecularFactor,
         SpecularFactor,
@@ -38,6 +42,7 @@ namespace SharpGLTF.Schema2
         ClearCoatFactor,
         ClearCoatFactor,
         ThicknessFactor,
         ThicknessFactor,
         TransmissionFactor,
         TransmissionFactor,
+        IridescenceFactor,
         AttenuationDistance,
         AttenuationDistance,
     }
     }
 
 

+ 83 - 0
src/SharpGLTF.Core/Schema2/gltf.MaterialsFactory.cs

@@ -105,6 +105,9 @@ namespace SharpGLTF.Schema2
             channels = this.GetExtension<MaterialVolume>()?.GetChannels(this);
             channels = this.GetExtension<MaterialVolume>()?.GetChannels(this);
             if (channels != null) { foreach (var c in channels) yield return c; }
             if (channels != null) { foreach (var c in channels) yield return c; }
 
 
+            channels = this.GetExtension<MaterialIridescence>()?.GetChannels(this);
+            if (channels != null) { foreach (var c in channels) yield return c; }
+
             var normalParam = new _MaterialParameter<float>(
             var normalParam = new _MaterialParameter<float>(
                 _MaterialParameterKey.NormalScale,
                 _MaterialParameterKey.NormalScale,
                 MaterialNormalTextureInfo.ScaleDefault,
                 MaterialNormalTextureInfo.ScaleDefault,
@@ -649,4 +652,84 @@ namespace SharpGLTF.Schema2
             return new _MaterialParameter<float>(_MaterialParameterKey.EmissiveStrength, DefaultEmissiveStrength, _getter, _setter);
             return new _MaterialParameter<float>(_MaterialParameterKey.EmissiveStrength, DefaultEmissiveStrength, _getter, _setter);
         }
         }
     }
     }
+
+
+    internal sealed partial class MaterialIridescence
+    {
+        #pragma warning disable CA1801 // Review unused parameters
+        internal MaterialIridescence(Material material) { }
+        #pragma warning restore CA1801 // Review unused parameters
+
+        protected override IEnumerable<ExtraProperties> GetLogicalChildren()
+        {
+            return base.GetLogicalChildren().ConcatElements(_iridescenceTexture, _iridescenceThicknessTexture);
+        }
+
+        protected override void OnValidateContent(ValidationContext validate)
+        {
+            base.OnValidateContent(validate);
+
+            /*
+            if (_attenuationColor.HasValue)
+            {
+                Guard.MustBeBetweenOrEqualTo(_attenuationColor.Value.X, 0, float.MaxValue, nameof(_attenuationColor));
+                Guard.MustBeBetweenOrEqualTo(_attenuationColor.Value.Y, 0, float.MaxValue, nameof(_attenuationColor));
+                Guard.MustBeBetweenOrEqualTo(_attenuationColor.Value.Z, 0, float.MaxValue, nameof(_attenuationColor));
+            }
+
+            if (_thicknessFactor.HasValue)
+            {
+                Guard.MustBeBetweenOrEqualTo(_thicknessFactor.Value, _thicknessFactorMinimum, float.MaxValue, nameof(_thicknessFactor));
+            }*/
+        }
+
+        private TextureInfo _GetIridescenceTexture(bool create)
+        {
+            if (create && _iridescenceTexture == null) _iridescenceTexture = new TextureInfo();
+            return _iridescenceTexture;
+        }
+
+        private TextureInfo _GetIridescenceThicknessTexture(bool create)
+        {
+            if (create && _iridescenceThicknessTexture == null) _iridescenceThicknessTexture = new TextureInfo();
+            return _iridescenceThicknessTexture;
+        }
+
+        public float IridescenceFactor
+        {
+            get => (float)_iridescenceFactor.AsValue(_iridescenceFactorDefault);
+            set => _iridescenceFactor = ((double)value).AsNullable(_iridescenceFactorDefault, _iridescenceFactorMinimum, _iridescenceFactorMaximum);
+        }
+
+        public float IridescenceIndexOfRefraction
+        {
+            get => (float)_iridescenceIor.AsValue(_iridescenceIorDefault);
+            set => _iridescenceIor = ((double)value).AsNullable(_iridescenceIorDefault, _iridescenceIorMinimum, double.MaxValue);
+        }
+
+        public float IridescenceThicknessMinimum
+        {
+            get => (float)_iridescenceThicknessMinimum.AsValue(_iridescenceThicknessMinimumDefault);
+            set => _iridescenceThicknessMinimum = ((double)value).AsNullable(_iridescenceThicknessMinimumDefault, _iridescenceThicknessMinimumMinimum, double.MaxValue);
+        }
+
+        public float IridescenceThicknessMaximum
+        {
+            get => (float)_iridescenceThicknessMaximum.AsValue(_iridescenceThicknessMaximumDefault);
+            set => _iridescenceThicknessMaximum = ((double)value).AsNullable(_iridescenceThicknessMaximumDefault, _iridescenceThicknessMaximumMinimum, double.MaxValue);
+        }
+
+        public IEnumerable<MaterialChannel> GetChannels(Material material)
+        {
+            var factor = new _MaterialParameter<float>(_MaterialParameterKey.IridescenceFactor, (float)_iridescenceFactorDefault, () => IridescenceFactor, v => IridescenceFactor = v);
+            var idxRef = new _MaterialParameter<float>(_MaterialParameterKey.IndexOfRefraction, (float)_iridescenceIorDefault, () => IridescenceIndexOfRefraction, v => IridescenceIndexOfRefraction = v);
+
+            yield return new MaterialChannel(material, "Iridescence", _GetIridescenceTexture, factor, idxRef);
+
+            var thkMin = new _MaterialParameter<float>(_MaterialParameterKey.Minimum, (float)_iridescenceThicknessMinimumDefault, () => IridescenceThicknessMinimum, v => IridescenceThicknessMinimum = v);
+            var thkMax = new _MaterialParameter<float>(_MaterialParameterKey.Maximum, (float)_iridescenceThicknessMaximumDefault, () => IridescenceThicknessMaximum, v => IridescenceThicknessMaximum = v);
+
+            yield return new MaterialChannel(material, "IridescenceThickness", _GetIridescenceThicknessTexture, thkMin, thkMax);
+        }
+    }
 }
 }

+ 5 - 0
src/SharpGLTF.Toolkit/Materials/MaterialEnums.cs

@@ -61,6 +61,10 @@ namespace SharpGLTF.Materials
         OcclusionStrength,
         OcclusionStrength,
         EmissiveStrength,
         EmissiveStrength,
 
 
+        Minimum, Maximum,
+
+        IndexOfRefraction,
+
         MetallicFactor,
         MetallicFactor,
         RoughnessFactor,
         RoughnessFactor,
         SpecularFactor,
         SpecularFactor,
@@ -68,6 +72,7 @@ namespace SharpGLTF.Materials
         ClearCoatFactor,
         ClearCoatFactor,
         ThicknessFactor,
         ThicknessFactor,
         TransmissionFactor,
         TransmissionFactor,
+        IridescenceFactor,
         AttenuationDistance,
         AttenuationDistance,
     }
     }
 
 

+ 12 - 19
tests/SharpGLTF.Core.Tests/Schema2/LoadAndSave/LoadSampleTests.cs

@@ -54,13 +54,16 @@ namespace SharpGLTF.Schema2.LoadAndSave
 
 
             var perf_clone = perf.ElapsedMilliseconds;
             var perf_clone = perf.ElapsedMilliseconds;
 
 
-            var unsupportedExtensions = new[] { "MSFT_lod", "EXT_lights_image_based" };
-
-            // check extensions used
-            if (unsupportedExtensions.All(uex => !model.ExtensionsUsed.Contains(uex)))
+            if (!f.Contains("Iridescence")) // the iridescence sample models declares using IOR but it's not actually used
             {
             {
-                var detectedExtensions = model.GatherUsedExtensions().ToArray();
-                CollectionAssert.AreEquivalent(model.ExtensionsUsed, detectedExtensions);
+                var unsupportedExtensions = new[] { "MSFT_lod", "EXT_lights_image_based" };
+
+                // check extensions used
+                if (unsupportedExtensions.All(uex => !model.ExtensionsUsed.Contains(uex)))
+                {
+                    var detectedExtensions = model.GatherUsedExtensions().ToArray();
+                    CollectionAssert.AreEquivalent(model.ExtensionsUsed, detectedExtensions);
+                }
             }
             }
 
 
             // Save models
             // Save models
@@ -161,6 +164,7 @@ namespace SharpGLTF.Schema2.LoadAndSave
             roundtripInstanced.AttachToCurrentTest($"{ff}.roundtrip.instancing.glb");            
             roundtripInstanced.AttachToCurrentTest($"{ff}.roundtrip.instancing.glb");            
         }
         }
 
 
+        [TestCase("IridescenceMetallicSpheres.gltf")]
         [TestCase("SpecGlossVsMetalRough.gltf")]
         [TestCase("SpecGlossVsMetalRough.gltf")]
         [TestCase(@"TextureTransformTest.gltf")]
         [TestCase(@"TextureTransformTest.gltf")]
         [TestCase(@"UnlitTest\glTF-Binary\UnlitTest.glb")]                                                
         [TestCase(@"UnlitTest\glTF-Binary\UnlitTest.glb")]                                                
@@ -169,7 +173,7 @@ namespace SharpGLTF.Schema2.LoadAndSave
         [TestCase(@"glTF-Quantized\AnimatedMorphCube.gltf")]
         [TestCase(@"glTF-Quantized\AnimatedMorphCube.gltf")]
         [TestCase(@"glTF-Quantized\Duck.gltf")]
         [TestCase(@"glTF-Quantized\Duck.gltf")]
         [TestCase(@"glTF-Quantized\Lantern.gltf")]
         [TestCase(@"glTF-Quantized\Lantern.gltf")]
-        [TestCase(@"MosquitoInAmber.glb")]
+        [TestCase(@"MosquitoInAmber.glb")]        
         public void LoadModelsWithExtensions(string filePath)
         public void LoadModelsWithExtensions(string filePath)
         {            
         {            
             TestContext.CurrentContext.AttachGltfValidatorLinks();
             TestContext.CurrentContext.AttachGltfValidatorLinks();
@@ -178,18 +182,7 @@ namespace SharpGLTF.Schema2.LoadAndSave
                 .GetSampleModelsPaths()
                 .GetSampleModelsPaths()
                 .FirstOrDefault(item => item.EndsWith(filePath));
                 .FirstOrDefault(item => item.EndsWith(filePath));
 
 
-            var model = ModelRoot.Load(filePath);
-            Assert.NotNull(model);
-
-            // do a model clone and compare it
-            _AssertAreEqual(model, model.DeepClone());
-
-            // evaluate and save all the triangles to a Wavefront Object
-
-            filePath = System.IO.Path.GetFileNameWithoutExtension(filePath);
-            model.AttachToCurrentTest(filePath + "_wf.obj");
-            model.AttachToCurrentTest(filePath + ".glb");
-            model.AttachToCurrentTest(filePath + ".gltf");
+            _LoadModel(filePath);
         }
         }
 
 
         [Test]
         [Test]

+ 1 - 2
tests/SharpGLTF.Core.Tests/Validation/InvalidFilesTests.cs

@@ -59,8 +59,7 @@ namespace SharpGLTF.Validation
             var files = TestFiles
             var files = TestFiles
                 .GetKhronosValidationPaths()
                 .GetKhronosValidationPaths()
                 .Where(item => item.EndsWith(".gltf"))
                 .Where(item => item.EndsWith(".gltf"))
-                .Where(item => !item.Contains("KHR_materials_variants"))
-                .Where(item => !item.Contains("KHR_materials_iridescence"));
+                .Where(item => !item.Contains("KHR_materials_variants"));
 
 
             foreach (var f in files)
             foreach (var f in files)
             {
             {

+ 0 - 2
tests/SharpGLTF.NUnit/TestFiles.cs

@@ -282,8 +282,6 @@ namespace SharpGLTF
 
 
         public IEnumerable<string> GetPaths(params string[] basePath)
         public IEnumerable<string> GetPaths(params string[] basePath)
         {
         {
-            if (Name.Contains("Iridescence")) yield break; // still under development
-
             var rootPath = System.IO.Path.Combine(basePath);
             var rootPath = System.IO.Path.Combine(basePath);
 
 
             foreach(var variant in Variants)
             foreach(var variant in Variants)