using System; namespace UnityEngine.Rendering { /// /// Structure holding Spherical Harmonic L1 coefficient. /// [Serializable] public struct SphericalHarmonicsL1 { /// /// Red channel of each of the three L1 SH coefficient. /// public Vector4 shAr; /// /// Green channel of each of the three L1 SH coefficient. /// public Vector4 shAg; /// /// Blue channel of each of the three L1 SH coefficient. /// public Vector4 shAb; /// /// A set of L1 coefficients initialized to zero. /// public static readonly SphericalHarmonicsL1 zero = new SphericalHarmonicsL1 { shAr = Vector4.zero, shAg = Vector4.zero, shAb = Vector4.zero }; // These operators are implemented so that SphericalHarmonicsL1 matches API of SphericalHarmonicsL2. /// /// Sum two SphericalHarmonicsL1. /// /// First SphericalHarmonicsL1. /// Second SphericalHarmonicsL1. /// The resulting SphericalHarmonicsL1. public static SphericalHarmonicsL1 operator +(SphericalHarmonicsL1 lhs, SphericalHarmonicsL1 rhs) => new SphericalHarmonicsL1() { shAr = lhs.shAr + rhs.shAr, shAg = lhs.shAg + rhs.shAg, shAb = lhs.shAb + rhs.shAb }; /// /// Subtract two SphericalHarmonicsL1. /// /// First SphericalHarmonicsL1. /// Second SphericalHarmonicsL1. /// The resulting SphericalHarmonicsL1. public static SphericalHarmonicsL1 operator -(SphericalHarmonicsL1 lhs, SphericalHarmonicsL1 rhs) => new SphericalHarmonicsL1() { shAr = lhs.shAr - rhs.shAr, shAg = lhs.shAg - rhs.shAg, shAb = lhs.shAb - rhs.shAb }; /// /// Multiply two SphericalHarmonicsL1. /// /// First SphericalHarmonicsL1. /// Second SphericalHarmonicsL1. /// The resulting SphericalHarmonicsL1. public static SphericalHarmonicsL1 operator *(SphericalHarmonicsL1 lhs, float rhs) => new SphericalHarmonicsL1() { shAr = lhs.shAr * rhs, shAg = lhs.shAg * rhs, shAb = lhs.shAb * rhs }; /// /// Divide two SphericalHarmonicsL1. /// /// First SphericalHarmonicsL1. /// Second SphericalHarmonicsL1. /// The resulting SphericalHarmonicsL1. public static SphericalHarmonicsL1 operator /(SphericalHarmonicsL1 lhs, float rhs) => new SphericalHarmonicsL1() { shAr = lhs.shAr / rhs, shAg = lhs.shAg / rhs, shAb = lhs.shAb / rhs }; /// /// Compare two SphericalHarmonicsL1. /// /// First SphericalHarmonicsL1. /// Second SphericalHarmonicsL1. /// Whether the SphericalHarmonicsL1 match. public static bool operator ==(SphericalHarmonicsL1 lhs, SphericalHarmonicsL1 rhs) { return lhs.shAr == rhs.shAr && lhs.shAg == rhs.shAg && lhs.shAb == rhs.shAb; } /// /// Check two SphericalHarmonicsL1 inequality. /// /// First SphericalHarmonicsL1. /// Second SphericalHarmonicsL1. /// Whether the SphericalHarmonicsL1 are different. public static bool operator !=(SphericalHarmonicsL1 lhs, SphericalHarmonicsL1 rhs) { return !(lhs == rhs); } /// /// Compare this SphericalHarmonicsL1 with an object. /// /// The object to compare with. /// Whether the SphericalHarmonicsL1 is equal to the object passed. public override bool Equals(object other) { if (!(other is SphericalHarmonicsL1)) return false; return this == (SphericalHarmonicsL1)other; } /// /// Produces an hash code of the SphericalHarmonicsL1. /// /// The hash code for this SphericalHarmonicsL1. public override int GetHashCode() { return ((17 * 23 + shAr.GetHashCode()) * 23 + shAg.GetHashCode()) * 23 + shAb.GetHashCode(); } } /// /// A collection of utility functions used to access and set SphericalHarmonicsL2 in a more verbose way. /// public class SphericalHarmonicsL2Utils { /// /// Returns the L1 coefficients organized in such a way that are swizzled per channel rather than per coefficient. /// /// The SphericalHarmonicsL2 data structure to use to query the information. /// The red channel of all coefficient for the L1 band. /// The green channel of all coefficient for the L1 band. /// The blue channel of all coefficient for the L1 band. public static void GetL1(SphericalHarmonicsL2 sh, out Vector3 L1_R, out Vector3 L1_G, out Vector3 L1_B) { L1_R = new Vector3(sh[0, 1], sh[0, 2], sh[0, 3]); L1_G = new Vector3(sh[1, 1], sh[1, 2], sh[1, 3]); L1_B = new Vector3(sh[2, 1], sh[2, 2], sh[2, 3]); } /// /// Returns all the L2 coefficients. /// /// The SphericalHarmonicsL2 data structure to use to query the information. /// The first coefficient for the L2 band. /// The second coefficient for the L2 band. /// The third coefficient for the L2 band. /// The fourth coefficient for the L2 band. /// The fifth coefficient for the L2 band. public static void GetL2(SphericalHarmonicsL2 sh, out Vector3 L2_0, out Vector3 L2_1, out Vector3 L2_2, out Vector3 L2_3, out Vector3 L2_4) { L2_0 = new Vector3(sh[0, 4], sh[1, 4], sh[2, 4]); L2_1 = new Vector3(sh[0, 5], sh[1, 5], sh[2, 5]); L2_2 = new Vector3(sh[0, 6], sh[1, 6], sh[2, 6]); L2_3 = new Vector3(sh[0, 7], sh[1, 7], sh[2, 7]); L2_4 = new Vector3(sh[0, 8], sh[1, 8], sh[2, 8]); } /// /// Set L0 coefficient. /// /// The SphericalHarmonicsL2 data structure to store information on. /// The L0 coefficient to set. public static void SetL0(ref SphericalHarmonicsL2 sh, Vector3 L0) { sh[0, 0] = L0.x; sh[1, 0] = L0.y; sh[2, 0] = L0.z; } /// /// Set the red channel for each of the L1 coefficients. /// /// The SphericalHarmonicsL2 data structure to store information on. /// The red channels for each L1 coefficient. public static void SetL1R(ref SphericalHarmonicsL2 sh, Vector3 L1_R) { sh[0, 1] = L1_R.x; sh[0, 2] = L1_R.y; sh[0, 3] = L1_R.z; } /// /// Set the green channel for each of the L1 coefficients. /// /// The SphericalHarmonicsL2 data structure to store information on. /// The green channels for each L1 coefficient. public static void SetL1G(ref SphericalHarmonicsL2 sh, Vector3 L1_G) { sh[1, 1] = L1_G.x; sh[1, 2] = L1_G.y; sh[1, 3] = L1_G.z; } /// /// Set the blue channel for each of the L1 coefficients. /// /// The SphericalHarmonicsL2 data structure to store information on. /// The blue channels for each L1 coefficient. public static void SetL1B(ref SphericalHarmonicsL2 sh, Vector3 L1_B) { sh[2, 1] = L1_B.x; sh[2, 2] = L1_B.y; sh[2, 3] = L1_B.z; } /// /// Set all L1 coefficients per channel. /// /// The SphericalHarmonicsL2 data structure to store information on. /// The red channels for each L1 coefficient. /// The green channels for each L1 coefficient. /// The blue channels for each L1 coefficient. public static void SetL1(ref SphericalHarmonicsL2 sh, Vector3 L1_R, Vector3 L1_G, Vector3 L1_B) { SetL1R(ref sh, L1_R); SetL1G(ref sh, L1_G); SetL1B(ref sh, L1_B); } /// /// Set a spherical harmonics coefficient. /// /// The SphericalHarmonicsL2 data structure to store information on. /// The index of the coefficient that is set (must be less than 9). /// The values of the coefficient is set. public static void SetCoefficient(ref SphericalHarmonicsL2 sh, int index, Vector3 coefficient) { Debug.Assert(index < 9); sh[0, index] = coefficient.x; sh[1, index] = coefficient.y; sh[2, index] = coefficient.z; } /// /// Get a spherical harmonics coefficient. /// /// The SphericalHarmonicsL2 data structure to get information from. /// The index of the coefficient that is requested (must be less than 9). /// The value of the requested coefficient. public static Vector3 GetCoefficient(SphericalHarmonicsL2 sh, int index) { Debug.Assert(index < 9); return new Vector3(sh[0, index], sh[1, index], sh[2, index]); } } }