Created
January 13, 2019 17:49
-
-
Save kaneta1992/f4c19ec069903fb6c94af33dc72be034 to your computer and use it in GitHub Desktop.
GLSLで使いたいのでビット演算を使わずにfloatをunsigned char 4つにパック・アンパックする
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cmath> | |
#include <limits> | |
#include <iostream> | |
struct ivec4 { | |
unsigned char x, y, z, w; | |
}; | |
float fract(float x) { | |
return x - std::floorf(x); | |
} | |
float sign(float x) { | |
if (x > 0.0f) { | |
return 1.0f; | |
} | |
else if (x == 0.0f) { | |
return 0.0f; | |
} | |
else { | |
return -1.0f; | |
} | |
} | |
unsigned char step(float a, float b) { | |
return a <= b ? 1 : 0; | |
} | |
ivec4 packn(float val) { | |
float a = fract(val); | |
float b = fract(val * 256.0f); | |
float c = fract(val * 256.0f * 256.0f); | |
ivec4 ret; | |
ret.y = unsigned char(a * 256.0f); | |
ret.z = unsigned char(b * 256.0f); | |
ret.w = unsigned char(c * 128.0f); | |
return ret; | |
} | |
float unpackn(ivec4 packed) { | |
return (packed.y / 256.0f) + (packed.z / 256.0f / 256.0f) + (packed.w / 128.0f / 256.0f / 256.0f); | |
} | |
ivec4 pack(float val) { | |
float s = sign(val); | |
val *= s; | |
float log = std::log2f(val); | |
float exp = std::floorf(log); | |
float pow = std::powf(2.0f, exp); | |
float m = val / pow; | |
ivec4 packed = packn(m - 1.0f); | |
packed.x = unsigned char(exp + 127.0f); | |
packed.w += step(s, 0.0) * 128; | |
return packed; | |
} | |
float unpack(ivec4 packed) { | |
float e = float(packed.x - 127.0f); | |
float f = std::floorf(float(packed.w / 128.0f)); | |
float s = sign(f - 0.5f); | |
packed.w -= unsigned char(f * 128); | |
float m = unpackn(packed) + 1.0f; | |
return m * std::powf(2.0f, float(e)) * -s; | |
} | |
int main() { | |
std::cout << std::fixed; | |
float val = 0.114514f; | |
ivec4 packed = packn(val); | |
std::cout << "val = " << val << " unpacked = " << unpackn(packed) << std::endl; | |
val = -121.0001f; | |
packed = pack(val); | |
std::cout << "val = " << val << " unpacked = " << unpack(packed) << std::endl; | |
val = 114514.1919f; | |
packed = pack(val); | |
std::cout << "val = " << val << " unpacked = " << unpack(packed) << std::endl; | |
val = 456.4322f; | |
packed = pack(val); | |
std::cout << "val = " << val << " unpacked = " << unpack(packed) << std::endl; | |
val = -0.000012f; | |
packed = pack(val); | |
std::cout << "val = " << val << " unpacked = " << unpack(packed) << std::endl; | |
val = 1.0f; | |
packed = pack(val); | |
std::cout << "val = " << val << " unpacked = " << unpack(packed) << std::endl; | |
val = 0.0f; | |
packed = pack(val); | |
std::cout << "val = " << val << " unpacked = " << unpack(packed) << std::endl; | |
getchar(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment