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\$
4
  • \$\begingroup\$ Also, I'll monitor this question and vote for good answers! \$\endgroup\$
    – Olhovsky
    Jan 29, 2011 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, 2011 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, 2011 at 20:03
  • 1
    \$\begingroup\$ What about use 8R8G8B8A used four times? Isn't it easier? \$\endgroup\$
    – Notabene
    Jan 31, 2011 at 13:38

1 Answer 1

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);
}
\$\endgroup\$
4
  • \$\begingroup\$ Oopsie, this was in glsl - I'm fairly certain hlsl isn't far off, though. \$\endgroup\$ Jan 31, 2011 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, 2011 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, 2011 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\$ Jan 31, 2011 at 8:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .