0

I am trying to do the following in GLSL 2 es:

Given a number (say 4 for example) of normalized var4 variables(RGBA) reduce their bit depth and pack the results in a single 0-1 clamped var4. This will be stored as an 8 bit (per channel) texture and later unpacked. I realize that this will result in quality loss but that is acceptable.

So in this example:

RGBA 8 bit
-> reduced to RGBA 2 bit
-> packed with 3 other RGBA 2 bit var4s
-> saved as single 8 bit RGBA texture
-> unpacked back into 4 x RGBA 2 bit variables
-> scaled back to a reduced quality version of the original.

I realize that I can't do bit-shifting in GLSL so I would have to do some collection of multiplications, the magic combination of which has so far escaped me! Others have talked about packing floats in vec4s but my problem is a little different.

Thanks!

OhBeWise
  • 5,350
  • 3
  • 32
  • 60
Child
  • 3
  • 3

1 Answers1

1

Well, bit shifting can be represented by mulitplication (for left shifts) or division (for right shifts) with powers of two. You just have to take into account that the floats will stroe the fractional parts which would normally be shifted "out" in normal integer bitshifts.

So to pack 4 normalized floats a,b,c,d into a normalized float x, you can simply use

x = 1.0/255.0 * (floor(a*255.0/64.0)*64.0 + floor(b*255.0/64.0)*16.0 + floor(c*255.0/64.0)*4.0 + floor(d*255.0/64.0));

Unpacking is a bit more complicated because you can't simply mask out single bits. Instead, you can subtract the most significant bits as you reconstruct them, for example like this:

a = floor(x*255.0/64.0)*64.0/255.0;
x -= a;
b = floor(x*255.0/16.0)*16.0/255.0;
x -= b;
b *= 4.0;
c = floor(x*255.0/4.0)*4.0/255.0;
x -= c;
c *= 16.0;
d = x*255.0 * 64.0 / 255.0; // scan be simplified to just x*64.0
derhass
  • 43,833
  • 2
  • 57
  • 78
  • Thanks for the reply. However I think something is slightly out here in the packing code: if the floats a, b, c and d are normalized and floored after dividing by 64 they always be 0. Does this packing code assume these variables to be in the range 0-255? – Child May 18 '15 at 09:45
  • @Child: You are right, I had the unnormalized [0,255] range in my mind why a tried to mimic the bit-shifting one would do on integers. I updated my answer. – derhass May 18 '15 at 18:10
  • Thanks, I made the change in my code anyway and it works well! Thanks again. – Child May 19 '15 at 09:24
  • I think there may be something slightly out with the unpack code still - the values calculated are in the range 0-0.75 rather than 0-1. If we take `a` for example - if x has a value 1.0 we get a=0.75 from the first line. I don't think this matters since it's easy enough to correct but I mention it for interest and help to anyone else using the code. – Child May 20 '15 at 08:05