Skip to content

Commit 8aafa16

Browse files
committed
Added KHR_material_dispersion
1 parent 3ec7719 commit 8aafa16

File tree

9 files changed

+212
-8
lines changed

9 files changed

+212
-8
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
using SharpGLTF.SchemaReflection;
6+
7+
namespace SharpGLTF
8+
{
9+
class DispersionExtension : SchemaProcessor
10+
{
11+
private static string SchemaUri => Constants.KhronosExtensionPath("KHR_materials_dispersion", "material.KHR_materials_dispersion.schema.json");
12+
13+
private const string ExtensionRootClassName = "KHR_materials_dispersion glTF Material Extension";
14+
15+
public override IEnumerable<(string, SchemaType.Context)> Process()
16+
{
17+
var ctx = SchemaProcessing.LoadSchemaContext(SchemaUri);
18+
ctx.IgnoredByCodeEmitter("glTF Property");
19+
ctx.IgnoredByCodeEmitter("glTF Child of Root Property");
20+
21+
yield return ("ext.Dispersion.g", ctx);
22+
}
23+
24+
public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
25+
{
26+
newEmitter.SetRuntimeName(ExtensionRootClassName, "MaterialDispersion");
27+
}
28+
}
29+
}

build/SharpGLTF.CodeGen/Program.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ static void Main(string[] args)
2828
// material extensions
2929
processors.Add(new UnlitExtension());
3030
processors.Add(new IorExtension());
31-
processors.Add(new SheenExtension());
31+
processors.Add(new SheenExtension());
3232
processors.Add(new VolumeExtension());
3333
processors.Add(new SpecularExtension());
3434
processors.Add(new ClearCoatExtension());
35+
processors.Add(new DispersionExtension());
3536
processors.Add(new AnisotropyExtension());
3637
processors.Add(new IridescenceExtension());
3738
processors.Add(new TransmissionExtension());
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// <auto-generated/>
2+
3+
//------------------------------------------------------------------------------------------------
4+
// This file has been programatically generated; DON´T EDIT!
5+
//------------------------------------------------------------------------------------------------
6+
7+
#pragma warning disable SA1001
8+
#pragma warning disable SA1027
9+
#pragma warning disable SA1028
10+
#pragma warning disable SA1121
11+
#pragma warning disable SA1205
12+
#pragma warning disable SA1309
13+
#pragma warning disable SA1402
14+
#pragma warning disable SA1505
15+
#pragma warning disable SA1507
16+
#pragma warning disable SA1508
17+
#pragma warning disable SA1652
18+
19+
using System;
20+
using System.Collections.Generic;
21+
using System.Linq;
22+
using System.Text;
23+
using System.Numerics;
24+
using System.Text.Json;
25+
26+
using JSONREADER = System.Text.Json.Utf8JsonReader;
27+
using JSONWRITER = System.Text.Json.Utf8JsonWriter;
28+
using FIELDINFO = SharpGLTF.Reflection.FieldInfo;
29+
30+
31+
namespace SharpGLTF.Schema2
32+
{
33+
using Collections;
34+
35+
/// <summary>
36+
/// glTF extension that defines the strength of dispersion.
37+
/// </summary>
38+
#if NET6_0_OR_GREATER
39+
[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)]
40+
#endif
41+
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("SharpGLTF.CodeGen", "1.0.0.0")]
42+
partial class MaterialDispersion : ExtraProperties
43+
{
44+
45+
#region reflection
46+
47+
public const string SCHEMANAME = "KHR_materials_dispersion";
48+
protected override string GetSchemaName() => SCHEMANAME;
49+
50+
protected override IEnumerable<string> ReflectFieldsNames()
51+
{
52+
yield return "dispersion";
53+
foreach(var f in base.ReflectFieldsNames()) yield return f;
54+
}
55+
protected override bool TryReflectField(string name, out FIELDINFO value)
56+
{
57+
switch(name)
58+
{
59+
case "dispersion": value = FIELDINFO.From("dispersion",this, instance => instance._dispersion ?? 0); return true;
60+
default: return base.TryReflectField(name, out value);
61+
}
62+
}
63+
64+
#endregion
65+
66+
#region data
67+
68+
private const Double _dispersionDefault = 0;
69+
private const Double _dispersionMinimum = 0;
70+
private Double? _dispersion = _dispersionDefault;
71+
72+
#endregion
73+
74+
#region serialization
75+
76+
protected override void SerializeProperties(JSONWRITER writer)
77+
{
78+
base.SerializeProperties(writer);
79+
SerializeProperty(writer, "dispersion", _dispersion, _dispersionDefault);
80+
}
81+
82+
protected override void DeserializeProperty(string jsonPropertyName, ref JSONREADER reader)
83+
{
84+
switch (jsonPropertyName)
85+
{
86+
case "dispersion": DeserializePropertyValue<MaterialDispersion, Double?>(ref reader, this, out _dispersion); break;
87+
default: base.DeserializeProperty(jsonPropertyName,ref reader); break;
88+
}
89+
}
90+
91+
#endregion
92+
93+
}
94+
95+
}

