如何快速将浮点数打包为4个字节? [英] How to quickly pack a float to 4 bytes?
问题描述
我一直在寻找一种在WebGL纹理上存储浮点的方法.我找到了一些解决方案在互联网上,但那些仅处理[0..1)范围内的浮点数.我希望能够存储任意浮点数,为此,需要扩展此类函数以存储指数(例如,在第一个字节上).不过,我不太了解这些功能是如何工作的,因此如何运行尚不明确.简而言之:
I've been looking for a way to store floats on WebGL textures. I've found some solutions on the internet, but those only deal with floats on the [0..1) range. I'd like to be able to store arbitrary floats, and, for that, such a function would need to be extended to also store the exponent (on the first byte, say). I don't quite understand how those work, though, so it is not obvious how to do so. In short:
什么是将浮点数打包为4个字节的有效算法?
推荐答案
这不是很快,但是可行.(请注意,GLSL 1.00浮点文字在编译器中存在转换错误).
It's not fast, but doable. (Note that GLSL 1.00 floating point literals have conversion bugs in the compiler).
struct Bitset8Bits {
mediump vec4 bit0;
mediump vec4 bit1;
mediump vec4 bit2;
mediump vec4 bit3;
mediump vec4 bit4;
mediump vec4 bit5;
mediump vec4 bit6;
mediump vec4 bit7;
};
vec4 when_gt (vec4 l, vec4 r) {
return max(sign(l - r), 0.0);
}
Bitset8Bits unpack_4_bytes (lowp vec4 byte) {
Bitset8Bits result;
result.bit7 = when_gt(byte, vec4(127.5));
vec4 bits0to6 = byte - 128.0 * result.bit7;
result.bit6 = when_gt(bits0to6, vec4(63.5));
vec4 bits0to5 = bits0to6 - 64.0 * result.bit6;
result.bit5 = when_gt(bits0to5, vec4(31.5));
vec4 bits0to4 = bits0to5 - 32.0 * result.bit5;
result.bit4 = when_gt(bits0to4, vec4(15.5));
vec4 bits0to3 = bits0to4 - 16.0 * result.bit4;
result.bit3 = when_gt(bits0to3, vec4(7.5));
vec4 bits0to2 = bits0to3 - 8.0 * result.bit3;
result.bit2 = when_gt(bits0to2, vec4(3.5));
vec4 bits0to1 = bits0to2 - 4.0 * result.bit2;
result.bit1 = when_gt(bits0to1, vec4(1.5));
vec4 bit0 = bits0to1 - 2.0 * result.bit1;
result.bit0 = when_gt(bit0, vec4(0.5));
return result;
}
float when_gt (float l, float r) {
return max(sign(l - r), 0.0);
}
vec4 pack_4_bytes (Bitset8Bits state) {
vec4 data;
data = state.bit0
+ 2.0 * state.bit1
+ 4.0 * state.bit2
+ 8.0 * state.bit3
+ 16.0 * state.bit4
+ 32.0 * state.bit5
+ 64.0 * state.bit6
+ 128.0 * state.bit7;
return data;
}
vec4 brians_float_pack (
float original_value) {
// Remove the sign
float pos_value = abs(original_value);
float exp_real = floor(log2(pos_value));
float multiplier = pow(2.0, exp_real);
float normalized = pos_value / multiplier - 1.0;
float exp_v = exp_real + 127.0;
// if exp_v == -Inf -> 0
// if exp_v == +Inf -> 255
// if exp_v < -126.0 -> denormalized (remove the "1")
// otherwise + 127.0;
Bitset8Bits packed_v;
packed_v.bit7.a =
step(sign(original_value) - 1.0, -1.5); // pos
// Exponent 8 bits
packed_v.bit6.a = when_gt(exp_v, 127.5);
float bits0to6 = exp_v - 128.0 * packed_v.bit6.a;
packed_v.bit5.a = when_gt(bits0to6, 63.5);
float bits0to5 = bits0to6 - 64.0 * packed_v.bit5.a;
packed_v.bit4.a = when_gt(bits0to5, 31.5);
float bits0to4 = bits0to5 - 32.0 * packed_v.bit4.a;
packed_v.bit3.a = when_gt(bits0to4, 15.5);
float bits0to3 = bits0to4 - 16.0 * packed_v.bit3.a;
packed_v.bit2.a = when_gt(bits0to3, 7.5);
float bits0to2 = bits0to3 - 8.0 * packed_v.bit2.a;
packed_v.bit1.a = when_gt(bits0to2, 3.5);
float bits0to1 = bits0to2 - 4.0 * packed_v.bit1.a;
packed_v.bit0.a = when_gt(bits0to1, 1.5);
float bit0 = bits0to1 - 2.0 * packed_v.bit0.a;
packed_v.bit7.b = when_gt(bit0, 0.5);
// Significand 23 bits
float factor = 0.5;
// 0.4999999
// Significand MSB bit 22:
packed_v.bit6.b =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit6.b;
factor = 0.5 * factor;
packed_v.bit5.b =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit5.b;
factor = 0.5 * factor;
packed_v.bit4.b =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit4.b;
factor = 0.5 * factor;
packed_v.bit3.b =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit3.b;
factor = 0.5 * factor;
packed_v.bit2.b =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit2.b;
factor = 0.5 * factor;
packed_v.bit1.b =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit1.b;
factor = 0.5 * factor;
packed_v.bit0.b =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit0.b;
factor = 0.5 * factor;
packed_v.bit7.g =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit7.g;
factor = 0.5 * factor;
packed_v.bit6.g =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit6.g;
factor = 0.5 * factor;
packed_v.bit5.g =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit5.g;
factor = 0.5 * factor;
packed_v.bit4.g =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit4.g;
factor = 0.5 * factor;
packed_v.bit3.g =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit3.g;
factor = 0.5 * factor;
packed_v.bit2.g =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit2.g;
factor = 0.5 * factor;
packed_v.bit1.g =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit1.g;
factor = 0.5 * factor;
packed_v.bit0.g =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit0.g;
factor = 0.5 * factor;
packed_v.bit7.r =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit7.r;
factor = 0.5 * factor;
packed_v.bit6.r =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit6.r;
factor = 0.5 * factor;
packed_v.bit5.r =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit5.r;
factor = 0.5 * factor;
packed_v.bit4.r =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit4.r;
factor = 0.5 * factor;
packed_v.bit3.r =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit3.r;
factor = 0.5 * factor;
packed_v.bit2.r =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit2.r;
factor = 0.5 * factor;
packed_v.bit1.r =
when_gt(normalized, factor - 0.00000005);
normalized = normalized - factor * packed_v.bit1.r;
factor = 0.5 * factor;
// LSB bit 0
packed_v.bit0.r =
when_gt(normalized, factor - 0.00000005);
vec4 result = pack_4_bytes(packed_v);
return result;
}
这篇关于如何快速将浮点数打包为4个字节?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!