Sign in to follow this  
othello

GLSL: Pack into half floats

Recommended Posts

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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
[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.
[/quote]

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:

[code]
| 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 |
[/code]

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

Share this post


Link to post
Share on other sites
[quote name='othello' timestamp='1307247410' post='4819632']
[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.
[/quote]

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:

[code]
| 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 |
[/code]

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 [url="http://aras-p.info/texts/CompactNormalStorage.html"]here[/url].

2. depth
16bit for depth is too low, use 2 16bit floats (precison ~24 bit):
[code]
encode
float depth = ...
float d_high = floor(depth*1024);
float d_low = fract(depth*1024);

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

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:
[code]
encode
float result = (float)index + alpha

decode
int index = (int)floor(input)
float alpha = fract(alpha)
[/code]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this