This question is very related to the question here(How do I convert a vec4 rgba value to a float?).
There is some of articles or questions related to this question already, but I wonder most of articles are not identifying which type of floating value. As long as I can come up with, there is some of floating value packing/unpacking formula below.
- unsigned normalized float
- signed normalized float
- signed ranged float (the floating value I can find range limitation)
- unsigned ranged float
- unsigned float
- signed float
However, these are just 2 case actually. The other packing/unpacking can be processed by these 2 method.
- unsigned ranged float (I can pack/unpack by easy bitshifting)
- signed float
I want to pack and unpack signed floating values into vec3 or vec2 also.
For my case, the floating value is not ensured to be normalized, so I can not use the simple bitshifting way.
If you know the max range of values you want to store, say +5 to -5, than the easiest way is just to pick some convert that range to a value from 0 to 1. Expand that to the number of bits you have and then break it into parts.
To put it back you do the opposite. Assemble the parts, divide to get back to a zeroToOne value, then expand by the range.
For vec3 just expand it
In order to pack a floating-point value in a
vec2
,vec3
orvec4
, either the range of the source values has to be restricted and well specified, or the exponent has to be stored somehow too.In general, if the significant digits of a floating-point number should be pack in bytes, consecutively 8 bits packages have to be extract from the the significant digits and have to be stored in a byte.
Encode a floating point number in a restricted and predefined range
A value range [
minVal
,maxVal
] must be defined which includes all values that are to be encoded and the value range must be mapped to the range from [0.0, 1.0].Encoding of a floating point number in the range [
minVal
,maxVal
] tovec2
,vec3
andvec4
:Decodeing of a
vec2
,vec3
andvec4
to a floating point number in the range [minVal
,maxVal
]:Note,Since a standard 32-bit [IEEE 754][2] number has only 24 significant digits, it is completely sufficient to encode the number in 3 bytes.
Encode the significant digits and the exponent of a floating point number
Encoding of the significant digits of a floating point number and its exponent to
vec2
,vec3
andvec4
:Decoding of a
vec2
,vec3
andvec4
to he significant digits of a floating point number and its exponent:See also the answer to the following question:
I tested gman's solution and found that the scale factor was incorrect, and it produced roundoff errors, and there needs to be an additional division by 255.0 if you want to store the result in a RGB texture. So this is my revised solution:
Example:
I have written small example few days ago with shadertoy: https://www.shadertoy.com/view/XdK3Dh
It stores float as RGB or load float from pixel. There is also test that function are exact inverses (lot of other functions i have seen has bug in some ranges because of bad precision).
Entire example assumes you want to save values in buffer and read it back in next draw. Having only 256 colors, it limits you to get 16777216 different values. Most of the time I dont need larger scale. I also shifted it to have signed float insted in interval <-8388608;8388608>.
One more thing, values that overflow will be rounded to min/max value.