// SPDX-FileCopyrightText: 2023 Unity Technologies and the glTFast authors
// SPDX-License-Identifier: Apache-2.0
using System;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Serialization;
namespace GLTFast.Schema
{
///
[Serializable]
public class Material : MaterialBase<
MaterialExtensions,
NormalTextureInfo,
OcclusionTextureInfo,
PbrMetallicRoughness,
TextureInfo,
TextureInfoExtensions
>
{ }
///
/// Material extensions type
/// normalTextureInfo type
/// occlusionTextureInfo type
/// PBR Metallic Roughness type
/// textureInfo type
/// textureInfo extensions type
[Serializable]
public abstract class MaterialBase<
TExtensions,
TNormalTextureInfo,
TOcclusionTextureInfo,
TPbrMetallicRoughness,
TTextureInfo,
TTextureInfoExtensions
> : MaterialBase
where TExtensions : MaterialExtensions
where TNormalTextureInfo : NormalTextureInfoBase
where TOcclusionTextureInfo : OcclusionTextureInfoBase
where TPbrMetallicRoughness : PbrMetallicRoughnessBase
where TTextureInfo : TextureInfoBase
where TTextureInfoExtensions : TextureInfoExtensions
{
///
public TTextureInfo emissiveTexture;
///
public TExtensions extensions;
///
public TNormalTextureInfo normalTexture;
///
public TOcclusionTextureInfo occlusionTexture;
///
public TPbrMetallicRoughness pbrMetallicRoughness;
///
public override MaterialExtensions Extensions => extensions;
///
internal override void UnsetExtensions()
{
extensions = null;
}
///
public override PbrMetallicRoughnessBase PbrMetallicRoughness => pbrMetallicRoughness;
///
public override NormalTextureInfoBase NormalTexture => normalTexture;
///
public override OcclusionTextureInfoBase OcclusionTexture => occlusionTexture;
///
public override TextureInfoBase EmissiveTexture => emissiveTexture;
}
///
/// The material appearance of a primitive.
///
[Serializable]
public abstract class MaterialBase : NamedObject
{
///
/// The material’s alpha rendering mode enumeration specifying the
/// interpretation of the alpha value of the base color.
///
public enum AlphaMode
{
///
/// The alpha value is ignored, and the rendered output is fully
/// opaque.
///
Opaque,
///
/// The rendered output is either fully opaque or fully transparent
/// depending on the alpha value and the specified alphaCutoff
/// value
///
Mask,
///
/// 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.
///
Blend
}
///
/// Material extensions.
///
public abstract MaterialExtensions Extensions { get; }
///
/// Sets to null.
///
internal abstract void UnsetExtensions();
///
/// A set of parameter values that are used to define the metallic-roughness
/// material model from Physically-Based Rendering (PBR) methodology.
///
public abstract PbrMetallicRoughnessBase PbrMetallicRoughness { get; }
// ///
// /// A set of parameter values used to light flat-shaded materials
// ///
// public MaterialCommonConstant CommonConstant;
///
/// A tangent space normal map. Each texel represents the XYZ components of a
/// normal vector in tangent space.
///
public abstract NormalTextureInfoBase NormalTexture { get; }
///
/// The occlusion map is a greyscale texture, with white indicating areas that
/// should receive full indirect lighting and black indicating no indirect
/// lighting.
///
public abstract OcclusionTextureInfoBase OcclusionTexture { get; }
///
/// 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.
///
public abstract TextureInfoBase EmissiveTexture { get; }
///
/// The RGB components of the emissive color of the material.
/// If an emissiveTexture is specified, this value is multiplied with the texel
/// values.
///
// Field is public for unified serialization only. Warn via Obsolete attribute.
[Obsolete("Use Emissive for access.")]
public float[] emissiveFactor = { 0, 0, 0 };
///
/// Emissive color of the material.
///
public Color Emissive
{
#pragma warning disable CS0618 // Type or member is obsolete
get => new Color(
emissiveFactor[0],
emissiveFactor[1],
emissiveFactor[2]
);
set => emissiveFactor = new[] { value.r, value.g, value.b };
#pragma warning restore CS0618 // Type or member is obsolete
}
///
/// 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).
///
// Field is public for unified serialization only. Warn via Obsolete attribute.
[Obsolete("Use GetAlphaMode and SetAlphaMode for access.")]
public string alphaMode;
AlphaMode? m_AlphaModeEnum;
///
/// typed and cached getter for string.
///
/// Alpha mode if it was retrieved correctly. otherwise
public AlphaMode GetAlphaMode()
{
if (m_AlphaModeEnum.HasValue)
{
return m_AlphaModeEnum.Value;
}
#pragma warning disable CS0618 // Type or member is obsolete
m_AlphaModeEnum = Enum.TryParse(alphaMode, true, out var alphaModeEnum)
? alphaModeEnum
: AlphaMode.Opaque;
alphaMode = null;
#pragma warning restore CS0618 // Type or member is obsolete
return m_AlphaModeEnum.Value;
}
///
/// typed setter for string.
///
/// Alpha mode
public void SetAlphaMode(AlphaMode mode)
{
m_AlphaModeEnum = mode;
#pragma warning disable CS0618 // Type or member is obsolete
alphaMode = null;
#pragma warning restore CS0618 // Type or member is obsolete
}
///
/// 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.
///
public float alphaCutoff = 0.5f;
///
/// 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.
///
public bool doubleSided;
///
/// True if the material requires the mesh to have normals.
///
public bool RequiresNormals => Extensions?.KHR_materials_unlit == null;
///
/// True if the material requires the mesh to have tangents.
///
public bool RequiresTangents => NormalTexture != null && NormalTexture.index >= 0;
internal void GltfSerialize(JsonWriter writer)
{
writer.AddObject();
GltfSerializeName(writer);
if (PbrMetallicRoughness != null)
{
writer.AddProperty("pbrMetallicRoughness");
PbrMetallicRoughness.GltfSerialize(writer);
}
if (NormalTexture != null)
{
writer.AddProperty("normalTexture");
NormalTexture.GltfSerialize(writer);
}
if (OcclusionTexture != null)
{
writer.AddProperty("occlusionTexture");
OcclusionTexture.GltfSerialize(writer);
}
if (EmissiveTexture != null)
{
writer.AddProperty("emissiveTexture");
EmissiveTexture.GltfSerialize(writer);
}
#pragma warning disable CS0618 // Type or member is obsolete
if (emissiveFactor != null
&& (
emissiveFactor[0] > Constants.epsilon
|| emissiveFactor[1] > Constants.epsilon
|| emissiveFactor[2] > Constants.epsilon)
)
{
writer.AddArrayProperty("emissiveFactor", emissiveFactor);
}
#pragma warning restore CS0618 // Type or member is obsolete
if (m_AlphaModeEnum.HasValue && m_AlphaModeEnum.Value != AlphaMode.Opaque)
{
writer.AddProperty("alphaMode", m_AlphaModeEnum.Value.ToString().ToUpperInvariant());
}
if (math.abs(alphaCutoff - .5f) > Constants.epsilon)
{
writer.AddProperty("alphaCutoff", alphaCutoff);
}
if (doubleSided)
{
writer.AddProperty("doubleSided", doubleSided);
}
if (Extensions != null)
{
writer.AddProperty("extensions");
Extensions.GltfSerialize(writer);
}
writer.Close();
}
}
}