using System;
namespace UnityEngine.Rendering.PostProcessing
{
///
/// The base abstract class for all parameter override types.
///
///
public abstract class ParameterOverride
{
///
/// The override state of this parameter.
///
public bool overrideState;
internal abstract void Interp(ParameterOverride from, ParameterOverride to, float t);
///
/// Returns the computed hash code for this parameter.
///
/// A computed hash code
public abstract int GetHash();
///
/// Casts and returns the value stored in this parameter.
///
/// The type to cast to
/// The value stored in this parameter
public T GetValue()
{
return ((ParameterOverride)this).value;
}
///
/// This method is called right after the parent has
/// been initialized. This is used in case you need to access fields or properties that
/// can't be accessed in the constructor of a
/// (ParameterOverride objects are generally declared and initialized in a
/// ).
///
///
protected internal virtual void OnEnable()
{
}
///
/// This method is called right before the parent
/// gets de-initialized.
///
///
protected internal virtual void OnDisable()
{
}
internal abstract void SetValue(ParameterOverride parameter);
}
///
/// The base typed class for all parameter override types.
///
/// The type of value to store in this ParameterOverride
///
/// Due to limitations with the serialization system in Unity you shouldn't use this class
/// directly. Use one of the pre-flatten types (like or make your
/// own by extending this class.
///
///
/// This sample code shows how to make a custom parameter holding a float.
///
/// [Serializable]
/// public sealed class FloatParameter : ParameterOverride<float>
/// {
/// public override void Interp(float from, float to, float t)
/// {
/// value = from + (to - from) * t;
/// }
/// }
///
///
[Serializable]
public class ParameterOverride : ParameterOverride
{
///
/// The value stored in this parameter.
///
public T value;
///
/// Creates a ParameterOverride with a default and
/// set to false.
///
public ParameterOverride()
: this(default(T), false)
{
}
///
/// Creates a ParameterOverride with a given value and
/// set to false.
///
/// The value to set this parameter to
public ParameterOverride(T value)
: this(value, false)
{
}
///
/// Creates a ParameterOverride with a given value and override state.
///
/// The value to set this parameter to
/// The override state for this value
public ParameterOverride(T value, bool overrideState)
{
this.value = value;
this.overrideState = overrideState;
}
internal override void Interp(ParameterOverride from, ParameterOverride to, float t)
{
// Note: this isn't completely safe but it'll do fine
Interp(from.GetValue(), to.GetValue(), t);
}
///
/// Interpolates between two values given an interpolation factor .
///
/// The value to interpolate from
/// The value to interpolate to
/// An interpolation factor (generally in range [0,1])
///
/// By default this method does a "snap" interpolation, meaning it will return the value
/// if is higher than 0,
/// otherwise.
///
public virtual void Interp(T from, T to, float t)
{
// Returns `to` if `dt > 0` by default so we don't have to write overrides for bools and
// enumerations.
value = t > 0f ? to : from;
}
///
/// Sets the value for this parameter to and mark the override state
/// to true.
///
///
public void Override(T x)
{
overrideState = true;
value = x;
}
internal override void SetValue(ParameterOverride parameter)
{
value = parameter.GetValue();
}
///
/// Returns the computed hash code for this parameter.
///
/// A computed hash code
public override int GetHash()
{
unchecked
{
int hash = 17;
hash = hash * 23 + overrideState.GetHashCode();
hash = hash * 23 + value.GetHashCode();
return hash;
}
}
///
/// Implicit conversion between and its value type.
///
/// The parameter to implicitly cast
/// A value of type .
public static implicit operator T(ParameterOverride prop)
{
return prop.value;
}
}
// Bypassing the limited unity serialization system...
///
/// A that holds a float value.
///
///
/// The interpolation method for this parameter is the same as .
///
[Serializable]
public sealed class FloatParameter : ParameterOverride
{
///
/// Interpolates between two values given an interpolation factor .
///
/// The value to interpolate from
/// The value to interpolate to
/// An interpolation factor (generally in range [0,1])
///
/// By default this method does a "snap" interpolation, meaning it will return the value
/// if is higher than 0,
/// otherwise.
///
public override void Interp(float from, float to, float t)
{
value = from + (to - from) * t;
}
}
///
/// A that holds a int value.
///
///
/// The interpolation method for this parameter is the same as
/// casted to int.
///
[Serializable]
public sealed class IntParameter : ParameterOverride
{
///
/// Interpolates between two values given an interpolation factor .
///
/// The value to interpolate from
/// The value to interpolate to
/// An interpolation factor (generally in range [0,1])
///
/// By default this method does a "snap" interpolation, meaning it will return the value
/// if is higher than 0,
/// otherwise.
///
public override void Interp(int from, int to, float t)
{
// Int snapping interpolation. Don't use this for enums as they don't necessarily have
// contiguous values. Use the default interpolator instead (same as bool).
value = (int)(from + (to - from) * t);
}
}
///
/// A that holds a bool value.
///
[Serializable]
public sealed class BoolParameter : ParameterOverride { }
///
/// A that holds a value.
///
///
/// The interpolation method for this parameter is the same as
/// for each channel.
///
[Serializable]
public sealed class ColorParameter : ParameterOverride
{
///
/// Interpolates between two values given an interpolation factor .
///
/// The value to interpolate from
/// The value to interpolate to
/// An interpolation factor (generally in range [0,1])
///
/// By default this method does a "snap" interpolation, meaning it will return the value
/// if is higher than 0,
/// otherwise.
///
public override void Interp(Color from, Color to, float t)
{
// Lerping color values is a sensitive subject... We looked into lerping colors using
// HSV and LCH but they have some downsides that make them not work correctly in all
// situations, so we stick with RGB lerping for now, at least its behavior is
// predictable despite looking desaturated when `t ~= 0.5` and it's faster anyway.
value.r = from.r + (to.r - from.r) * t;
value.g = from.g + (to.g - from.g) * t;
value.b = from.b + (to.b - from.b) * t;
value.a = from.a + (to.a - from.a) * t;
}
///
/// Implicit conversion between and a .
///
/// The parameter to implicitly cast
/// A Vector4.
public static implicit operator Vector4(ColorParameter prop)
{
return prop.value;
}
}
///
/// A that holds a value.
///
///
/// The interpolation method for this parameter is the same as
/// for each axis.
///
[Serializable]
public sealed class Vector2Parameter : ParameterOverride
{
///
/// Interpolates between two values given an interpolation factor .
///
/// The value to interpolate from
/// The value to interpolate to
/// An interpolation factor (generally in range [0,1])
///
/// By default this method does a "snap" interpolation, meaning it will return the value
/// if is higher than 0,
/// otherwise.
///
public override void Interp(Vector2 from, Vector2 to, float t)
{
value.x = from.x + (to.x - from.x) * t;
value.y = from.y + (to.y - from.y) * t;
}
///
/// Implicit conversion between and a .
///
/// The parameter to implicitly cast
/// A Vector3.
public static implicit operator Vector3(Vector2Parameter prop)
{
return prop.value;
}
///
/// Implicit conversion between and a .
///
/// The parameter to implicitly cast
/// A Vector4.
public static implicit operator Vector4(Vector2Parameter prop)
{
return prop.value;
}
}
///
/// A that holds a value.
///
///
/// The interpolation method for this parameter is the same as
/// for each axis.
///
[Serializable]
public sealed class Vector3Parameter : ParameterOverride
{
///
/// Interpolates between two values given an interpolation factor .
///
/// The value to interpolate from
/// The value to interpolate to
/// An interpolation factor (generally in range [0,1])
///
/// By default this method does a "snap" interpolation, meaning it will return the value
/// if is higher than 0,
/// otherwise.
///
public override void Interp(Vector3 from, Vector3 to, float t)
{
value.x = from.x + (to.x - from.x) * t;
value.y = from.y + (to.y - from.y) * t;
value.z = from.z + (to.z - from.z) * t;
}
///
/// Implicit conversion between and a .
///
/// The parameter to implicitly cast
/// A Vector2.
public static implicit operator Vector2(Vector3Parameter prop)
{
return prop.value;
}
///
/// Implicit conversion between and a .
///
/// The parameter to implicitly cast
/// A Vector4.
public static implicit operator Vector4(Vector3Parameter prop)
{
return prop.value;
}
}
///
/// A that holds a value.
///
///
/// The interpolation method for this parameter is the same as
/// for each axis.
///
[Serializable]
public sealed class Vector4Parameter : ParameterOverride
{
///
/// Interpolates between two values given an interpolation factor .
///
/// The value to interpolate from
/// The value to interpolate to
/// An interpolation factor (generally in range [0,1])
///
/// By default this method does a "snap" interpolation, meaning it will return the value
/// if is higher than 0,
/// otherwise.
///
public override void Interp(Vector4 from, Vector4 to, float t)
{
value.x = from.x + (to.x - from.x) * t;
value.y = from.y + (to.y - from.y) * t;
value.z = from.z + (to.z - from.z) * t;
value.w = from.w + (to.w - from.w) * t;
}
///
/// Implicit conversion between and a .
///
/// The parameter to implicitly cast
/// A Vector2.
public static implicit operator Vector2(Vector4Parameter prop)
{
return prop.value;
}
///
/// Implicit conversion between and a .
///
/// The parameter to implicitly cast
/// A Vector3.
public static implicit operator Vector3(Vector4Parameter prop)
{
return prop.value;
}
}
///
/// A that holds a value.
///
///
/// The interpolation method for this parameter is the same as
/// for each point on the curve.
///
[Serializable]
public sealed class SplineParameter : ParameterOverride
{
///
/// This method is called right after the parent has
/// been initialized. This is used in case you need to access fields or properties that
/// can't be accessed in the constructor of a
/// (ParameterOverride objects are generally declared and initialized in a
/// ).
///
///
protected internal override void OnEnable()
{
if (value != null)
value.Cache(int.MinValue);
}
internal override void SetValue(ParameterOverride parameter)
{
base.SetValue(parameter);
if (value != null)
value.Cache(Time.renderedFrameCount);
}
///
/// Interpolates between two values given an interpolation factor .
///
/// The value to interpolate from
/// The value to interpolate to
/// An interpolation factor (generally in range [0,1])
///
/// By default this method does a "snap" interpolation, meaning it will return the value
/// if is higher than 0,
/// otherwise.
///
public override void Interp(Spline from, Spline to, float t)
{
if (from == null || to == null)
{
base.Interp(from, to, t);
return;
}
int frameCount = Time.renderedFrameCount;
from.Cache(frameCount);
to.Cache(frameCount);
for (int i = 0; i < Spline.k_Precision; i++)
{
float a = from.cachedData[i];
float b = to.cachedData[i];
value.cachedData[i] = a + (b - a) * t;
}
}
}
///
/// A set of default textures to use as default values for .
///
public enum TextureParameterDefault
{
///
/// No texture, or null.
///
None,
///
/// A black texture.
///
Black,
///
/// A white texture.
///
White,
///
/// A transparent texture.
///
Transparent,
///
/// A 2D lookup table in strip format with width = height * height.
///
Lut2D
}
///
/// A that holds a value.
///
///
/// Texture interpolation is done using a classic linear interpolation method.
///
[Serializable]
public sealed class TextureParameter : ParameterOverride
{
/// The default state & type for the texture.
public TextureParameterDefault defaultState = TextureParameterDefault.Black;
///
/// Interpolates between two values given an interpolation factor .
///
/// The value to interpolate from
/// The value to interpolate to
/// An interpolation factor (generally in range [0,1])
///
/// By default this method does a "snap" interpolation, meaning it will return the value
/// if is higher than 0,
/// otherwise.
///
public override void Interp(Texture from, Texture to, float t)
{
// Both are null, do nothing
if (from == null && to == null)
{
value = null;
return;
}
// Both aren't null we're ready to blend
if (from != null && to != null)
{
value = TextureLerper.instance.Lerp(from, to, t);
return;
}
// One of them is null, blend to/from a default value is applicable
{
if (defaultState == TextureParameterDefault.Lut2D)
{
int size = from != null ? from.height : to.height;
Texture defaultTexture = RuntimeUtilities.GetLutStrip(size);
if (from == null) from = defaultTexture;
if (to == null) to = defaultTexture;
}
Color tgtColor;
switch (defaultState)
{
case TextureParameterDefault.Black:
tgtColor = Color.black;
break;
case TextureParameterDefault.White:
tgtColor = Color.white;
break;
case TextureParameterDefault.Transparent:
tgtColor = Color.clear;
break;
case TextureParameterDefault.Lut2D:
{
// Find the current lut size
int size = from != null ? from.height : to.height;
Texture defaultTexture = RuntimeUtilities.GetLutStrip(size);
if (from == null) from = defaultTexture;
if (to == null) to = defaultTexture;
// Fail safe in case the lut size is incorrect
if (from.width != to.width || from.height != to.height)
{
value = null;
return;
}
value = TextureLerper.instance.Lerp(from, to, t);
// All done, return
return;
}
default:
// defaultState is none, so just interpolate the base and return
base.Interp(from, to, t);
return;
}
// If we made it this far, tgtColor contains the color we'll be lerping into (or out of)
if (from == null)
{
// color -> texture lerp, invert ratio
value = TextureLerper.instance.Lerp(to, tgtColor, 1f - t);
}
else
{
value = TextureLerper.instance.Lerp(from, tgtColor, t);
}
}
}
}
}