// SPDX-FileCopyrightText: 2023 Unity Technologies and the glTFast authors
// SPDX-License-Identifier: Apache-2.0
using System;
using UnityEngine;
namespace GLTFast.Schema
{
///
/// Texture sampler properties for filtering and wrapping modes.
///
[Serializable]
public class Sampler : NamedObject
{
///
/// Magnification filter mode.
///
public enum MagFilterMode
{
/// No value
None = 0,
/// Nearest pixel sampling
Nearest = 9728,
/// Linear pixel interpolation sampling
Linear = 9729,
}
///
/// Minification filter mode.
///
public enum MinFilterMode
{
/// No value
None = 0,
/// Nearest pixel sampling
Nearest = 9728,
/// Linear pixel interpolation sampling
Linear = 9729,
/// Nearest pixel and nearest mipmap sampling
NearestMipmapNearest = 9984,
/// Linear pixel interpolation and nearest mipmap sampling
LinearMipmapNearest = 9985,
/// Nearest pixel and linear mipmap interpolation sampling
NearestMipmapLinear = 9986,
/// Linear pixel interpolation and linear mipmap interpolation sampling
LinearMipmapLinear = 9987
}
///
/// Texture wrap mode.
///
public enum WrapMode
{
/// No value
None = 0,
/// Clamp to edge
ClampToEdge = 33071,
/// Mirrored repeat
MirroredRepeat = 33648,
/// Repeat
Repeat = 10497
}
///
/// Magnification filter.
/// Valid values correspond to WebGL enums: `9728` (NEAREST) and `9729` (LINEAR).
///
public MagFilterMode magFilter = MagFilterMode.None;
///
/// Minification filter. All valid values correspond to WebGL enums.
///
public MinFilterMode minFilter = MinFilterMode.None;
///
/// s wrapping mode. All valid values correspond to WebGL enums.
///
public WrapMode wrapS = WrapMode.Repeat;
///
/// t wrapping mode. All valid values correspond to WebGL enums.
///
public WrapMode wrapT = WrapMode.Repeat;
///
/// Unity filter mode, derived from glTF's
/// and .
///
public FilterMode FilterMode => ConvertFilterMode(minFilter, magFilter);
///
/// Unity texture wrap mode (horizontal), derived from glTF's
/// value.
///
public TextureWrapMode WrapU => ConvertWrapMode(wrapS);
///
/// Unity texture wrap mode (vertical), derived from glTF's
/// value.
///
public TextureWrapMode WrapV => ConvertWrapMode(wrapT);
static FilterMode ConvertFilterMode(MinFilterMode minFilterToConvert, MagFilterMode magFilterToConvert)
{
switch (minFilterToConvert)
{
case MinFilterMode.LinearMipmapLinear:
return FilterMode.Trilinear;
case MinFilterMode.Nearest:
case MinFilterMode.NearestMipmapNearest:
case MinFilterMode.NearestMipmapLinear: // incorrect mip-map filtering in this case!
return FilterMode.Point;
}
switch (magFilterToConvert)
{
case MagFilterMode.Nearest:
return FilterMode.Point;
default:
return FilterMode.Bilinear;
}
}
static TextureWrapMode ConvertWrapMode(WrapMode wrapMode)
{
switch (wrapMode)
{
case WrapMode.None:
case WrapMode.Repeat:
default:
return TextureWrapMode.Repeat;
case WrapMode.ClampToEdge:
return TextureWrapMode.Clamp;
case WrapMode.MirroredRepeat:
return TextureWrapMode.Mirror;
}
}
static WrapMode ConvertWrapMode(TextureWrapMode wrapMode)
{
switch (wrapMode)
{
case TextureWrapMode.Clamp:
return WrapMode.ClampToEdge;
case TextureWrapMode.Mirror:
case TextureWrapMode.MirrorOnce:
return WrapMode.MirroredRepeat;
case TextureWrapMode.Repeat:
default:
return WrapMode.Repeat;
}
}
///
/// Parameter-less constructor
///
public Sampler() { }
///
/// Constructs a Sampler with filter and wrap modes.
///
/// Unity texture filter mode
/// Unity texture wrap mode (horizontal)
/// Unity texture wrap mode (vertical)
public Sampler(FilterMode filterMode, TextureWrapMode wrapModeU, TextureWrapMode wrapModeV)
{
switch (filterMode)
{
case FilterMode.Point:
magFilter = MagFilterMode.Nearest;
minFilter = MinFilterMode.Nearest;
break;
case FilterMode.Bilinear:
magFilter = MagFilterMode.Linear;
minFilter = MinFilterMode.Linear;
break;
case FilterMode.Trilinear:
magFilter = MagFilterMode.Linear;
minFilter = MinFilterMode.LinearMipmapLinear;
break;
}
wrapS = ConvertWrapMode(wrapModeU);
wrapT = ConvertWrapMode(wrapModeV);
}
///
/// Applies the Sampler's settings to a Unity texture.
///
/// Texture to apply the settings to
/// Fallback minification filter
/// Fallback magnification filter
public void Apply(Texture2D image,
MinFilterMode defaultMinFilter = MinFilterMode.Linear,
MagFilterMode defaultMagFilter = MagFilterMode.Linear)
{
if (image == null) return;
image.wrapModeU = WrapU;
image.wrapModeV = WrapV;
// Use the default filtering mode for textures that have no such specification in data
image.filterMode = ConvertFilterMode(
minFilter == MinFilterMode.None ? defaultMinFilter : minFilter,
magFilter == MagFilterMode.None ? defaultMagFilter : magFilter
);
}
internal void GltfSerialize(JsonWriter writer)
{
writer.AddObject();
GltfSerializeName(writer);
// Assuming MagFilterMode.Linear is the project's default, only
// serialize valid, non-default values
if (magFilter == MagFilterMode.Nearest)
{
writer.AddProperty("magFilter", (int)magFilter);
}
// Assuming MinFilterMode.Linear is the project's default, only
// serialize valid, non-default values
if (minFilter != MinFilterMode.None && minFilter != MinFilterMode.Linear)
{
writer.AddProperty("minFilter", (int)minFilter);
}
if (wrapS != WrapMode.None && wrapS != WrapMode.Repeat)
{
writer.AddProperty("wrapS", (int)wrapS);
}
if (wrapT != WrapMode.None && wrapT != WrapMode.Repeat)
{
writer.AddProperty("wrapT", (int)wrapT);
}
writer.Close();
}
}
}