설명 없음
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Packing.hlsl 19KB

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