1/// @ref gtc_packing 2/// @file glm/gtc/packing.inl 3 4#include "../common.hpp" 5#include "../vec2.hpp" 6#include "../vec3.hpp" 7#include "../vec4.hpp" 8#include "../detail/type_half.hpp" 9#include <cstring> 10#include <limits> 11 12namespace glm{ 13namespace detail 14{ 15 GLM_FUNC_QUALIFIER glm::uint16 float2half(glm::uint32 f) 16 { 17 // 10 bits => EE EEEFFFFF 18 // 11 bits => EEE EEFFFFFF 19 // Half bits => SEEEEEFF FFFFFFFF 20 // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF 21 22 // 0x00007c00 => 00000000 00000000 01111100 00000000 23 // 0x000003ff => 00000000 00000000 00000011 11111111 24 // 0x38000000 => 00111000 00000000 00000000 00000000 25 // 0x7f800000 => 01111111 10000000 00000000 00000000 26 // 0x00008000 => 00000000 00000000 10000000 00000000 27 return 28 ((f >> 16) & 0x8000) | // sign 29 ((((f & 0x7f800000) - 0x38000000) >> 13) & 0x7c00) | // exponential 30 ((f >> 13) & 0x03ff); // Mantissa 31 } 32 33 GLM_FUNC_QUALIFIER glm::uint32 float2packed11(glm::uint32 f) 34 { 35 // 10 bits => EE EEEFFFFF 36 // 11 bits => EEE EEFFFFFF 37 // Half bits => SEEEEEFF FFFFFFFF 38 // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF 39 40 // 0x000007c0 => 00000000 00000000 00000111 11000000 41 // 0x00007c00 => 00000000 00000000 01111100 00000000 42 // 0x000003ff => 00000000 00000000 00000011 11111111 43 // 0x38000000 => 00111000 00000000 00000000 00000000 44 // 0x7f800000 => 01111111 10000000 00000000 00000000 45 // 0x00008000 => 00000000 00000000 10000000 00000000 46 return 47 ((((f & 0x7f800000) - 0x38000000) >> 17) & 0x07c0) | // exponential 48 ((f >> 17) & 0x003f); // Mantissa 49 } 50 51 GLM_FUNC_QUALIFIER glm::uint32 packed11ToFloat(glm::uint32 p) 52 { 53 // 10 bits => EE EEEFFFFF 54 // 11 bits => EEE EEFFFFFF 55 // Half bits => SEEEEEFF FFFFFFFF 56 // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF 57 58 // 0x000007c0 => 00000000 00000000 00000111 11000000 59 // 0x00007c00 => 00000000 00000000 01111100 00000000 60 // 0x000003ff => 00000000 00000000 00000011 11111111 61 // 0x38000000 => 00111000 00000000 00000000 00000000 62 // 0x7f800000 => 01111111 10000000 00000000 00000000 63 // 0x00008000 => 00000000 00000000 10000000 00000000 64 return 65 ((((p & 0x07c0) << 17) + 0x38000000) & 0x7f800000) | // exponential 66 ((p & 0x003f) << 17); // Mantissa 67 } 68 69 GLM_FUNC_QUALIFIER glm::uint32 float2packed10(glm::uint32 f) 70 { 71 // 10 bits => EE EEEFFFFF 72 // 11 bits => EEE EEFFFFFF 73 // Half bits => SEEEEEFF FFFFFFFF 74 // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF 75 76 // 0x0000001F => 00000000 00000000 00000000 00011111 77 // 0x0000003F => 00000000 00000000 00000000 00111111 78 // 0x000003E0 => 00000000 00000000 00000011 11100000 79 // 0x000007C0 => 00000000 00000000 00000111 11000000 80 // 0x00007C00 => 00000000 00000000 01111100 00000000 81 // 0x000003FF => 00000000 00000000 00000011 11111111 82 // 0x38000000 => 00111000 00000000 00000000 00000000 83 // 0x7f800000 => 01111111 10000000 00000000 00000000 84 // 0x00008000 => 00000000 00000000 10000000 00000000 85 return 86 ((((f & 0x7f800000) - 0x38000000) >> 18) & 0x03E0) | // exponential 87 ((f >> 18) & 0x001f); // Mantissa 88 } 89 90 GLM_FUNC_QUALIFIER glm::uint32 packed10ToFloat(glm::uint32 p) 91 { 92 // 10 bits => EE EEEFFFFF 93 // 11 bits => EEE EEFFFFFF 94 // Half bits => SEEEEEFF FFFFFFFF 95 // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF 96 97 // 0x0000001F => 00000000 00000000 00000000 00011111 98 // 0x0000003F => 00000000 00000000 00000000 00111111 99 // 0x000003E0 => 00000000 00000000 00000011 11100000 100 // 0x000007C0 => 00000000 00000000 00000111 11000000 101 // 0x00007C00 => 00000000 00000000 01111100 00000000 102 // 0x000003FF => 00000000 00000000 00000011 11111111 103 // 0x38000000 => 00111000 00000000 00000000 00000000 104 // 0x7f800000 => 01111111 10000000 00000000 00000000 105 // 0x00008000 => 00000000 00000000 10000000 00000000 106 return 107 ((((p & 0x03E0) << 18) + 0x38000000) & 0x7f800000) | // exponential 108 ((p & 0x001f) << 18); // Mantissa 109 } 110 111 GLM_FUNC_QUALIFIER glm::uint half2float(glm::uint h) 112 { 113 return ((h & 0x8000) << 16) | ((( h & 0x7c00) + 0x1C000) << 13) | ((h & 0x03FF) << 13); 114 } 115 116 GLM_FUNC_QUALIFIER glm::uint floatTo11bit(float x) 117 { 118 if(x == 0.0f) 119 return 0u; 120 else if(glm::isnan(x)) 121 return ~0u; 122 else if(glm::isinf(x)) 123 return 0x1Fu << 6u; 124 125 uint Pack = 0u; 126 memcpy(&Pack, &x, sizeof(Pack)); 127 return float2packed11(Pack); 128 } 129 130 GLM_FUNC_QUALIFIER float packed11bitToFloat(glm::uint x) 131 { 132 if(x == 0) 133 return 0.0f; 134 else if(x == ((1 << 11) - 1)) 135 return ~0;//NaN 136 else if(x == (0x1f << 6)) 137 return ~0;//Inf 138 139 uint Result = packed11ToFloat(x); 140 141 float Temp = 0; 142 memcpy(&Temp, &Result, sizeof(Temp)); 143 return Temp; 144 } 145 146 GLM_FUNC_QUALIFIER glm::uint floatTo10bit(float x) 147 { 148 if(x == 0.0f) 149 return 0u; 150 else if(glm::isnan(x)) 151 return ~0u; 152 else if(glm::isinf(x)) 153 return 0x1Fu << 5u; 154 155 uint Pack = 0; 156 memcpy(&Pack, &x, sizeof(Pack)); 157 return float2packed10(Pack); 158 } 159 160 GLM_FUNC_QUALIFIER float packed10bitToFloat(glm::uint x) 161 { 162 if(x == 0) 163 return 0.0f; 164 else if(x == ((1 << 10) - 1)) 165 return ~0;//NaN 166 else if(x == (0x1f << 5)) 167 return ~0;//Inf 168 169 uint Result = packed10ToFloat(x); 170 171 float Temp = 0; 172 memcpy(&Temp, &Result, sizeof(Temp)); 173 return Temp; 174 } 175 176// GLM_FUNC_QUALIFIER glm::uint f11_f11_f10(float x, float y, float z) 177// { 178// return ((floatTo11bit(x) & ((1 << 11) - 1)) << 0) | ((floatTo11bit(y) & ((1 << 11) - 1)) << 11) | ((floatTo10bit(z) & ((1 << 10) - 1)) << 22); 179// } 180 181 union u3u3u2 182 { 183 struct 184 { 185 uint x : 3; 186 uint y : 3; 187 uint z : 2; 188 } data; 189 uint8 pack; 190 }; 191 192 union u4u4 193 { 194 struct 195 { 196 uint x : 4; 197 uint y : 4; 198 } data; 199 uint8 pack; 200 }; 201 202 union u4u4u4u4 203 { 204 struct 205 { 206 uint x : 4; 207 uint y : 4; 208 uint z : 4; 209 uint w : 4; 210 } data; 211 uint16 pack; 212 }; 213 214 union u5u6u5 215 { 216 struct 217 { 218 uint x : 5; 219 uint y : 6; 220 uint z : 5; 221 } data; 222 uint16 pack; 223 }; 224 225 union u5u5u5u1 226 { 227 struct 228 { 229 uint x : 5; 230 uint y : 5; 231 uint z : 5; 232 uint w : 1; 233 } data; 234 uint16 pack; 235 }; 236 237 union u10u10u10u2 238 { 239 struct 240 { 241 uint x : 10; 242 uint y : 10; 243 uint z : 10; 244 uint w : 2; 245 } data; 246 uint32 pack; 247 }; 248 249 union i10i10i10i2 250 { 251 struct 252 { 253 int x : 10; 254 int y : 10; 255 int z : 10; 256 int w : 2; 257 } data; 258 uint32 pack; 259 }; 260 261 union u9u9u9e5 262 { 263 struct 264 { 265 uint x : 9; 266 uint y : 9; 267 uint z : 9; 268 uint w : 5; 269 } data; 270 uint32 pack; 271 }; 272 273 template <precision P, template <typename, precision> class vecType> 274 struct compute_half 275 {}; 276 277 template <precision P> 278 struct compute_half<P, tvec1> 279 { 280 GLM_FUNC_QUALIFIER static tvec1<uint16, P> pack(tvec1<float, P> const & v) 281 { 282 int16 const Unpack(detail::toFloat16(v.x)); 283 u16vec1 Packed(uninitialize); 284 memcpy(&Packed, &Unpack, sizeof(Packed)); 285 return Packed; 286 } 287 288 GLM_FUNC_QUALIFIER static tvec1<float, P> unpack(tvec1<uint16, P> const & v) 289 { 290 i16vec1 Unpack(uninitialize); 291 memcpy(&Unpack, &v, sizeof(Unpack)); 292 return tvec1<float, P>(detail::toFloat32(v.x)); 293 } 294 }; 295 296 template <precision P> 297 struct compute_half<P, tvec2> 298 { 299 GLM_FUNC_QUALIFIER static tvec2<uint16, P> pack(tvec2<float, P> const & v) 300 { 301 tvec2<int16, P> const Unpack(detail::toFloat16(v.x), detail::toFloat16(v.y)); 302 u16vec2 Packed(uninitialize); 303 memcpy(&Packed, &Unpack, sizeof(Packed)); 304 return Packed; 305 } 306 307 GLM_FUNC_QUALIFIER static tvec2<float, P> unpack(tvec2<uint16, P> const & v) 308 { 309 i16vec2 Unpack(uninitialize); 310 memcpy(&Unpack, &v, sizeof(Unpack)); 311 return tvec2<float, P>(detail::toFloat32(v.x), detail::toFloat32(v.y)); 312 } 313 }; 314 315 template <precision P> 316 struct compute_half<P, tvec3> 317 { 318 GLM_FUNC_QUALIFIER static tvec3<uint16, P> pack(tvec3<float, P> const & v) 319 { 320 tvec3<int16, P> const Unpack(detail::toFloat16(v.x), detail::toFloat16(v.y), detail::toFloat16(v.z)); 321 u16vec3 Packed(uninitialize); 322 memcpy(&Packed, &Unpack, sizeof(Packed)); 323 return Packed; 324 } 325 326 GLM_FUNC_QUALIFIER static tvec3<float, P> unpack(tvec3<uint16, P> const & v) 327 { 328 i16vec3 Unpack(uninitialize); 329 memcpy(&Unpack, &v, sizeof(Unpack)); 330 return tvec3<float, P>(detail::toFloat32(v.x), detail::toFloat32(v.y), detail::toFloat32(v.z)); 331 } 332 }; 333 334 template <precision P> 335 struct compute_half<P, tvec4> 336 { 337 GLM_FUNC_QUALIFIER static tvec4<uint16, P> pack(tvec4<float, P> const & v) 338 { 339 tvec4<int16, P> const Unpack(detail::toFloat16(v.x), detail::toFloat16(v.y), detail::toFloat16(v.z), detail::toFloat16(v.w)); 340 u16vec4 Packed(uninitialize); 341 memcpy(&Packed, &Unpack, sizeof(Packed)); 342 return Packed; 343 } 344 345 GLM_FUNC_QUALIFIER static tvec4<float, P> unpack(tvec4<uint16, P> const & v) 346 { 347 i16vec4 Unpack(uninitialize); 348 memcpy(&Unpack, &v, sizeof(Unpack)); 349 return tvec4<float, P>(detail::toFloat32(v.x), detail::toFloat32(v.y), detail::toFloat32(v.z), detail::toFloat32(v.w)); 350 } 351 }; 352}//namespace detail 353 354 GLM_FUNC_QUALIFIER uint8 packUnorm1x8(float v) 355 { 356 return static_cast<uint8>(round(clamp(v, 0.0f, 1.0f) * 255.0f)); 357 } 358 359 GLM_FUNC_QUALIFIER float unpackUnorm1x8(uint8 p) 360 { 361 float const Unpack(p); 362 return Unpack * static_cast<float>(0.0039215686274509803921568627451); // 1 / 255 363 } 364 365 GLM_FUNC_QUALIFIER uint16 packUnorm2x8(vec2 const & v) 366 { 367 u8vec2 const Topack(round(clamp(v, 0.0f, 1.0f) * 255.0f)); 368 369 uint16 Unpack = 0; 370 memcpy(&Unpack, &Topack, sizeof(Unpack)); 371 return Unpack; 372 } 373 374 GLM_FUNC_QUALIFIER vec2 unpackUnorm2x8(uint16 p) 375 { 376 u8vec2 Unpack(uninitialize); 377 memcpy(&Unpack, &p, sizeof(Unpack)); 378 return vec2(Unpack) * float(0.0039215686274509803921568627451); // 1 / 255 379 } 380 381 GLM_FUNC_QUALIFIER uint8 packSnorm1x8(float v) 382 { 383 int8 const Topack(static_cast<int8>(round(clamp(v ,-1.0f, 1.0f) * 127.0f))); 384 uint8 Packed = 0; 385 memcpy(&Packed, &Topack, sizeof(Packed)); 386 return Packed; 387 } 388 389 GLM_FUNC_QUALIFIER float unpackSnorm1x8(uint8 p) 390 { 391 int8 Unpack = 0; 392 memcpy(&Unpack, &p, sizeof(Unpack)); 393 return clamp( 394 static_cast<float>(Unpack) * 0.00787401574803149606299212598425f, // 1.0f / 127.0f 395 -1.0f, 1.0f); 396 } 397 398 GLM_FUNC_QUALIFIER uint16 packSnorm2x8(vec2 const & v) 399 { 400 i8vec2 const Topack(round(clamp(v, -1.0f, 1.0f) * 127.0f)); 401 uint16 Packed = 0; 402 memcpy(&Packed, &Topack, sizeof(Packed)); 403 return Packed; 404 } 405 406 GLM_FUNC_QUALIFIER vec2 unpackSnorm2x8(uint16 p) 407 { 408 i8vec2 Unpack(uninitialize); 409 memcpy(&Unpack, &p, sizeof(Unpack)); 410 return clamp( 411 vec2(Unpack) * 0.00787401574803149606299212598425f, // 1.0f / 127.0f 412 -1.0f, 1.0f); 413 } 414 415 GLM_FUNC_QUALIFIER uint16 packUnorm1x16(float s) 416 { 417 return static_cast<uint16>(round(clamp(s, 0.0f, 1.0f) * 65535.0f)); 418 } 419 420 GLM_FUNC_QUALIFIER float unpackUnorm1x16(uint16 p) 421 { 422 float const Unpack(p); 423 return Unpack * 1.5259021896696421759365224689097e-5f; // 1.0 / 65535.0 424 } 425 426 GLM_FUNC_QUALIFIER uint64 packUnorm4x16(vec4 const & v) 427 { 428 u16vec4 const Topack(round(clamp(v , 0.0f, 1.0f) * 65535.0f)); 429 uint64 Packed = 0; 430 memcpy(&Packed, &Topack, sizeof(Packed)); 431 return Packed; 432 } 433 434 GLM_FUNC_QUALIFIER vec4 unpackUnorm4x16(uint64 p) 435 { 436 u16vec4 Unpack(uninitialize); 437 memcpy(&Unpack, &p, sizeof(Unpack)); 438 return vec4(Unpack) * 1.5259021896696421759365224689097e-5f; // 1.0 / 65535.0 439 } 440 441 GLM_FUNC_QUALIFIER uint16 packSnorm1x16(float v) 442 { 443 int16 const Topack = static_cast<int16>(round(clamp(v ,-1.0f, 1.0f) * 32767.0f)); 444 uint16 Packed = 0; 445 memcpy(&Packed, &Topack, sizeof(Packed)); 446 return Packed; 447 } 448 449 GLM_FUNC_QUALIFIER float unpackSnorm1x16(uint16 p) 450 { 451 int16 Unpack = 0; 452 memcpy(&Unpack, &p, sizeof(Unpack)); 453 return clamp( 454 static_cast<float>(Unpack) * 3.0518509475997192297128208258309e-5f, //1.0f / 32767.0f, 455 -1.0f, 1.0f); 456 } 457 458 GLM_FUNC_QUALIFIER uint64 packSnorm4x16(vec4 const & v) 459 { 460 i16vec4 const Topack(round(clamp(v ,-1.0f, 1.0f) * 32767.0f)); 461 uint64 Packed = 0; 462 memcpy(&Packed, &Topack, sizeof(Packed)); 463 return Packed; 464 } 465 466 GLM_FUNC_QUALIFIER vec4 unpackSnorm4x16(uint64 p) 467 { 468 i16vec4 Unpack(uninitialize); 469 memcpy(&Unpack, &p, sizeof(Unpack)); 470 return clamp( 471 vec4(Unpack) * 3.0518509475997192297128208258309e-5f, //1.0f / 32767.0f, 472 -1.0f, 1.0f); 473 } 474 475 GLM_FUNC_QUALIFIER uint16 packHalf1x16(float v) 476 { 477 int16 const Topack(detail::toFloat16(v)); 478 uint16 Packed = 0; 479 memcpy(&Packed, &Topack, sizeof(Packed)); 480 return Packed; 481 } 482 483 GLM_FUNC_QUALIFIER float unpackHalf1x16(uint16 v) 484 { 485 int16 Unpack = 0; 486 memcpy(&Unpack, &v, sizeof(Unpack)); 487 return detail::toFloat32(Unpack); 488 } 489 490 GLM_FUNC_QUALIFIER uint64 packHalf4x16(glm::vec4 const & v) 491 { 492 i16vec4 const Unpack( 493 detail::toFloat16(v.x), 494 detail::toFloat16(v.y), 495 detail::toFloat16(v.z), 496 detail::toFloat16(v.w)); 497 uint64 Packed = 0; 498 memcpy(&Packed, &Unpack, sizeof(Packed)); 499 return Packed; 500 } 501 502 GLM_FUNC_QUALIFIER glm::vec4 unpackHalf4x16(uint64 v) 503 { 504 i16vec4 Unpack(uninitialize); 505 memcpy(&Unpack, &v, sizeof(Unpack)); 506 return vec4( 507 detail::toFloat32(Unpack.x), 508 detail::toFloat32(Unpack.y), 509 detail::toFloat32(Unpack.z), 510 detail::toFloat32(Unpack.w)); 511 } 512 513 GLM_FUNC_QUALIFIER uint32 packI3x10_1x2(ivec4 const & v) 514 { 515 detail::i10i10i10i2 Result; 516 Result.data.x = v.x; 517 Result.data.y = v.y; 518 Result.data.z = v.z; 519 Result.data.w = v.w; 520 return Result.pack; 521 } 522 523 GLM_FUNC_QUALIFIER ivec4 unpackI3x10_1x2(uint32 v) 524 { 525 detail::i10i10i10i2 Unpack; 526 Unpack.pack = v; 527 return ivec4( 528 Unpack.data.x, 529 Unpack.data.y, 530 Unpack.data.z, 531 Unpack.data.w); 532 } 533 534 GLM_FUNC_QUALIFIER uint32 packU3x10_1x2(uvec4 const & v) 535 { 536 detail::u10u10u10u2 Result; 537 Result.data.x = v.x; 538 Result.data.y = v.y; 539 Result.data.z = v.z; 540 Result.data.w = v.w; 541 return Result.pack; 542 } 543 544 GLM_FUNC_QUALIFIER uvec4 unpackU3x10_1x2(uint32 v) 545 { 546 detail::u10u10u10u2 Unpack; 547 Unpack.pack = v; 548 return uvec4( 549 Unpack.data.x, 550 Unpack.data.y, 551 Unpack.data.z, 552 Unpack.data.w); 553 } 554 555 GLM_FUNC_QUALIFIER uint32 packSnorm3x10_1x2(vec4 const & v) 556 { 557 detail::i10i10i10i2 Result; 558 Result.data.x = int(round(clamp(v.x,-1.0f, 1.0f) * 511.f)); 559 Result.data.y = int(round(clamp(v.y,-1.0f, 1.0f) * 511.f)); 560 Result.data.z = int(round(clamp(v.z,-1.0f, 1.0f) * 511.f)); 561 Result.data.w = int(round(clamp(v.w,-1.0f, 1.0f) * 1.f)); 562 return Result.pack; 563 } 564 565 GLM_FUNC_QUALIFIER vec4 unpackSnorm3x10_1x2(uint32 v) 566 { 567 detail::i10i10i10i2 Unpack; 568 Unpack.pack = v; 569 vec4 Result; 570 Result.x = clamp(float(Unpack.data.x) / 511.f, -1.0f, 1.0f); 571 Result.y = clamp(float(Unpack.data.y) / 511.f, -1.0f, 1.0f); 572 Result.z = clamp(float(Unpack.data.z) / 511.f, -1.0f, 1.0f); 573 Result.w = clamp(float(Unpack.data.w) / 1.f, -1.0f, 1.0f); 574 return Result; 575 } 576 577 GLM_FUNC_QUALIFIER uint32 packUnorm3x10_1x2(vec4 const & v) 578 { 579 uvec4 const Unpack(round(clamp(v, 0.0f, 1.0f) * vec4(1023.f, 1023.f, 1023.f, 3.f))); 580 581 detail::u10u10u10u2 Result; 582 Result.data.x = Unpack.x; 583 Result.data.y = Unpack.y; 584 Result.data.z = Unpack.z; 585 Result.data.w = Unpack.w; 586 return Result.pack; 587 } 588 589 GLM_FUNC_QUALIFIER vec4 unpackUnorm3x10_1x2(uint32 v) 590 { 591 vec4 const ScaleFactors(1.0f / 1023.f, 1.0f / 1023.f, 1.0f / 1023.f, 1.0f / 3.f); 592 593 detail::u10u10u10u2 Unpack; 594 Unpack.pack = v; 595 return vec4(Unpack.data.x, Unpack.data.y, Unpack.data.z, Unpack.data.w) * ScaleFactors; 596 } 597 598 GLM_FUNC_QUALIFIER uint32 packF2x11_1x10(vec3 const & v) 599 { 600 return 601 ((detail::floatTo11bit(v.x) & ((1 << 11) - 1)) << 0) | 602 ((detail::floatTo11bit(v.y) & ((1 << 11) - 1)) << 11) | 603 ((detail::floatTo10bit(v.z) & ((1 << 10) - 1)) << 22); 604 } 605 606 GLM_FUNC_QUALIFIER vec3 unpackF2x11_1x10(uint32 v) 607 { 608 return vec3( 609 detail::packed11bitToFloat(v >> 0), 610 detail::packed11bitToFloat(v >> 11), 611 detail::packed10bitToFloat(v >> 22)); 612 } 613 614 GLM_FUNC_QUALIFIER uint32 packF3x9_E1x5(vec3 const & v) 615 { 616 float const SharedExpMax = (pow(2.0f, 9.0f - 1.0f) / pow(2.0f, 9.0f)) * pow(2.0f, 31.f - 15.f); 617 vec3 const Color = clamp(v, 0.0f, SharedExpMax); 618 float const MaxColor = max(Color.x, max(Color.y, Color.z)); 619 620 float const ExpSharedP = max(-15.f - 1.f, floor(log2(MaxColor))) + 1.0f + 15.f; 621 float const MaxShared = floor(MaxColor / pow(2.0f, (ExpSharedP - 16.f - 9.f)) + 0.5f); 622 float const ExpShared = MaxShared == pow(2.0f, 9.0f) ? ExpSharedP + 1.0f : ExpSharedP; 623 624 uvec3 const ColorComp(floor(Color / pow(2.f, (ExpShared - 15.f - 9.f)) + 0.5f)); 625 626 detail::u9u9u9e5 Unpack; 627 Unpack.data.x = ColorComp.x; 628 Unpack.data.y = ColorComp.y; 629 Unpack.data.z = ColorComp.z; 630 Unpack.data.w = uint(ExpShared); 631 return Unpack.pack; 632 } 633 634 GLM_FUNC_QUALIFIER vec3 unpackF3x9_E1x5(uint32 v) 635 { 636 detail::u9u9u9e5 Unpack; 637 Unpack.pack = v; 638 639 return vec3(Unpack.data.x, Unpack.data.y, Unpack.data.z) * pow(2.0f, Unpack.data.w - 15.f - 9.f); 640 } 641 642 template <precision P, template <typename, precision> class vecType> 643 GLM_FUNC_QUALIFIER vecType<uint16, P> packHalf(vecType<float, P> const & v) 644 { 645 return detail::compute_half<P, vecType>::pack(v); 646 } 647 648 template <precision P, template <typename, precision> class vecType> 649 GLM_FUNC_QUALIFIER vecType<float, P> unpackHalf(vecType<uint16, P> const & v) 650 { 651 return detail::compute_half<P, vecType>::unpack(v); 652 } 653 654 template <typename uintType, typename floatType, precision P, template <typename, precision> class vecType> 655 GLM_FUNC_QUALIFIER vecType<uintType, P> packUnorm(vecType<floatType, P> const & v) 656 { 657 GLM_STATIC_ASSERT(std::numeric_limits<uintType>::is_integer, "uintType must be an integer type"); 658 GLM_STATIC_ASSERT(std::numeric_limits<floatType>::is_iec559, "floatType must be a floating point type"); 659 660 return vecType<uintType, P>(round(clamp(v, static_cast<floatType>(0), static_cast<floatType>(1)) * static_cast<floatType>(std::numeric_limits<uintType>::max()))); 661 } 662 663 template <typename uintType, typename floatType, precision P, template <typename, precision> class vecType> 664 GLM_FUNC_QUALIFIER vecType<floatType, P> unpackUnorm(vecType<uintType, P> const & v) 665 { 666 GLM_STATIC_ASSERT(std::numeric_limits<uintType>::is_integer, "uintType must be an integer type"); 667 GLM_STATIC_ASSERT(std::numeric_limits<floatType>::is_iec559, "floatType must be a floating point type"); 668 669 return vecType<float, P>(v) * (static_cast<floatType>(1) / static_cast<floatType>(std::numeric_limits<uintType>::max())); 670 } 671 672 template <typename intType, typename floatType, precision P, template <typename, precision> class vecType> 673 GLM_FUNC_QUALIFIER vecType<intType, P> packSnorm(vecType<floatType, P> const & v) 674 { 675 GLM_STATIC_ASSERT(std::numeric_limits<intType>::is_integer, "uintType must be an integer type"); 676 GLM_STATIC_ASSERT(std::numeric_limits<floatType>::is_iec559, "floatType must be a floating point type"); 677 678 return vecType<intType, P>(round(clamp(v , static_cast<floatType>(-1), static_cast<floatType>(1)) * static_cast<floatType>(std::numeric_limits<intType>::max()))); 679 } 680 681 template <typename intType, typename floatType, precision P, template <typename, precision> class vecType> 682 GLM_FUNC_QUALIFIER vecType<floatType, P> unpackSnorm(vecType<intType, P> const & v) 683 { 684 GLM_STATIC_ASSERT(std::numeric_limits<intType>::is_integer, "uintType must be an integer type"); 685 GLM_STATIC_ASSERT(std::numeric_limits<floatType>::is_iec559, "floatType must be a floating point type"); 686 687 return clamp(vecType<floatType, P>(v) * (static_cast<floatType>(1) / static_cast<floatType>(std::numeric_limits<intType>::max())), static_cast<floatType>(-1), static_cast<floatType>(1)); 688 } 689 690 GLM_FUNC_QUALIFIER uint8 packUnorm2x4(vec2 const & v) 691 { 692 u32vec2 const Unpack(round(clamp(v, 0.0f, 1.0f) * 15.0f)); 693 detail::u4u4 Result; 694 Result.data.x = Unpack.x; 695 Result.data.y = Unpack.y; 696 return Result.pack; 697 } 698 699 GLM_FUNC_QUALIFIER vec2 unpackUnorm2x4(uint8 v) 700 { 701 float const ScaleFactor(1.f / 15.f); 702 detail::u4u4 Unpack; 703 Unpack.pack = v; 704 return vec2(Unpack.data.x, Unpack.data.y) * ScaleFactor; 705 } 706 707 GLM_FUNC_QUALIFIER uint16 packUnorm4x4(vec4 const & v) 708 { 709 u32vec4 const Unpack(round(clamp(v, 0.0f, 1.0f) * 15.0f)); 710 detail::u4u4u4u4 Result; 711 Result.data.x = Unpack.x; 712 Result.data.y = Unpack.y; 713 Result.data.z = Unpack.z; 714 Result.data.w = Unpack.w; 715 return Result.pack; 716 } 717 718 GLM_FUNC_QUALIFIER vec4 unpackUnorm4x4(uint16 v) 719 { 720 float const ScaleFactor(1.f / 15.f); 721 detail::u4u4u4u4 Unpack; 722 Unpack.pack = v; 723 return vec4(Unpack.data.x, Unpack.data.y, Unpack.data.z, Unpack.data.w) * ScaleFactor; 724 } 725 726 GLM_FUNC_QUALIFIER uint16 packUnorm1x5_1x6_1x5(vec3 const & v) 727 { 728 u32vec3 const Unpack(round(clamp(v, 0.0f, 1.0f) * vec3(31.f, 63.f, 31.f))); 729 detail::u5u6u5 Result; 730 Result.data.x = Unpack.x; 731 Result.data.y = Unpack.y; 732 Result.data.z = Unpack.z; 733 return Result.pack; 734 } 735 736 GLM_FUNC_QUALIFIER vec3 unpackUnorm1x5_1x6_1x5(uint16 v) 737 { 738 vec3 const ScaleFactor(1.f / 31.f, 1.f / 63.f, 1.f / 31.f); 739 detail::u5u6u5 Unpack; 740 Unpack.pack = v; 741 return vec3(Unpack.data.x, Unpack.data.y, Unpack.data.z) * ScaleFactor; 742 } 743 744 GLM_FUNC_QUALIFIER uint16 packUnorm3x5_1x1(vec4 const & v) 745 { 746 u32vec4 const Unpack(round(clamp(v, 0.0f, 1.0f) * vec4(31.f, 31.f, 31.f, 1.f))); 747 detail::u5u5u5u1 Result; 748 Result.data.x = Unpack.x; 749 Result.data.y = Unpack.y; 750 Result.data.z = Unpack.z; 751 Result.data.w = Unpack.w; 752 return Result.pack; 753 } 754 755 GLM_FUNC_QUALIFIER vec4 unpackUnorm3x5_1x1(uint16 v) 756 { 757 vec4 const ScaleFactor(1.f / 31.f, 1.f / 31.f, 1.f / 31.f, 1.f); 758 detail::u5u5u5u1 Unpack; 759 Unpack.pack = v; 760 return vec4(Unpack.data.x, Unpack.data.y, Unpack.data.z, Unpack.data.w) * ScaleFactor; 761 } 762 763 GLM_FUNC_QUALIFIER uint8 packUnorm2x3_1x2(vec3 const & v) 764 { 765 u32vec3 const Unpack(round(clamp(v, 0.0f, 1.0f) * vec3(7.f, 7.f, 3.f))); 766 detail::u3u3u2 Result; 767 Result.data.x = Unpack.x; 768 Result.data.y = Unpack.y; 769 Result.data.z = Unpack.z; 770 return Result.pack; 771 } 772 773 GLM_FUNC_QUALIFIER vec3 unpackUnorm2x3_1x2(uint8 v) 774 { 775 vec3 const ScaleFactor(1.f / 7.f, 1.f / 7.f, 1.f / 3.f); 776 detail::u3u3u2 Unpack; 777 Unpack.pack = v; 778 return vec3(Unpack.data.x, Unpack.data.y, Unpack.data.z) * ScaleFactor; 779 } 780}//namespace glm 781 782