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