I'm writing a shader (HLSL), and I need to pack a color value into the R32 format. I've found various pieces of code for packing a float into the R8G8B8A8 format, but none of them seem to work in reverse. I'm targeting SM3.0, so (afaik) bit operations are not an option.
To sum it up, I need to be able to do this:
float4 color = ...; // Where color ranges from 0 -> 1
float packedValue = pack(color);
Anyone know how to do this?
UPDATE
I've gotten some headway... perhaps this will help to clarify the question.
My temporary solution is as such:
const int PRECISION = 64;
float4 unpack(float value)
{
float4 color;
color.a = value % PRECISION;
value = floor(value / PRECISION);
color.b = value % PRECISION;
value = floor(value / PRECISION);
color.g = value % PRECISION;
value = floor(value / PRECISION);
color.r = value;
return color / (PRECISION - 1);
}
float pack(float4 color)
{
int4 iVal = floor(color * (PRECISION - 1));
float output = 0;
output += iVal.r * PRECISION * PRECISION * PRECISION;
output += iVal.g * PRECISION * PRECISION;
output += iVal.b * PRECISION;
output += iVal.a;
return output;
}
I'm basically... pretending I'm using integer types :s
Through guess and check, 64 was the highest number I could use while still maintaining a [0...1] range. Unfortunately, that also means I'm losing some precision - 6 bits instead of 8.
Have a look at: http://diaryofagraphicsprogrammer.blogspot.com/2009/10/bitmasks-packing-data-into-fp-render.html
The short answer is that it's not possible to do a lossless packing of 4 floats into 1 float.
Even if you do find a way to pack 4 floats, storing their exponent and significand, the packing and unpacking process may be prohibitively expensive.