A game about forced loneliness, made by TACStudios
1#ifndef UNITY_PACKING_INCLUDED
2#define UNITY_PACKING_INCLUDED
3
4#if SHADER_API_MOBILE || SHADER_API_GLES3 || SHADER_API_SWITCH || defined(UNITY_UNIFIED_SHADER_PRECISION_MODEL)
5#pragma warning (disable : 3205) // conversion of larger type to smaller
6#endif
7
8//-----------------------------------------------------------------------------
9// Normal packing
10//-----------------------------------------------------------------------------
11
12real3 PackNormalMaxComponent(real3 n)
13{
14 return (n / Max3(abs(n.x), abs(n.y), abs(n.z))) * 0.5 + 0.5;
15}
16
17real3 UnpackNormalMaxComponent(real3 n)
18{
19 return normalize(n * 2.0 - 1.0);
20}
21
22// Ref: http://www.vis.uni-stuttgart.de/~engelhts/paper/vmvOctaMaps.pdf "Octahedron Environment Maps"
23// Encode with Oct, this function work with any size of output
24// return real between [-1, 1]
25real2 PackNormalOctRectEncode(real3 n)
26{
27 // Perform planar projection.
28 real3 p = n * rcp(dot(abs(n), 1.0));
29 real x = p.x, y = p.y, z = p.z;
30
31 // Unfold the octahedron.
32 // Also correct the aspect ratio from 2:1 to 1:1.
33 real r = saturate(0.5 - 0.5 * x + 0.5 * y);
34 real g = x + y;
35
36 // Negative hemisphere on the left, positive on the right.
37 return real2(CopySign(r, z), g);
38}
39
40real3 UnpackNormalOctRectEncode(real2 f)
41{
42 real r = f.r, g = f.g;
43
44 // Solve for {x, y, z} given {r, g}.
45 real x = 0.5 + 0.5 * g - abs(r);
46 real y = g - x;
47 real z = max(1.0 - abs(x) - abs(y), REAL_EPS); // EPS is absolutely crucial for anisotropy
48
49 real3 p = real3(x, y, CopySign(z, r));
50
51 return normalize(p);
52}
53
54// Ref: http://jcgt.org/published/0003/02/01/paper.pdf "A Survey of Efficient Representations for Independent Unit Vectors"
55// Encode with Oct, this function work with any size of output
56// return float between [-1, 1]
57float2 PackNormalOctQuadEncode(float3 n)
58{
59 //float l1norm = dot(abs(n), 1.0);
60 //float2 res0 = n.xy * (1.0 / l1norm);
61
62 //float2 val = 1.0 - abs(res0.yx);
63 //return (n.zz < float2(0.0, 0.0) ? (res0 >= 0.0 ? val : -val) : res0);
64
65 // Optimized version of above code:
66 n *= rcp(max(dot(abs(n), 1.0), 1e-6));
67 float t = saturate(-n.z);
68 return n.xy + float2(n.x >= 0.0 ? t : -t, n.y >= 0.0 ? t : -t);
69}
70
71float3 UnpackNormalOctQuadEncode(float2 f)
72{
73 // NOTE: Do NOT use abs() in this line. It causes miscompilations. (UUM-62216, UUM-70600)
74 float3 n = float3(f.x, f.y, 1.0 - (f.x < 0 ? -f.x : f.x) - (f.y < 0 ? -f.y : f.y));
75
76 //float2 val = 1.0 - abs(n.yx);
77 //n.xy = (n.zz < float2(0.0, 0.0) ? (n.xy >= 0.0 ? val : -val) : n.xy);
78
79 // Optimized version of above code:
80 float t = max(-n.z, 0.0);
81 n.xy += float2(n.x >= 0.0 ? -t : t, n.y >= 0.0 ? -t : t);
82
83 return normalize(n);
84}
85
86real2 PackNormalHemiOctEncode(real3 n)
87{
88 real l1norm = dot(abs(n), 1.0);
89 real2 res = n.xy * (1.0 / l1norm);
90
91 return real2(res.x + res.y, res.x - res.y);
92}
93
94real3 UnpackNormalHemiOctEncode(real2 f)
95{
96 real2 val = real2(f.x + f.y, f.x - f.y) * 0.5;
97 real3 n = real3(val, 1.0 - dot(abs(val), 1.0));
98
99 return normalize(n);
100}
101
102// Tetrahedral encoding - Looks like Tetra encoding 10:10 + 2 is similar to oct 11:11, as oct is cheaper prefer it
103// To generate the basisNormal below we use these 4 vertex of a regular tetrahedron
104// v0 = float3(1.0, 0.0, -1.0 / sqrt(2.0));
105// v1 = float3(-1.0, 0.0, -1.0 / sqrt(2.0));
106// v2 = float3(0.0, 1.0, 1.0 / sqrt(2.0));
107// v3 = float3(0.0, -1.0, 1.0 / sqrt(2.0));
108// Then we normalize the average of each face's vertices
109// normalize(v0 + v1 + v2), etc...
110static const real3 tetraBasisNormal[4] =
111{
112 real3(0., 0.816497, -0.57735),
113 real3(-0.816497, 0., 0.57735),
114 real3(0.816497, 0., 0.57735),
115 real3(0., -0.816497, -0.57735)
116};
117
118// Then to get the local matrix (with z axis rotate to basisNormal) use GetLocalFrame(basisNormal[xxx])
119static const real3x3 tetraBasisArray[4] =
120{
121 real3x3(-1., 0., 0.,0., 0.57735, 0.816497,0., 0.816497, -0.57735),
122 real3x3(0., -1., 0.,0.57735, 0., 0.816497,-0.816497, 0., 0.57735),
123 real3x3(0., 1., 0.,-0.57735, 0., 0.816497,0.816497, 0., 0.57735),
124 real3x3(1., 0., 0.,0., -0.57735, 0.816497,0., -0.816497, -0.57735)
125};
126
127// Return [-1..1] vector2 oriented in plane of the faceIndex of a regular tetrahedron
128real2 PackNormalTetraEncode(float3 n, out uint faceIndex)
129{
130 // Retrieve the tetrahedra's face for the normal direction
131 // It is the one with the greatest dot value with face normal
132 real dot0 = dot(n, tetraBasisNormal[0]);
133 real dot1 = dot(n, tetraBasisNormal[1]);
134 real dot2 = dot(n, tetraBasisNormal[2]);
135 real dot3 = dot(n, tetraBasisNormal[3]);
136
137 real maxi0 = max(dot0, dot1);
138 real maxi1 = max(dot2, dot3);
139 real maxi = max(maxi0, maxi1);
140
141 // Get the index from the greatest dot
142 if (maxi == dot0)
143 faceIndex = 0;
144 else if (maxi == dot1)
145 faceIndex = 1;
146 else if (maxi == dot2)
147 faceIndex = 2;
148 else //(maxi == dot3)
149 faceIndex = 3;
150
151 // Rotate n into this local basis
152 n = mul(tetraBasisArray[faceIndex], n);
153
154 // Project n onto the local plane
155 return n.xy;
156}
157
158// Assume f [-1..1]
159real3 UnpackNormalTetraEncode(real2 f, uint faceIndex)
160{
161 // Recover n from local plane
162 real3 n = real3(f.xy, sqrt(1.0 - dot(f.xy, f.xy)));
163 // Inverse of transform PackNormalTetraEncode (just swap order in mul as we have a rotation)
164 return mul(n, tetraBasisArray[faceIndex]);
165}
166
167// Unpack from normal map
168real3 UnpackNormalRGB(real4 packedNormal, real scale = 1.0)
169{
170 real3 normal;
171 normal.xyz = packedNormal.rgb * 2.0 - 1.0;
172 normal.xy *= scale;
173 return normal;
174}
175
176real3 UnpackNormalRGBNoScale(real4 packedNormal)
177{
178 return packedNormal.rgb * 2.0 - 1.0;
179}
180
181real3 UnpackNormalAG(real4 packedNormal, real scale = 1.0)
182{
183 real3 normal;
184 normal.xy = packedNormal.ag * 2.0 - 1.0;
185 normal.z = max(1.0e-16, sqrt(1.0 - saturate(dot(normal.xy, normal.xy))));
186
187 // must scale after reconstruction of normal.z which also
188 // mirrors UnpackNormalRGB(). This does imply normal is not returned
189 // as a unit length vector but doesn't need it since it will get normalized after TBN transformation.
190 // If we ever need to blend contributions with built-in shaders for URP
191 // then we should consider using UnpackDerivativeNormalAG() instead like
192 // HDRP does since derivatives do not use renormalization and unlike tangent space
193 // normals allow you to blend, accumulate and scale contributions correctly.
194 normal.xy *= scale;
195 return normal;
196}
197
198// Unpack normal as DXT5nm (1, y, 0, x) or BC5 (x, y, 0, 1)
199real3 UnpackNormalmapRGorAG(real4 packedNormal, real scale = 1.0)
200{
201 // Convert to (?, y, 0, x)
202 packedNormal.a *= packedNormal.r;
203 return UnpackNormalAG(packedNormal, scale);
204}
205
206#ifndef BUILTIN_TARGET_API
207real3 UnpackNormal(real4 packedNormal)
208{
209#if defined(UNITY_ASTC_NORMALMAP_ENCODING)
210 return UnpackNormalAG(packedNormal, 1.0);
211#elif defined(UNITY_NO_DXT5nm)
212 return UnpackNormalRGBNoScale(packedNormal);
213#else
214 // Compiler will optimize the scale away
215 return UnpackNormalmapRGorAG(packedNormal, 1.0);
216#endif
217}
218#endif
219
220real3 UnpackNormalScale(real4 packedNormal, real bumpScale)
221{
222#if defined(UNITY_ASTC_NORMALMAP_ENCODING)
223 return UnpackNormalAG(packedNormal, bumpScale);
224#elif defined(UNITY_NO_DXT5nm)
225 return UnpackNormalRGB(packedNormal, bumpScale);
226#else
227 return UnpackNormalmapRGorAG(packedNormal, bumpScale);
228#endif
229}
230
231//-----------------------------------------------------------------------------
232// HDR packing
233//-----------------------------------------------------------------------------
234
235// Ref: http://realtimecollisiondetection.net/blog/?p=15
236real4 PackToLogLuv(real3 vRGB)
237{
238 // M matrix, for encoding
239 const real3x3 M = real3x3(
240 0.2209, 0.3390, 0.4184,
241 0.1138, 0.6780, 0.7319,
242 0.0102, 0.1130, 0.2969);
243
244 real4 vResult;
245 real3 Xp_Y_XYZp = mul(vRGB, M);
246 Xp_Y_XYZp = max(Xp_Y_XYZp, real3(1e-6, 1e-6, 1e-6));
247 vResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;
248 real Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;
249 vResult.w = frac(Le);
250 vResult.z = (Le - (floor(vResult.w * 255.0)) / 255.0) / 255.0;
251 return vResult;
252}
253
254real3 UnpackFromLogLuv(real4 vLogLuv)
255{
256 // Inverse M matrix, for decoding
257 const real3x3 InverseM = real3x3(
258 6.0014, -2.7008, -1.7996,
259 -1.3320, 3.1029, -5.7721,
260 0.3008, -1.0882, 5.6268);
261
262 real Le = vLogLuv.z * 255.0 + vLogLuv.w;
263 real3 Xp_Y_XYZp;
264 Xp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);
265 Xp_Y_XYZp.z = Xp_Y_XYZp.y / vLogLuv.y;
266 Xp_Y_XYZp.x = vLogLuv.x * Xp_Y_XYZp.z;
267 real3 vRGB = mul(Xp_Y_XYZp, InverseM);
268 return max(vRGB, real3(0.0, 0.0, 0.0));
269}
270
271// The standard 32-bit HDR color format
272uint PackToR11G11B10f(float3 rgb)
273{
274 uint r = (f32tof16(rgb.x) << 17) & 0xFFE00000;
275 uint g = (f32tof16(rgb.y) << 6) & 0x001FFC00;
276 uint b = (f32tof16(rgb.z) >> 5) & 0x000003FF;
277 return r | g | b;
278}
279
280float3 UnpackFromR11G11B10f(uint rgb)
281{
282 float r = f16tof32((rgb >> 17) & 0x7FF0);
283 float g = f16tof32((rgb >> 6) & 0x7FF0);
284 float b = f16tof32((rgb << 5) & 0x7FE0);
285 return float3(r, g, b);
286}
287
288//-----------------------------------------------------------------------------
289// Quaternion packing
290//-----------------------------------------------------------------------------
291
292// Ref: https://cedec.cesa.or.jp/2015/session/ENG/14698.html The Rendering Materials of Far Cry 4
293
294/*
295// This is GCN intrinsic
296uint FindBiggestComponent(real4 q)
297{
298 uint xyzIndex = CubeMapFaceID(q.x, q.y, q.z) * 0.5f;
299 uint wIndex = 3;
300
301 bool wBiggest = abs(q.w) > max3(abs(q.x), qbs(q.y), qbs(q.z));
302
303 return wBiggest ? wIndex : xyzIndex;
304}
305
306// Pack a quaternion into a 10:10:10:2
307real4 PackQuat(real4 quat)
308{
309 uint index = FindBiggestComponent(quat);
310
311 if (index == 0) quat = quat.yzwx;
312 if (index == 1) quat = quat.xzwy;
313 if (index == 2) quat = quat.xywz;
314
315 real4 packedQuat;
316 packedQuat.xyz = quat.xyz * FastSign(quat.w) * sqrt(0.5) + 0.5;
317 packedQuat.w = index / 3.0;
318
319 return packedQuat;
320}
321*/
322
323// Unpack a quaternion from a 10:10:10:2
324real4 UnpackQuat(real4 packedQuat)
325{
326 uint index = (uint)(packedQuat.w * 3.0);
327
328 real4 quat;
329 quat.xyz = packedQuat.xyz * sqrt(2.0) - (1.0 / sqrt(2.0));
330 quat.w = sqrt(1.0 - saturate(dot(quat.xyz, quat.xyz)));
331
332 if (index == 0) quat = quat.wxyz;
333 if (index == 1) quat = quat.xwyz;
334 if (index == 2) quat = quat.xywz;
335
336 return quat;
337}
338
339//-----------------------------------------------------------------------------
340// Integer packing
341//-----------------------------------------------------------------------------
342
343// Packs an integer stored using at most 'numBits' into a [0..1] real.
344real PackInt(uint i, uint numBits)
345{
346 uint maxInt = (1u << numBits) - 1u;
347 return saturate(i * rcp(maxInt));
348}
349
350// Unpacks a [0..1] real into an integer of size 'numBits'.
351uint UnpackInt(real f, uint numBits)
352{
353 uint maxInt = (1u << numBits) - 1u;
354 return (uint)(f * maxInt + 0.5); // Round instead of truncating
355}
356
357// Packs a [0..255] integer into a [0..1] real.
358real PackByte(uint i)
359{
360 return PackInt(i, 8);
361}
362
363// Unpacks a [0..1] real into a [0..255] integer.
364uint UnpackByte(real f)
365{
366 return UnpackInt(f, 8);
367}
368
369// Packs a [0..65535] integer into a [0..1] real.
370real PackShort(uint i)
371{
372 return PackInt(i, 16);
373}
374
375// Unpacks a [0..1] real into a [0..65535] integer.
376uint UnpackShort(real f)
377{
378 return UnpackInt(f, 16);
379}
380
381// Packs 8 lowermost bits of a [0..65535] integer into a [0..1] real.
382real PackShortLo(uint i)
383{
384 uint lo = BitFieldExtract(i, 0u, 8u);
385 return PackInt(lo, 8);
386}
387
388// Packs 8 uppermost bits of a [0..65535] integer into a [0..1] real.
389real PackShortHi(uint i)
390{
391 uint hi = BitFieldExtract(i, 8u, 8u);
392 return PackInt(hi, 8);
393}
394
395real Pack2Byte(real2 inputs)
396{
397 real2 temp = inputs * real2(255.0, 255.0);
398 temp.x *= 256.0;
399 temp = round(temp);
400 real combined = temp.x + temp.y;
401 return combined * (1.0 / 65535.0);
402}
403
404real2 Unpack2Byte(real inputs)
405{
406 real temp = round(inputs * 65535.0);
407 real ipart;
408 real fpart = modf(temp / 256.0, ipart);
409 real2 result = real2(ipart, round(256.0 * fpart));
410 return result * (1.0 / real2(255.0, 255.0));
411}
412
413// Encode a real in [0..1] and an int in [0..maxi - 1] as a real [0..1] to be store in log2(precision) bit
414// maxi must be a power of two and define the number of bit dedicated 0..1 to the int part (log2(maxi))
415// Example: precision is 256.0, maxi is 2, i is [0..1] encode on 1 bit. f is [0..1] encode on 7 bit.
416// Example: precision is 256.0, maxi is 4, i is [0..3] encode on 2 bit. f is [0..1] encode on 6 bit.
417// Example: precision is 256.0, maxi is 8, i is [0..7] encode on 3 bit. f is [0..1] encode on 5 bit.
418// ...
419// Example: precision is 1024.0, maxi is 8, i is [0..7] encode on 3 bit. f is [0..1] encode on 7 bit.
420//...
421real PackFloatInt(real f, uint i, real maxi, real precision)
422{
423 // Constant
424 real precisionMinusOne = precision - 1.0;
425 real t1 = ((precision / maxi) - 1.0) / precisionMinusOne;
426 real t2 = (precision / maxi) / precisionMinusOne;
427
428 return t1 * f + t2 * real(i);
429}
430
431void UnpackFloatInt(real val, real maxi, real precision, out real f, out uint i)
432{
433 // Constant
434 real precisionMinusOne = precision - 1.0;
435 real t1 = ((precision / maxi) - 1.0) / precisionMinusOne;
436 real t2 = (precision / maxi) / precisionMinusOne;
437
438 // extract integer part
439 i = int((val / t2) + rcp(precisionMinusOne)); // + rcp(precisionMinusOne) to deal with precision issue (can't use round() as val contain the floating number
440 // Now that we have i, solve formula in PackFloatInt for f
441 //f = (val - t2 * real(i)) / t1 => convert in mads form
442 f = saturate((-t2 * real(i) + val) / t1); // Saturate in case of precision issue
443}
444
445// Define various variante for ease of read
446real PackFloatInt8bit(real f, uint i, real maxi)
447{
448 return PackFloatInt(f, i, maxi, 256.0);
449}
450
451void UnpackFloatInt8bit(real val, real maxi, out real f, out uint i)
452{
453 UnpackFloatInt(val, maxi, 256.0, f, i);
454}
455
456real PackFloatInt10bit(real f, uint i, real maxi)
457{
458 return PackFloatInt(f, i, maxi, 1024.0);
459}
460
461void UnpackFloatInt10bit(real val, real maxi, out real f, out uint i)
462{
463 UnpackFloatInt(val, maxi, 1024.0, f, i);
464}
465
466real PackFloatInt16bit(real f, uint i, real maxi)
467{
468 return PackFloatInt(f, i, maxi, 65536.0);
469}
470
471void UnpackFloatInt16bit(real val, real maxi, out real f, out uint i)
472{
473 UnpackFloatInt(val, maxi, 65536.0, f, i);
474}
475
476//-----------------------------------------------------------------------------
477// Float packing
478//-----------------------------------------------------------------------------
479
480// src must be between 0.0 and 1.0
481uint PackFloatToUInt(real src, uint offset, uint numBits)
482{
483 return UnpackInt(src, numBits) << offset;
484}
485
486real UnpackUIntToFloat(uint src, uint offset, uint numBits)
487{
488 uint maxInt = (1u << numBits) - 1u;
489 return real(BitFieldExtract(src, offset, numBits)) * rcp(maxInt);
490}
491
492uint PackToR10G10B10A2(real4 rgba)
493{
494 return (PackFloatToUInt(rgba.x, 0, 10) |
495 PackFloatToUInt(rgba.y, 10, 10) |
496 PackFloatToUInt(rgba.z, 20, 10) |
497 PackFloatToUInt(rgba.w, 30, 2));
498}
499
500real4 UnpackFromR10G10B10A2(uint rgba)
501{
502 real4 output;
503 output.x = UnpackUIntToFloat(rgba, 0, 10);
504 output.y = UnpackUIntToFloat(rgba, 10, 10);
505 output.z = UnpackUIntToFloat(rgba, 20, 10);
506 output.w = UnpackUIntToFloat(rgba, 30, 2);
507 return output;
508}
509
510// Both the input and the output are in the [0, 1] range.
511real2 PackFloatToR8G8(real f)
512{
513 uint i = UnpackShort(f);
514 return real2(PackShortLo(i), PackShortHi(i));
515}
516
517// Both the input and the output are in the [0, 1] range.
518real UnpackFloatFromR8G8(real2 f)
519{
520 uint lo = UnpackByte(f.x);
521 uint hi = UnpackByte(f.y);
522 uint cb = (hi << 8) + lo;
523 return PackShort(cb);
524}
525
526// Pack float2 (each of 12 bit) in 888
527uint3 PackFloat2To888UInt(float2 f)
528{
529 uint2 i = (uint2)(f * 4095.5);
530 uint2 hi = i >> 8;
531 uint2 lo = i & 255;
532 // 8 bit in lo, 4 bit in hi
533 uint3 cb = uint3(lo, hi.x | (hi.y << 4));
534 return cb;
535}
536
537// Pack float2 (each of 12 bit) in 888
538float3 PackFloat2To888(float2 f)
539{
540 return PackFloat2To888UInt(f) / 255.0;
541}
542
543// Unpack 2 float of 12bit packed into a 888
544float2 Unpack888UIntToFloat2(uint3 x)
545{
546 // 8 bit in lo, 4 bit in hi
547 uint hi = x.z >> 4;
548 uint lo = x.z & 15;
549 uint2 cb = x.xy | uint2(lo << 8, hi << 8);
550
551 return cb / 4095.0;
552}
553
554// Unpack 2 float of 12bit packed into a 888
555float2 Unpack888ToFloat2(float3 x)
556{
557 uint3 i = (uint3)(x * 255.5); // +0.5 to fix precision error on iOS
558 return Unpack888UIntToFloat2(i);
559}
560
561// Pack 2 float values from the [0, 1] range, to an 8 bits float from the [0, 1] range
562float PackFloat2To8(float2 f)
563{
564 float2 i = floor(f * 15.0); // f.x & f.y encoded over 4 bits, can have 2^4 = 16 distinct values mapped to [0, 1, ..., 15]
565 float x_y_expanded = i.x * 16.0 + i.y; // f.x encoded over higher bits, f.y encoded over the lower bits - x_y values in range [0, 1, ..., 255]
566 return x_y_expanded / 255.0;
567
568 // above 4 lines equivalent to:
569 //return (16.0 * f.x + f.y) / 17.0;
570}
571
572// Unpack 2 float values from the [0, 1] range, packed in an 8 bits float from the [0, 1] range
573float2 Unpack8ToFloat2(float f)
574{
575 float x_y_expanded = 255.0 * f;
576 float x_expanded = floor(x_y_expanded / 16.0);
577 float y_expanded = x_y_expanded - 16.0 * x_expanded;
578 float x = x_expanded / 15.0;
579 float y = y_expanded / 15.0;
580 return float2(x, y);
581}
582
583//-----------------------------------------------------------------------------
584// Color packing
585//-----------------------------------------------------------------------------
586
587float4 UnpackFromR8G8B8A8(uint rgba)
588{
589 return float4(rgba & 255, (rgba >> 8) & 255, (rgba >> 16) & 255, (rgba >> 24) & 255) * (1.0 / 255);
590}
591
592float2 PackToR5G6B5(float3 rgb)
593{
594 uint rgb16 = (PackFloatToUInt(rgb.x, 0, 5) |
595 PackFloatToUInt(rgb.y, 5, 6) |
596 PackFloatToUInt(rgb.z, 11, 5));
597 return float2(PackByte(rgb16 >> 8), PackByte(rgb16 & 0xFF));
598}
599
600float3 UnpackFromR5G6B5(float2 rgb)
601{
602 uint rgb16 = (UnpackByte(rgb.x) << 8) | UnpackByte(rgb.y);
603 return float3(UnpackUIntToFloat(rgb16, 0, 5),
604 UnpackUIntToFloat(rgb16, 5, 6),
605 UnpackUIntToFloat(rgb16, 11, 5));
606}
607
608uint PackToR7G7B6(float3 rgb)
609{
610 uint rgb20 = (PackFloatToUInt(rgb.x, 0, 7) |
611 PackFloatToUInt(rgb.y, 7, 7) |
612 PackFloatToUInt(rgb.z, 14, 6));
613 return rgb20;
614}
615
616float3 UnpackFromR7G7B6(uint rgb)
617{
618 return float3(UnpackUIntToFloat(rgb, 0, 7),
619 UnpackUIntToFloat(rgb, 7, 7),
620 UnpackUIntToFloat(rgb, 14, 6));
621}
622
623
624#if SHADER_API_MOBILE || SHADER_API_GLES3 || SHADER_API_SWITCH
625#pragma warning (enable : 3205) // conversion of larger type to smaller
626#endif
627
628#endif // UNITY_PACKING_INCLUDED