src/SharpGLTF.Core/Schema2/gltf.ExtensionsFactory.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ static ExtensionsFactory()
4040
RegisterExtension<Material, MaterialUnlit>("KHR_materials_unlit", p => new MaterialUnlit(p));
4141
RegisterExtension<Material, MaterialSheen>("KHR_materials_sheen", p => new MaterialSheen(p));
4242
RegisterExtension<Material, MaterialIOR>("KHR_materials_ior", p => new MaterialIOR(p));
43+
RegisterExtension<Material, MaterialDispersion>("KHR_materials_dispersion", p => new MaterialDispersion(p));
4344
RegisterExtension<Material, MaterialSpecular>("KHR_materials_specular", p => new MaterialSpecular(p));
4445
RegisterExtension<Material, MaterialClearCoat>("KHR_materials_clearcoat", p => new MaterialClearCoat(p));
4546
RegisterExtension<Material, MaterialTransmission>("KHR_materials_transmission", p => new MaterialTransmission(p));
@@ -174,8 +175,10 @@ internal static string Identify(Type parentType, Type extensionType)
174175
return null;
175176
}
176177

178+
[System.Diagnostics.DebuggerDisplay("{Name} {ParentType} {ExtType}")]
177179
internal readonly struct ExtensionEntry
178180
{
181+
#region lifecycle
179182
public static ExtensionEntry Create
180183
<
181184
TParent,
@@ -213,11 +216,19 @@ public ExtensionEntry(string n, Type p, Type e, Func<JsonSerializable, JsonSeria
213216
Factory = f;
214217
}
215218

219+
#endregion
220+
221+
#region data
222+
216223
public readonly string Name;
217224
public readonly Type ParentType;
218225
public readonly Type ExtType;
219226
public readonly Func<JsonSerializable, JsonSerializable> Factory;
220227

228+
#endregion
229+
230+
#region API
231+
221232
public readonly bool IsMatch(Type parentType, string extensionName)
222233
{
223234
return this.ParentType.IsAssignableFrom(parentType) && this.Name == extensionName;
@@ -227,6 +238,8 @@ public readonly bool IsMatch(Type parentType, Type extensionType)
227238
{
228239
return this.ParentType.IsAssignableFrom(parentType) && this.ExtType == extensionType;
229240
}
241+
242+
#endregion
230243
}
231244

232245
#endregion

src/SharpGLTF.Core/Schema2/gltf.Material.cs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ public float IndexOfRefraction
7777
if (this.GetExtension<MaterialUnlit>() != null) return;
7878
if (this.GetExtension<MaterialPBRSpecularGlossiness>() != null) return;
7979

80-
// setting the IOR to its default value essentially
81-
// makes the extension unneccesary
80+
// setting the IOR to its default value
81+
// essentially makes the extension unneccesary.
8282
if (value == MaterialIOR.DefaultIndexOfRefraction)
8383
{
8484
this.RemoveExtensions<MaterialIOR>();
@@ -89,10 +89,36 @@ public float IndexOfRefraction
8989
}
9090
}
9191

92+
/// <summary>
93+
/// Gets or sets the Dispersion.
94+
/// </summary>
95+
/// <remarks>
96+
/// This property backs KHR_Materials_Dispersion extension.
97+
/// </remarks>
98+
public float Dispersion
99+
{
100+
get => this.GetExtension<MaterialDispersion>()?.Dispersion ?? MaterialDispersion.DefaultDispersion;
101+
set
102+
{
103+
if (this.GetExtension<MaterialUnlit>() != null) return;
104+
if (this.GetExtension<MaterialPBRSpecularGlossiness>() != null) return;
105+
106+
// setting the Dispersion to its default value
107+
// essentially makes the extension unneccesary.
108+
if (value == MaterialDispersion.DefaultDispersion)
109+
{
110+
this.RemoveExtensions<MaterialDispersion>();
111+
return;
112+
}
113+
114+
this.UseExtension<MaterialDispersion>().Dispersion = value;
115+
}
116+
}
117+
92118
#endregion
93119

94120
#region API
95-
121+
96122
/// <summary>
97123
/// Finds an instance of <see cref="MaterialChannel"/>
98124
/// </summary>

src/SharpGLTF.Core/Schema2/gltf.MaterialsFactory.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,31 @@ public float IndexOfRefraction
477477
}
478478
}
479479

