I am compressing a string of data in the formats of float. The current approach is throwing away eight bits in the integer part as my float is strictly within [0,1].
I wonder how I could do this.
Computer Graphics Stack Exchange is a question and answer site for computer graphics researchers and programmers. It only takes a minute to sign up.
Sign up to join this communityI am compressing a string of data in the formats of float. The current approach is throwing away eight bits in the integer part as my float is strictly within [0,1].
I wonder how I could do this.
In GLSL use frac to get the fractional part:
float x=1.02;
x = frac(x); // x==0.02 (in C++ use the modf function)
Multiply the fractional part by the max of the accuracy you want:
float accuracy=255; // 8 bits of accuracy (65535 for 16 bits)
x*=255; // x==5.12
Throw away the fractional part:
int y = round(x); // y == 5;
The value is ready to be stored in whatever 8 bit format is need. Such as a texture, or vertex attributes, etc.
To recover the fraction:
float x = (float)value / 255.0; // 5.0/255.0 == 0.01953125
This gives unsigned values between 0 and 1. A similar approach can be used for values between -1 and 1.
Precision is lost to the 8 bit encoding. But like mentioned in the comments that same can be done with 16 bit numbers.
If the values need to be stored in a texture then there are image formats just for this such as UNORM and SNORM. The GPU does the math for these formats when they are read from the texture.
The specs for the different API's provide guidelines on the expected values. The vulkan spec has something close to a function and a good explanation of the conversions it expects.
round()
or similar, rather than a simple cast which truncates.
$\endgroup$
Oct 29, 2022 at 19:03