A game about forced loneliness, made by TACStudios
1using System;
2
3namespace UnityEngine.Rendering
4{
5 /// <summary>
6 /// Structure holding Spherical Harmonic L1 coefficient.
7 /// </summary>
8 [Serializable]
9 public struct SphericalHarmonicsL1
10 {
11 /// <summary>
12 /// Red channel of each of the three L1 SH coefficient.
13 /// </summary>
14 public Vector4 shAr;
15 /// <summary>
16 /// Green channel of each of the three L1 SH coefficient.
17 /// </summary>
18 public Vector4 shAg;
19 /// <summary>
20 /// Blue channel of each of the three L1 SH coefficient.
21 /// </summary>
22 public Vector4 shAb;
23
24 /// <summary>
25 /// A set of L1 coefficients initialized to zero.
26 /// </summary>
27 public static readonly SphericalHarmonicsL1 zero = new SphericalHarmonicsL1
28 {
29 shAr = Vector4.zero,
30 shAg = Vector4.zero,
31 shAb = Vector4.zero
32 };
33
34 // These operators are implemented so that SphericalHarmonicsL1 matches API of SphericalHarmonicsL2.
35
36 /// <summary>
37 /// Sum two SphericalHarmonicsL1.
38 /// </summary>
39 /// <param name="lhs">First SphericalHarmonicsL1.</param>
40 /// <param name="rhs">Second SphericalHarmonicsL1.</param>
41 /// <returns>The resulting SphericalHarmonicsL1.</returns>
42 public static SphericalHarmonicsL1 operator +(SphericalHarmonicsL1 lhs, SphericalHarmonicsL1 rhs) => new SphericalHarmonicsL1()
43 {
44 shAr = lhs.shAr + rhs.shAr,
45 shAg = lhs.shAg + rhs.shAg,
46 shAb = lhs.shAb + rhs.shAb
47 };
48
49 /// <summary>
50 /// Subtract two SphericalHarmonicsL1.
51 /// </summary>
52 /// <param name="lhs">First SphericalHarmonicsL1.</param>
53 /// <param name="rhs">Second SphericalHarmonicsL1.</param>
54 /// <returns>The resulting SphericalHarmonicsL1.</returns>
55 public static SphericalHarmonicsL1 operator -(SphericalHarmonicsL1 lhs, SphericalHarmonicsL1 rhs) => new SphericalHarmonicsL1()
56 {
57 shAr = lhs.shAr - rhs.shAr,
58 shAg = lhs.shAg - rhs.shAg,
59 shAb = lhs.shAb - rhs.shAb
60 };
61
62 /// <summary>
63 /// Multiply two SphericalHarmonicsL1.
64 /// </summary>
65 /// <param name="lhs">First SphericalHarmonicsL1.</param>
66 /// <param name="rhs">Second SphericalHarmonicsL1.</param>
67 /// <returns>The resulting SphericalHarmonicsL1.</returns>
68 public static SphericalHarmonicsL1 operator *(SphericalHarmonicsL1 lhs, float rhs) => new SphericalHarmonicsL1()
69 {
70 shAr = lhs.shAr * rhs,
71 shAg = lhs.shAg * rhs,
72 shAb = lhs.shAb * rhs
73 };
74
75 /// <summary>
76 /// Divide two SphericalHarmonicsL1.
77 /// </summary>
78 /// <param name="lhs">First SphericalHarmonicsL1.</param>
79 /// <param name="rhs">Second SphericalHarmonicsL1.</param>
80 /// <returns>The resulting SphericalHarmonicsL1.</returns>
81 public static SphericalHarmonicsL1 operator /(SphericalHarmonicsL1 lhs, float rhs) => new SphericalHarmonicsL1()
82 {
83 shAr = lhs.shAr / rhs,
84 shAg = lhs.shAg / rhs,
85 shAb = lhs.shAb / rhs
86 };
87
88 /// <summary>
89 /// Compare two SphericalHarmonicsL1.
90 /// </summary>
91 /// <param name="lhs">First SphericalHarmonicsL1.</param>
92 /// <param name="rhs">Second SphericalHarmonicsL1.</param>
93 /// <returns>Whether the SphericalHarmonicsL1 match.</returns>
94 public static bool operator ==(SphericalHarmonicsL1 lhs, SphericalHarmonicsL1 rhs)
95 {
96 return lhs.shAr == rhs.shAr
97 && lhs.shAg == rhs.shAg
98 && lhs.shAb == rhs.shAb;
99 }
100
101 /// <summary>
102 /// Check two SphericalHarmonicsL1 inequality.
103 /// </summary>
104 /// <param name="lhs">First SphericalHarmonicsL1.</param>
105 /// <param name="rhs">Second SphericalHarmonicsL1.</param>
106 /// <returns>Whether the SphericalHarmonicsL1 are different.</returns>
107 public static bool operator !=(SphericalHarmonicsL1 lhs, SphericalHarmonicsL1 rhs)
108 {
109 return !(lhs == rhs);
110 }
111
112 /// <summary>
113 /// Compare this SphericalHarmonicsL1 with an object.
114 /// </summary>
115 /// <param name="other">The object to compare with.</param>
116 /// <returns>Whether the SphericalHarmonicsL1 is equal to the object passed.</returns>
117 public override bool Equals(object other)
118 {
119 if (!(other is SphericalHarmonicsL1)) return false;
120 return this == (SphericalHarmonicsL1)other;
121 }
122
123 /// <summary>
124 /// Produces an hash code of the SphericalHarmonicsL1.
125 /// </summary>
126 /// <returns>The hash code for this SphericalHarmonicsL1.</returns>
127 public override int GetHashCode()
128 {
129 return ((17 * 23 + shAr.GetHashCode()) * 23 + shAg.GetHashCode()) * 23 + shAb.GetHashCode();
130 }
131 }
132
133 /// <summary>
134 /// A collection of utility functions used to access and set SphericalHarmonicsL2 in a more verbose way.
135 /// </summary>
136 public class SphericalHarmonicsL2Utils
137 {
138 /// <summary>
139 /// Returns the L1 coefficients organized in such a way that are swizzled per channel rather than per coefficient.
140 /// </summary>
141 /// <param name ="sh"> The SphericalHarmonicsL2 data structure to use to query the information.</param>
142 /// <param name ="L1_R">The red channel of all coefficient for the L1 band.</param>
143 /// <param name ="L1_G">The green channel of all coefficient for the L1 band.</param>
144 /// <param name ="L1_B">The blue channel of all coefficient for the L1 band.</param>
145 public static void GetL1(SphericalHarmonicsL2 sh, out Vector3 L1_R, out Vector3 L1_G, out Vector3 L1_B)
146 {
147 L1_R = new Vector3(sh[0, 1],
148 sh[0, 2],
149 sh[0, 3]);
150
151 L1_G = new Vector3(sh[1, 1],
152 sh[1, 2],
153 sh[1, 3]);
154
155 L1_B = new Vector3(sh[2, 1],
156 sh[2, 2],
157 sh[2, 3]);
158 }
159
160 /// <summary>
161 /// Returns all the L2 coefficients.
162 /// </summary>
163 /// <param name ="sh"> The SphericalHarmonicsL2 data structure to use to query the information.</param>
164 /// <param name ="L2_0">The first coefficient for the L2 band.</param>
165 /// <param name ="L2_1">The second coefficient for the L2 band.</param>
166 /// <param name ="L2_2">The third coefficient for the L2 band.</param>
167 /// <param name ="L2_3">The fourth coefficient for the L2 band.</param>
168 /// <param name ="L2_4">The fifth coefficient for the L2 band.</param>
169 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)
170 {
171 L2_0 = new Vector3(sh[0, 4],
172 sh[1, 4],
173 sh[2, 4]);
174
175 L2_1 = new Vector3(sh[0, 5],
176 sh[1, 5],
177 sh[2, 5]);
178
179 L2_2 = new Vector3(sh[0, 6],
180 sh[1, 6],
181 sh[2, 6]);
182
183 L2_3 = new Vector3(sh[0, 7],
184 sh[1, 7],
185 sh[2, 7]);
186
187 L2_4 = new Vector3(sh[0, 8],
188 sh[1, 8],
189 sh[2, 8]);
190 }
191
192 /// <summary>
193 /// Set L0 coefficient.
194 /// </summary>
195 /// <param name ="sh">The SphericalHarmonicsL2 data structure to store information on.</param>
196 /// <param name ="L0">The L0 coefficient to set.</param>
197 public static void SetL0(ref SphericalHarmonicsL2 sh, Vector3 L0)
198 {
199 sh[0, 0] = L0.x;
200 sh[1, 0] = L0.y;
201 sh[2, 0] = L0.z;
202 }
203
204 /// <summary>
205 /// Set the red channel for each of the L1 coefficients.
206 /// </summary>
207 /// <param name ="sh">The SphericalHarmonicsL2 data structure to store information on.</param>
208 /// <param name ="L1_R">The red channels for each L1 coefficient.</param>
209 public static void SetL1R(ref SphericalHarmonicsL2 sh, Vector3 L1_R)
210 {
211 sh[0, 1] = L1_R.x;
212 sh[0, 2] = L1_R.y;
213 sh[0, 3] = L1_R.z;
214 }
215
216 /// <summary>
217 /// Set the green channel for each of the L1 coefficients.
218 /// </summary>
219 /// <param name ="sh">The SphericalHarmonicsL2 data structure to store information on.</param>
220 /// <param name ="L1_G">The green channels for each L1 coefficient.</param>
221 public static void SetL1G(ref SphericalHarmonicsL2 sh, Vector3 L1_G)
222 {
223 sh[1, 1] = L1_G.x;
224 sh[1, 2] = L1_G.y;
225 sh[1, 3] = L1_G.z;
226 }
227
228 /// <summary>
229 /// Set the blue channel for each of the L1 coefficients.
230 /// </summary>
231 /// <param name ="sh">The SphericalHarmonicsL2 data structure to store information on.</param>
232 /// <param name ="L1_B">The blue channels for each L1 coefficient.</param>
233 public static void SetL1B(ref SphericalHarmonicsL2 sh, Vector3 L1_B)
234 {
235 sh[2, 1] = L1_B.x;
236 sh[2, 2] = L1_B.y;
237 sh[2, 3] = L1_B.z;
238 }
239
240 /// <summary>
241 /// Set all L1 coefficients per channel.
242 /// </summary>
243 /// <param name ="sh">The SphericalHarmonicsL2 data structure to store information on.</param>
244 /// <param name ="L1_R">The red channels for each L1 coefficient.</param>
245 /// <param name ="L1_G">The green channels for each L1 coefficient.</param>
246 /// <param name ="L1_B">The blue channels for each L1 coefficient.</param>
247 public static void SetL1(ref SphericalHarmonicsL2 sh, Vector3 L1_R, Vector3 L1_G, Vector3 L1_B)
248 {
249 SetL1R(ref sh, L1_R);
250 SetL1G(ref sh, L1_G);
251 SetL1B(ref sh, L1_B);
252 }
253
254 /// <summary>
255 /// Set a spherical harmonics coefficient.
256 /// </summary>
257 /// <param name ="sh">The SphericalHarmonicsL2 data structure to store information on.</param>
258 /// <param name ="index">The index of the coefficient that is set (must be less than 9).</param>
259 /// <param name ="coefficient">The values of the coefficient is set.</param>
260 public static void SetCoefficient(ref SphericalHarmonicsL2 sh, int index, Vector3 coefficient)
261 {
262 Debug.Assert(index < 9);
263 sh[0, index] = coefficient.x;
264 sh[1, index] = coefficient.y;
265 sh[2, index] = coefficient.z;
266 }
267
268 /// <summary>
269 /// Get a spherical harmonics coefficient.
270 /// </summary>
271 /// <param name ="sh">The SphericalHarmonicsL2 data structure to get information from.</param>
272 /// <param name ="index">The index of the coefficient that is requested (must be less than 9).</param>
273 /// <returns>The value of the requested coefficient.</returns>
274 public static Vector3 GetCoefficient(SphericalHarmonicsL2 sh, int index)
275 {
276 Debug.Assert(index < 9);
277 return new Vector3(sh[0, index], sh[1, index], sh[2, index]);
278 }
279 }
280}