GLSL: Pack into half floats

Started by
2 comments, last by Ashaman73 12 years, 10 months ago
Hi,
I was wondering if anyone had any ideas on how to pack and unpack 2 floating point values into a single float16, in glsl? Loss of precision is acceptable. I am trying to add extra attributes into my gbuffer, so I am trying to pack normal values to save space. My gbuffer is 4 framebuffers, with 16-bit float storage per channel.
Thanks
-othello
Advertisement
You really think float16 is precise enough for your normals?

You could just store your normal buffer in spherical coordinates, which cuts it down to 2 channels instead of 3. This is a common approach and shouldn't effect your precision.

You really think float16 is precise enough for your normals?

You could just store your normal buffer in spherical coordinates, which cuts it down to 2 channels instead of 3. This is a common approach and shouldn't effect your precision.


Sorry, I wasn't completely clear. I would be storing each component into a byte. So if I'm storing emission, for example, in the buffer:


| 16 bits | 16 bits | 16 bits | 16 bits |
| buff_r | buff_g | buff_b | buff_a |
| n.x | n.y | n.z | pad | e.r | e.g | e.b | pad |


A conversion to fixed point bytes is probably necessary for the attributes.

[quote name='Chris_F' timestamp='1307246947' post='4819629']
You really think float16 is precise enough for your normals?

You could just store your normal buffer in spherical coordinates, which cuts it down to 2 channels instead of 3. This is a common approach and shouldn't effect your precision.


Sorry, I wasn't completely clear. I would be storing each component into a byte. So if I'm storing emission, for example, in the buffer:


| 16 bits | 16 bits | 16 bits | 16 bits |
| buff_r | buff_g | buff_b | buff_a |
| n.x | n.y | n.z | pad | e.r | e.g | e.b | pad |


A conversion to fixed point bytes is probably necessary for the attributes.
[/quote]
Frist off, you can't divide a floating point number simple into two parts, for this you should use an integer format (not greatly supported by older hardware).

For my deferred rendering engine I always use 16bit floats for all rendering targets. Here are some tips to compress low and high detail data:
1. normals
As already mentionend, try to use normal compression (3 component => 2 component) to save some space. Take a look at aras normal compression page over here.

2. depth
16bit for depth is too low, use 2 16bit floats (precison ~24 bit):

encode
float depth = ...
float d_high = floor(depth*1024);
float d_low = fract(depth*1024);

decode
float depth = (d_high+d_low)/1024;


3. flags
For flags use simply the sign.

4. int + float[0..1)
Sometimes an index plus an alpha value [0..0.99999] are useful and these values can simply be compressed into a single float by:

encode
float result = (float)index + alpha

decode
int index = (int)floor(input)
float alpha = fract(alpha)

This topic is closed to new replies.

Advertisement