480+
/// <remarks>
481+
/// Mapped straight away to <see cref="Material.Dispersion"/>
482+
/// </remarks>
483+
internal sealed partial class MaterialDispersion
484+
{
485+
#pragma warning disable CA1801 // Review unused parameters
486+
internal MaterialDispersion(Material material) { }
487+
#pragma warning restore CA1801 // Review unused parameters
488+
489+
protected override void OnValidateContent(ValidationContext validate)
490+
{
491+
base.OnValidateContent(validate);
492+
493+
if (_dispersion < _dispersionMinimum) throw new ArgumentOutOfRangeException(nameof(Dispersion));
494+
}
495+
496+
public static float DefaultDispersion => (float)_dispersionDefault;
497+
498+
public float Dispersion
499+
{
500+
get => (float)(this._dispersion ?? _dispersionDefault);
501+
set => this._dispersion = Math.Max(_dispersionMinimum, value).AsNullable(_dispersionDefault);
502+
}
503+
}
504+
480505
internal sealed partial class MaterialSpecular
481506
{
482507
#pragma warning disable CA1801 // Review unused parameters

src/SharpGLTF.Toolkit/Materials/MaterialBuilder.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ public MaterialBuilder(MaterialBuilder other)
6161
this.AlphaCutoff = other.AlphaCutoff;
6262
this.DoubleSided = other.DoubleSided;
6363
this.ShaderStyle = other.ShaderStyle;
64-
this.IndexOfRefraction = other.IndexOfRefraction;
64+
this.Dispersion = other.Dispersion;
65+
this.IndexOfRefraction = other.IndexOfRefraction;
6566

6667
this._CompatibilityFallbackMaterial = other._CompatibilityFallbackMaterial == null
6768
? null
@@ -106,6 +107,8 @@ public String ShaderStyle
106107

107108
public float IndexOfRefraction { get; set; } = 1.5f;
108109

110+
public float Dispersion { get; set; } = 0;
111+
109112
/// <inheritdoc/>
110113
/// <remarks>
111114
/// Material builder uses default class equality, but NUnit4 does some weird trickery on equality
@@ -132,7 +135,8 @@ public static bool AreEqualByContent(MaterialBuilder x, MaterialBuilder y)
132135
// AlphaCutoff only has meaning when AlphaMode = Mask
133136
if (x.AlphaMode == AlphaMode.MASK && x.AlphaCutoff != y.AlphaCutoff) return false;
134137
if (x.DoubleSided != y.DoubleSided) return false;
135-
if (x.IndexOfRefraction != y.IndexOfRefraction) return false;
138+
if (x.Dispersion != y.Dispersion) return false;
139+
if (x.IndexOfRefraction != y.IndexOfRefraction) return false;
136140
if (x._ShaderStyle != y._ShaderStyle) return false;
137141

138142
if (!AreEqualByContent(x._CompatibilityFallbackMaterial, y._CompatibilityFallbackMaterial)) return false;
@@ -164,7 +168,8 @@ public static int GetContentHashCode(MaterialBuilder x)
164168
h ^= x.AlphaMode.GetHashCode();
165169
h ^= x.AlphaCutoff.GetHashCode();
166170
h ^= x.DoubleSided.GetHashCode();
167-
h ^= x.IndexOfRefraction.GetHashCode();
171+
h ^= x.Dispersion.GetHashCode();
172+
h ^= x.IndexOfRefraction.GetHashCode();
168173
h ^= x.ShaderStyle.GetHashCode(StringComparison.InvariantCulture);
169174

170175
h ^= x._Channels
@@ -285,7 +290,8 @@ internal void ValidateForSchema2()
285290
Guard.IsTrue(this.AlphaMode == this.CompatibilityFallback.AlphaMode, nameof(AlphaMode));
286291
Guard.MustBeEqualTo(this.AlphaCutoff, this.CompatibilityFallback.AlphaCutoff, nameof(AlphaCutoff));
287292
Guard.MustBeEqualTo(this.DoubleSided, this.CompatibilityFallback.DoubleSided, nameof(DoubleSided));
288-
Guard.MustBeEqualTo(this.IndexOfRefraction, this.CompatibilityFallback.IndexOfRefraction, nameof(IndexOfRefraction));
293+
Guard.MustBeEqualTo(this.Dispersion, this.CompatibilityFallback.Dispersion, nameof(Dispersion));
294+
Guard.MustBeEqualTo(this.IndexOfRefraction, this.CompatibilityFallback.IndexOfRefraction, nameof(IndexOfRefraction));
289295

290296
foreach (var chKey in new[] { KnownChannel.Normal, KnownChannel.Occlusion, KnownChannel.Emissive })
291297
{

src/SharpGLTF.Toolkit/Schema2/MaterialExtensions.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,9 @@ private static void _CopyDefaultTo(Material srcMaterial, MaterialBuilder dstMate
310310
dstMaterial.AlphaMode = srcMaterial.Alpha.ToToolkit();
311311
dstMaterial.AlphaCutoff = srcMaterial.AlphaCutoff;
312312
dstMaterial.DoubleSided = srcMaterial.DoubleSided;
313+
dstMaterial.Dispersion = srcMaterial.Dispersion;
313314
dstMaterial.IndexOfRefraction = srcMaterial.IndexOfRefraction;
315+
314316

315317
srcMaterial.CopyChannelsTo(dstMaterial, "Normal", "Occlusion", "Emissive");
316318
}
@@ -457,6 +459,10 @@ var hasDiffuseTransmission
457459
defMaterial = srcMaterial.CompatibilityFallback;
458460
}
459461

462+
// Dispersion must be set after dst material initialization,
463+
// otherwise it's erased since it's stored in an extension
464+
dstMaterial.Dispersion = srcMaterial.Dispersion;
465+
460466
// IOR must be set after dst material initialization,
461467
// otherwise it's erased since it's stored in an extension
462468
dstMaterial.IndexOfRefraction = srcMaterial.IndexOfRefraction;
@@ -477,6 +483,7 @@ var hasDiffuseTransmission
477483

478484
// final validation
479485

486+
System.Diagnostics.Debug.Assert(dstMaterial.Dispersion == srcMaterial.Dispersion, "set Dispersion after dst material initialization");
480487
System.Diagnostics.Debug.Assert(dstMaterial.IndexOfRefraction == srcMaterial.IndexOfRefraction, "set IOR after dst material initialization");
481488
}
482489

tests/SharpGLTF.Toolkit.Tests/Materials/MaterialBuilderTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ public void CreateMaterialWithExtensions()
110110
// https://github.com/vpenades/SharpGLTF/issues/246
111111
material.IndexOfRefraction = 7;
112112

113+
material.Dispersion = 2;
114+
113115
Assert.That(MaterialBuilder.AreEqualByContent(material, _Schema2Roundtrip(material)));
114116
Assert.That(MaterialBuilder.AreEqualByContent(material, material.Clone()));
115117

0 commit comments

Comments
 (0)