// 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(); } } }