Files
AR-Menu/Library/PackageCache/org.khronos.unitygltf@6b55d14e19c1/Runtime/Plugins/GLTFSerialization/Schema/GLTFMaterial.cs
2025-11-30 08:35:03 +02:00

245 lines
7.1 KiB
C#

using GLTF.Extensions;
using GLTF.Math;
using Newtonsoft.Json;
namespace GLTF.Schema
{
/// <summary>
/// The material appearance of a primitive.
/// </summary>
public class GLTFMaterial : GLTFChildOfRootProperty
{
/// <summary>
/// A set of parameter values that are used to define the metallic-roughness
/// material model from Physically-Based Rendering (PBR) methodology.
/// </summary>
public PbrMetallicRoughness PbrMetallicRoughness;
/// <summary>
/// A set of parameter values used to light flat-shaded materials
/// </summary>
public MaterialCommonConstant CommonConstant;
/// <summary>
/// A tangent space normal map. Each texel represents the XYZ components of a
/// normal vector in tangent space.
/// </summary>
public NormalTextureInfo NormalTexture;
/// <summary>
/// The occlusion map is a greyscale texture, with white indicating areas that
/// should receive full indirect lighting and black indicating no indirect
/// lighting.
/// </summary>
public OcclusionTextureInfo OcclusionTexture;
/// <summary>
/// The emissive map controls the color and intensity of the light being emitted
/// by the material. This texture contains RGB components in sRGB color space.
/// If a fourth component (A) is present, it is ignored.
/// </summary>
public TextureInfo EmissiveTexture;
/// <summary>
/// The RGB components of the emissive color of the material.
/// If an emissiveTexture is specified, this value is multiplied with the texel
/// values.
/// <items>
/// <minimum>0.0</minimum>
/// <maximum>1.0</maximum>
/// </items>
/// <minItems>3</minItems>
/// <maxItems>3</maxItems>
/// </summary>
public Color EmissiveFactor = Color.Clear;
/// <summary>
/// The material's alpha rendering mode enumeration specifying the interpretation of the
/// alpha value of the main factor and texture. In `OPAQUE` mode, the alpha value is
/// ignored and the rendered output is fully opaque. In `MASK` mode, the rendered output
/// is either fully opaque or fully transparent depending on the alpha value and the
/// specified alpha cutoff value. In `BLEND` mode, the alpha value is used to composite
/// the source and destination areas. The rendered output is combined with the background
/// using the normal painting operation (i.e. the Porter and Duff over operator).
/// </summary>
public AlphaMode AlphaMode = AlphaMode.OPAQUE;
/// <summary>
/// Specifies the cutoff threshold when in `MASK` mode. If the alpha value is greater than
/// or equal to this value then it is rendered as fully opaque, otherwise, it is rendered
/// as fully transparent. This value is ignored for other modes.
/// </summary>
public double AlphaCutoff = 0.5;
/// <summary>
/// Specifies whether the material is double sided. When this value is false, back-face
/// culling is enabled. When this value is true, back-face culling is disabled and double
/// sided lighting is enabled. The back-face must have its normals reversed before the
/// lighting equation is evaluated.
/// </summary>
public bool DoubleSided;
public GLTFMaterial()
{
}
public GLTFMaterial(GLTFMaterial material, GLTFRoot gltfRoot) : base(material, gltfRoot)
{
if (material == null) return;
if (material.PbrMetallicRoughness != null)
{
PbrMetallicRoughness = new PbrMetallicRoughness(material.PbrMetallicRoughness, gltfRoot);
}
if (material.CommonConstant != null)
{
CommonConstant = new MaterialCommonConstant(material.CommonConstant, gltfRoot);
}
if (material.NormalTexture != null)
{
NormalTexture = new NormalTextureInfo(material.NormalTexture, gltfRoot);
}
if (material.OcclusionTexture != null)
{
OcclusionTexture = new OcclusionTextureInfo(material.OcclusionTexture, gltfRoot);
}
if (material.EmissiveTexture != null)
{
EmissiveTexture = new TextureInfo(material.EmissiveTexture, gltfRoot);
}
EmissiveFactor = material.EmissiveFactor;
AlphaMode = material.AlphaMode;
AlphaCutoff = material.AlphaCutoff;
DoubleSided = material.DoubleSided;
}
public static GLTFMaterial Deserialize(GLTFRoot root, JsonReader reader)
{
var material = new GLTFMaterial();
while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
{
var curProp = reader.Value.ToString();
switch (curProp)
{
case "pbrMetallicRoughness":
material.PbrMetallicRoughness = PbrMetallicRoughness.Deserialize(root, reader);
break;
case "commonConstant":
material.CommonConstant = MaterialCommonConstant.Deserialize(root, reader);
break;
case "normalTexture":
material.NormalTexture = NormalTextureInfo.Deserialize(root, reader);
break;
case "occlusionTexture":
material.OcclusionTexture = OcclusionTextureInfo.Deserialize(root, reader);
break;
case "emissiveTexture":
material.EmissiveTexture = TextureInfo.Deserialize(root, reader);
break;
case "emissiveFactor":
var emissiveColor = reader.ReadAsRGBColor();
emissiveColor.A = 0;
material.EmissiveFactor = emissiveColor;
break;
case "alphaMode":
material.AlphaMode = reader.ReadStringEnum<AlphaMode>();
break;
case "alphaCutoff":
material.AlphaCutoff = reader.ReadAsDouble().Value;
break;
case "doubleSided":
material.DoubleSided = reader.ReadAsBoolean().Value;
break;
default:
material.DefaultPropertyDeserializer(root, reader);
break;
}
}
return material;
}
public override void Serialize(JsonWriter writer)
{
writer.WriteStartObject();
if (PbrMetallicRoughness != null)
{
writer.WritePropertyName("pbrMetallicRoughness");
PbrMetallicRoughness.Serialize(writer);
}
if (CommonConstant != null)
{
writer.WritePropertyName("commonConstant");
CommonConstant.Serialize(writer);
}
if (NormalTexture != null)
{
writer.WritePropertyName("normalTexture");
NormalTexture.Serialize(writer);
}
if (OcclusionTexture != null)
{
writer.WritePropertyName("occlusionTexture");
OcclusionTexture.Serialize(writer);
}
if (EmissiveTexture != null)
{
writer.WritePropertyName("emissiveTexture");
EmissiveTexture.Serialize(writer);
}
if (EmissiveFactor != Color.Clear && !(EmissiveFactor.R == 0 && EmissiveFactor.G == 0 && EmissiveFactor.B == 0))
{
writer.WritePropertyName("emissiveFactor");
writer.WriteStartArray();
writer.WriteValue(EmissiveFactor.R);
writer.WriteValue(EmissiveFactor.G);
writer.WriteValue(EmissiveFactor.B);
writer.WriteEndArray();
}
if (AlphaMode != AlphaMode.OPAQUE)
{
writer.WritePropertyName("alphaMode");
writer.WriteValue(AlphaMode.ToString());
}
if (AlphaCutoff != 0.5)
{
writer.WritePropertyName("alphaCutoff");
var sanitizedCutoff = AlphaCutoff < 0.0 ? 0.0 : AlphaCutoff > 1.0 ? 1.0 : AlphaCutoff;
writer.WriteValue(sanitizedCutoff);
}
if (DoubleSided)
{
writer.WritePropertyName("doubleSided");
writer.WriteValue(true);
}
base.Serialize(writer);
writer.WriteEndObject();
}
}
public enum AlphaMode
{
OPAQUE,
MASK,
BLEND
}
}