diff --git a/src/ThreeDModels/Format/Gltf/Extensions/KHR_materials_anisotropy.cs b/src/ThreeDModels/Format/Gltf/Extensions/KHR_materials_anisotropy.cs
new file mode 100644
index 0000000..8de024d
--- /dev/null
+++ b/src/ThreeDModels/Format/Gltf/Extensions/KHR_materials_anisotropy.cs
@@ -0,0 +1,98 @@
+using System.Text.Json;
+using ThreeDModels.Format.Gltf.Elements;
+using ThreeDModels.Format.Gltf.IO;
+using static ThreeDModels.Format.Gltf.IO.Utf8JsonReaderHelpers;
+
+namespace ThreeDModels.Format.Gltf.Extensions;
+
+///
+/// Represents an object that defines anisotropy.
+///
+public class KHR_materials_anisotropy : IGltfProperty
+{
+ ///
+ /// The anisotropy strength. When anisotropyTexture is present, this value is multiplied by the blue channel.
+ ///
+ public float AnisotropyStrength { get; set; }
+ ///
+ /// The rotation of the anisotropy in tangent, bitangent space, measured in radians counter-clockwise from the tangent.
+ ///
+ public float AnisotropyRotation { get; set; }
+ ///
+ /// The anisotropy texture. Red and green channels represent the anisotropy direction in [-1, 1] tangent, bitangent space, to be rotated by anisotropyRotation.
+ ///
+ public TextureInfo? AnisotropyTexture { get; set; }
+ public Dictionary? Extensions { get; set; }
+ public object? Extras { get; set; }
+}
+
+public class KhrMaterialsAnisotropyExtension : IGltfExtension
+{
+ public string Name => nameof(KHR_materials_anisotropy);
+ public const float Default_AnisotropyStrength = 0.0f;
+ public const float Default_AnisotropyRotation = 0.0f;
+
+ public object? Read(ref Utf8JsonReader jsonReader, GltfReaderContext context, Type parentType)
+ {
+ if (parentType != typeof(Material))
+ {
+ throw new InvalidDataException("KHR_materials_anisotropy must be used in a Material.");
+ }
+ float? anisotropyStrength = null;
+ float? anisotropyRotation = null;
+ TextureInfo? anisotropyTexture = null;
+ Dictionary? extensions = null;
+ object? extras = null;
+ if (jsonReader.TokenType == JsonTokenType.PropertyName && jsonReader.Read())
+ {
+ }
+ if (jsonReader.TokenType == JsonTokenType.Null)
+ {
+ return null;
+ }
+ else if (jsonReader.TokenType != JsonTokenType.StartObject)
+ {
+ throw new InvalidDataException("Failed to find start of property.");
+ }
+ while (jsonReader.Read())
+ {
+ if (jsonReader.TokenType == JsonTokenType.EndObject)
+ {
+ break;
+ }
+ var propertyName = jsonReader.GetString();
+ if (propertyName == nameof(anisotropyStrength))
+ {
+ anisotropyStrength = ReadFloat(ref jsonReader);
+ }
+ else if (propertyName == nameof(anisotropyRotation))
+ {
+ anisotropyRotation = ReadFloat(ref jsonReader);
+ }
+ else if (propertyName == nameof(anisotropyTexture))
+ {
+ anisotropyTexture = TextureInfoSerialization.Read(ref jsonReader, context);
+ }
+ else if (propertyName == nameof(extensions))
+ {
+ extensions = ExtensionsSerialization.Read(ref jsonReader, context);
+ }
+ else if (propertyName == nameof(extras))
+ {
+ extras = JsonSerialization.Read(ref jsonReader, context);
+ }
+ else
+ {
+ throw new InvalidDataException($"Unknown property: {propertyName}");
+ }
+ }
+ return new KHR_materials_anisotropy()
+ {
+ AnisotropyStrength = anisotropyStrength ?? Default_AnisotropyStrength,
+ AnisotropyRotation = anisotropyRotation ?? Default_AnisotropyRotation,
+ AnisotropyTexture = anisotropyTexture,
+ Extensions = extensions,
+ Extras = extras,
+ };
+ }
+}