Sign in to follow this  
othello

GLSL: Pack into half floats

Recommended Posts

othello    100
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
Chris_F    3030
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
othello    100
[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
Ashaman73    13715
[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