A game about forced loneliness, made by TACStudios
1using System.Collections.Generic;
2using System.Runtime.CompilerServices;
3using Unity.Mathematics;
4
5using RuntimeResources = UnityEngine.Rendering.ProbeReferenceVolume.RuntimeResources;
6
7namespace UnityEngine.Rendering
8{
9 static class ProbeVolumeConstantRuntimeResources
10 {
11 static ComputeBuffer m_SkySamplingDirectionsBuffer = null;
12 static ComputeBuffer m_AntiLeakDataBuffer = null;
13
14 [MethodImpl(MethodImplOptions.AggressiveInlining)]
15 internal static void GetRuntimeResources(ref RuntimeResources rr)
16 {
17 rr.SkyPrecomputedDirections = m_SkySamplingDirectionsBuffer;
18 rr.QualityLeakReductionData = m_AntiLeakDataBuffer;
19 }
20
21 internal static void Initialize()
22 {
23 if (m_SkySamplingDirectionsBuffer == null)
24 {
25 k_SkyDirections = GenerateSkyDirections();
26 m_SkySamplingDirectionsBuffer = new ComputeBuffer(k_SkyDirections.Length, 3 * sizeof(float));
27 m_SkySamplingDirectionsBuffer.SetData(k_SkyDirections);
28 }
29
30 if (m_AntiLeakDataBuffer == null)
31 {
32 m_AntiLeakDataBuffer = new ComputeBuffer(k_AntiLeakData.Length, sizeof(uint));
33 m_AntiLeakDataBuffer.SetData(k_AntiLeakData);
34 }
35 }
36
37 public static Vector3[] GetSkySamplingDirections()
38 {
39 return k_SkyDirections;
40 }
41
42 internal static void Cleanup()
43 {
44 CoreUtils.SafeRelease(m_SkySamplingDirectionsBuffer);
45 m_SkySamplingDirectionsBuffer = null;
46
47 CoreUtils.SafeRelease(m_AntiLeakDataBuffer);
48 m_AntiLeakDataBuffer = null;
49 }
50
51 #region Sky Directions Buffer generator
52 const int NB_SKY_PRECOMPUTED_DIRECTIONS = 255;
53 static Vector3[] k_SkyDirections = new Vector3[NB_SKY_PRECOMPUTED_DIRECTIONS];
54
55 static Vector3[] GenerateSkyDirections()
56 {
57 var skyDirections = new Vector3[NB_SKY_PRECOMPUTED_DIRECTIONS];
58
59 float sqrtNBpoints = Mathf.Sqrt((float)(NB_SKY_PRECOMPUTED_DIRECTIONS));
60 float phi = 0.0f;
61 float phiMax = 0.0f;
62 float thetaMax = 0.0f;
63
64 // Spiral based sampling on sphere
65 // See http://web.archive.org/web/20120331125729/http://www.math.niu.edu/~rusin/known-math/97/spherefaq
66 // http://www.math.vanderbilt.edu/saffeb/texts/161.pdf
67 for (int i=0; i < NB_SKY_PRECOMPUTED_DIRECTIONS; i++)
68 {
69 // theta from 0 to PI
70 // phi from 0 to 2PI
71 float h = -1.0f + (2.0f * i) / (NB_SKY_PRECOMPUTED_DIRECTIONS - 1.0f);
72 float theta = Mathf.Acos(h);
73 if (i == NB_SKY_PRECOMPUTED_DIRECTIONS - 1 || i==0)
74 phi = 0.0f;
75 else
76 phi = phi + 3.6f / sqrtNBpoints * 1.0f / (Mathf.Sqrt(1.0f-h*h));
77
78 Vector3 pointOnSphere = new Vector3(Mathf.Sin(theta) * Mathf.Cos(phi), Mathf.Sin(theta) * Mathf.Sin(phi), Mathf.Cos(theta));
79
80 pointOnSphere.Normalize();
81 skyDirections[i] = pointOnSphere;
82
83 phiMax = Mathf.Max(phiMax, phi);
84 thetaMax = Mathf.Max(thetaMax, theta);
85 }
86
87 return skyDirections;
88 }
89 #endregion
90
91 #region AntiLeak Buffer generator
92 #if UNITY_EDITOR
93 static uint3 GetSampleOffset(uint i)
94 {
95 return new uint3(i, i >> 1, i >> 2) & 1;
96 }
97 static int GetProbeIndex(int x, int y, int z)
98 {
99 return x + y * 2 + z * 4;
100 }
101
102 static uint BuildFace(int axis, int idx)
103 {
104 uint mask = 0;
105 int[] coords = new int[3];
106 coords[axis] = idx;
107 for (int i = 0; i < 2; i++)
108 {
109 coords[(axis + 1) % 3] = i;
110 for (int j = 0; j < 2; j++)
111 {
112 coords[(axis + 2) % 3] = j;
113 mask = mask | (uint)(1 << GetProbeIndex(coords[0], coords[1], coords[2]));
114 }
115 }
116 return mask;
117 }
118
119 static bool TryGetEdge(uint validityMask, uint samplingMask, out uint edge, out uint3 offset)
120 {
121 for (int i = 0; i < 8; i++)
122 {
123 if ((validityMask & (1 << i)) == 0)
124 continue;
125
126 uint3 p = GetSampleOffset((uint)i);
127 if (p.x == 0)
128 {
129 edge = (1u << i) | (1u << GetProbeIndex(1, (int)p.y, (int)p.z));
130 if ((validityMask & edge) == edge && (samplingMask & edge) == 0)
131 {
132 offset = 2 * p;
133 offset.x = 1;
134 return true;
135 }
136 }
137 if (p.y == 0)
138 {
139 edge = (1u << i) | (1u << GetProbeIndex((int)p.x, 1, (int)p.z));
140 if ((validityMask & edge) == edge && (samplingMask & edge) == 0)
141 {
142 offset = 2 * p;
143 offset.y = 1;
144 return true;
145 }
146 }
147 if (p.z == 0)
148 {
149 edge = (1u << i) | (1u << GetProbeIndex((int)p.x, (int)p.y, 1));
150 if ((validityMask & edge) == edge && (samplingMask & edge) == 0)
151 {
152 offset = 2 * p;
153 offset.z = 1;
154 return true;
155 }
156 }
157 }
158
159 edge = 0;
160 offset = 0;
161 return false;
162 }
163
164 static List<uint3> ComputeMask(uint validityMask)
165 {
166 List<uint3> samples = new();
167
168 // Cube sample
169 if (validityMask == 0 || validityMask == 255)
170 {
171 samples.Add(1);
172 return samples;
173 }
174
175 // track which probes are sampled
176 uint samplingMask = 0;
177
178 // Find face sample
179 for (int i = 0; i < 6; i++)
180 {
181 int axis = i / 2;
182 uint face = BuildFace(axis, i % 2);
183 if ((validityMask & face) == face) // all face is valid, sample it
184 {
185 uint3 offset = 0;
186 offset[axis] = (i % 2) == 0 ? 0u : 2u;
187 offset[(axis + 1) % 3] = 1;
188 offset[(axis + 2) % 3] = 1;
189
190 samples.Add(offset);
191 samplingMask = face;
192 break;
193 }
194 }
195
196 // Find edge samples
197 while (true)
198 {
199 if (!TryGetEdge(validityMask, samplingMask, out uint edge, out uint3 offset))
200 break;
201
202 samples.Add(offset);
203 samplingMask |= edge;
204 }
205
206 // Find single probe samples
207 for (int i = 0; i < 8; i++)
208 {
209 if (((1 << i) & (validityMask & ~samplingMask)) == 0)
210 continue;
211 samples.Add(2 * GetSampleOffset((uint)i));
212 samplingMask |= (uint)(1 << i);
213 }
214
215 return samples;
216 }
217
218 static uint PackSamplingDir(uint val)
219 {
220 // On a single axis there is up to 2 probes. A face or edge sample needs to sample in between the probes
221 // We encode 0 as sample first probe, 1 as sample between probe, 2 as sample second probe (2 bits)
222 // For faster decoding, we use a third bit that reduces ALU in shader
223 return /* 2 bits */ (val << 1) | /* 1 bit */ ((~val & 2) >> 1);
224 }
225
226 static uint InvalidSampleMask()
227 {
228 // This is a special code that results in no sampling in shader without any additional ALU
229 return 2 | (2 << 3) | (2 << 6);
230 }
231
232 static uint ComputeAntiLeakData(uint validityMask)
233 {
234 // This may generate more than 3 samples, but we limit to 3
235 var samples = ComputeMask(validityMask);
236 uint mask = 0;
237
238 for (int i = 0; i < 3; i++)
239 {
240 uint sampleMask;
241 if (i < samples.Count)
242 sampleMask = PackSamplingDir(samples[i].x) | (PackSamplingDir(samples[i].y) << 3) | (PackSamplingDir(samples[i].z) << 6);
243 else
244 sampleMask = InvalidSampleMask();
245
246 // 32bits - 9bits per samples (up to 3 samples)
247 // Each sample encodes sampling on each axis (3axis * 3bits)
248 // See PackSamplingDir for axis encoding
249 mask |= sampleMask << (9 * i);
250 }
251
252 return mask;
253 }
254
255 //[UnityEditor.MenuItem("Edit/Rendering/Global Illumination/Generate AntiLeak Buffer")]
256 static uint[] BuildAntiLeakDataArray()
257 {
258 uint[] antileak = new uint[256];
259 for (uint validityMask = 0; validityMask < 256; validityMask++)
260 antileak[validityMask] = ComputeAntiLeakData(validityMask);
261
262 string str = "static uint[] k_AntiLeakData = new uint[256] {\n";
263 for (int i = 0; i < 16; i++)
264 {
265 str += " ";
266 for (int j = 0; j < 16; j++)
267 {
268 str += antileak[i * 16 + j] + (j == 15 ? ",\n" : ", ");
269 }
270 }
271 str += " };";
272 Debug.Log(str);
273
274 return antileak;
275 }
276 #endif
277
278 // This is autogenerated using the MenuItem above -- do not edit by hand
279 static uint[] k_AntiLeakData = new uint[256] {
280 38347995, 38347849, 38347852, 38347851, 38347873, 38347865, 38322764, 38322763, 38347876, 38324297, 38347868, 38324299, 38347875, 38324313, 38322780, 38347867,
281 38348041, 38347977, 38408780, 38408779, 38408801, 38408793, 69517900, 69517899, 38408804, 38324425, 38408796, 69519435, 38408803, 69519449, 69517916, 38408795,
282 38348044, 38410313, 38347980, 38410315, 38410337, 38410329, 38322892, 70304331, 38410340, 70305865, 38410332, 70305867, 38410339, 70305881, 70304348, 38410331,
283 38348043, 38410441, 38408908, 38347979, 38322955, 38409817, 69518028, 38322891, 38324491, 70305993, 38409820, 38324427, 38409827, 26351193, 25564764, 38323915,
284 38348065, 38421065, 38421068, 38421067, 38348001, 38421081, 38312161, 38388299, 38421092, 75810889, 38421084, 75810891, 38421091, 75810905, 38388316, 38421083,
285 38348057, 38421193, 38312217, 38416971, 38408929, 38347993, 69507297, 38312153, 38324505, 75811017, 38416988, 26358347, 38416995, 38324441, 69583452, 38320345,
286 38421260, 75896905, 38421196, 75896907, 38410465, 75896921, 38388428, 70369867, 75896932, 70305865, 75896924, 70305867, 75896931, 70305881, 70369884, 75896923,
287 38421259, 75897033, 38417100, 38421195, 38409953, 38410457, 69583564, 38377689, 75811083, 70305993, 75896412, 75811019, 75896419, 70306009, 70107740, 70301913,
288 38348068, 38422601, 38422604, 38422603, 38422625, 38422617, 76595788, 76595787, 38348004, 38310628, 38422620, 38389835, 38422627, 38389849, 76595804, 38422619,
289 38422793, 38422729, 76681804, 76681803, 76681825, 76681817, 69517900, 69517899, 38408932, 38389961, 76681820, 69584971, 76681827, 69584985, 69517916, 76681819,
290 38348060, 38310684, 38422732, 38418507, 38322972, 38418521, 76595916, 25573451, 38410468, 70292196, 38347996, 38310620, 38418531, 70371417, 38322908, 38318812,
291 38422795, 38418633, 76681932, 38422731, 76595979, 76682841, 69518028, 76595915, 38409956, 70371529, 38408924, 38376156, 76682851, 70109273, 69518044, 69513948,
292 38348067, 38310691, 38312227, 38422091, 38422753, 38422105, 76585185, 76661323, 38421220, 75797220, 38422108, 75876427, 38348003, 38310627, 38312163, 38311651,
293 38422809, 38422217, 76585241, 76689995, 76681953, 38422745, 69507297, 76585177, 38417124, 75876553, 76690012, 73779275, 38408931, 38389977, 69507299, 76593369,
294 38421276, 75797276, 38422220, 75905099, 38418657, 75905113, 76661452, 74564171, 75897060, 70292196, 38421212, 75797212, 38410467, 70292195, 38388444, 75805404,
295 38348059, 38310683, 38312219, 38422219, 38322971, 38418649, 25467163, 76650713, 38324507, 26252059, 38417116, 75862748, 38409955, 70371545, 69583580, 38347995,
296 };
297 #endregion
298 }
299}