5
\$\begingroup\$

I can't find any useful information on packing 4 values into a 32 bit float in HLSL.

Ideally, what I want to be able to do in HLSL is:

float4 values = ... // Some values where each component is between 0 and 1.
float packedValues = pack32R(values);
float4 values2 = unpack32R(packedValues);

I realize that there will be precision limitations, and performance tradeoffs between different precisions in different methods. I'm just wondering what ideas are out there.

\$\endgroup\$
  • \$\begingroup\$ Also, I'll monitor this question and vote for good answers! \$\endgroup\$ – Olhovsky Jan 29 '11 at 19:34
  • \$\begingroup\$ Is there a reason you must pack the data into a float, or would packing them into a 32 bit integer as a fixed point format work? \$\endgroup\$ – user744 Jan 29 '11 at 19:49
  • \$\begingroup\$ I'm using 32R32R32R32R and want to maximize the amount of data that I can fit in there. So it has to be a float. \$\endgroup\$ – Olhovsky Jan 29 '11 at 20:03
  • 1
    \$\begingroup\$ What about use 8R8G8B8A used four times? Isn't it easier? \$\endgroup\$ – Notabene Jan 31 '11 at 13:38
4
\$\begingroup\$

32bit floats have 24 bits of significant precision, so the best precision you're going to get is 6 bits per component.

I haven't tested this, but basically all you need is:

// C side, params in 0..63 ints
#define PACKI(a,b,c,d) ((a) << 18) | ((b) << 12) | ((c) << 6) | (d)
// C side, params in 0..1 floats
#define PACKF(a,b,c,d) \
 ((int)floor((a)*63) << 18) | \
 ((int)floor((b)*63) <<  12) | \
 ((int)floor((c)*63) <<   6) | \
 ((int)floor((d)*63))

// GLSL side
vec4 unpack(float i)
{
   return mod(vec4(i / 262144.0, i / 4096.0, i / 64.0, i), 64.0);
}
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Oopsie, this was in glsl - I'm fairly certain hlsl isn't far off, though. \$\endgroup\$ – Jari Komppa Jan 31 '11 at 8:41
  • \$\begingroup\$ The HLSL is almost the same, however, bitshifts cant be used on floats in SM 3.0. Can I safely replace those shifts with multiplies? E.g. << 8 becomes *= 2^18? \$\endgroup\$ – Olhovsky Jan 31 '11 at 8:44
  • \$\begingroup\$ Also, the bitwise OR operation is not permitted on floats in SM 3.0. Correct me if I'm wrong. en.wikipedia.org/wiki/High_Level_Shader_Language \$\endgroup\$ – Olhovsky Jan 31 '11 at 8:45
  • 1
    \$\begingroup\$ You can safely replace shifts with multiples, but like I commented above, those #defines are for C side. ORs can be replaced with additions. \$\endgroup\$ – Jari Komppa Jan 31 '11 at 8:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.