I'm using Processing(Java) to write shaders that do lots of fancy code art. In my shader code I'm trying to get 2 integers (x,y positions) into an RGBA so I can send this colored pixel back to my Java program - and from there decode this color to get back the original integers. As far a I know, I cant use bitwise operations in GLSL, or least I'd have to re-write a lot of code. So I need to get 2 numbers into an RGBA, or 1 number into 2 bytes (RG) and the other in another 2 bytes (BA) - something like that.. without bitwise.. Help!!
-
If you only have access to a 4byte rgba rendertarget, then you can't store 2 integers = 8byte. You can probably store 2 short. Getting the high and low byte shouldn't be a problem with shift operators (available in glsl > 130). I don't think it is possible to do what you want completely without bit manipulation. Also, don't forget to handle the sign. – BDL Jun 09 '20 at 20:56
-
but i could store 1 integer in 2 bytes (0....65536 range)? and another integer in the other 2 bytes. I've seen it done in glsl on the web, but they use bit operations glsl 130 - maybe ill just try and use those. – Glenn Marshall Jun 09 '20 at 22:40
1 Answers
First we must take into account the MSB/LSB order on CPU side and internal format of GPU render buffer. The simplest way to check the order is to set color in GLSL with different channels and read it on CPU side as hex number so:
in GLSL set color to
vec4(0.1,0.2,0.3,0.4);
(r,g,b,a)read the color on CPU side and print it as HEX
the channels are:
chn float BYTE [dec] [hex] r = 0.1 -> 255*0.1 -> 19h g = 0.2 -> 255*0.1 -> 33h b = 0.3 -> 255*0.1 -> 4Ch a = 0.4 -> 255*0.1 -> 66h
Your output was
0x6619334C
which identifies the order ofr,g,b,a
as:MSB ....... LSB 66 19 33 4C hex (4xBYTE) 0.4 0.1 0.2 0.3 dec (4xfloat) a r g b
so we can encode x,y for example like this:
MSB ....... LSB a r g b Yh Yl Xh Xl
In case your
a
channel is not correct check if your render buffer has allocated 8 bits for alpha channel during OpenGL context creation (look for pixel format descriptor) and repair if not.In case you are using this for different render targets each can have different internal format so you need to check this for each separately.
Another problem is that your color on GLSL side is most likely a vec4
and not integer type so you need to use floats
... Also %
requires extention so to avoid that compute it by /
like this:
unsigned int x,y; // 2x16 bit integer
vec4 xy; // 4xfloat (32 bit color)
unsigned int h,l; // temp
h=x/256u; l=x-(256u*h);
xy.b=float(l)/255.0;
xy.g=float(h)/255.0;
h=y/256u; l=y-(256u*h);
xy.r=float(l)/255.0;
xy.a=float(h)/255.0;
Now the extraction of x,y
back on CPU side:
unsigned int rgba; // input 32 bit color
unsigned int x,y; // output 16 bit x,y
y=(rgba>>16)&0x0000FFFF;
x=(rgba )&0x0000FFFF;

- 49,595
- 11
- 110
- 380
-
hey thanks this looks interesting - I did manage to get something similar working by splitting into rg, ba - but I think the precision was off a bit - I only needed a range of about 0-4000 for x,y - but the results had the odd error - I'll try yours to see if it improves. thanks.. – Glenn Marshall Jun 12 '20 at 06:33
-
@GlennMarshall You can use this [GLSL debug prints](https://stackoverflow.com/a/44797902/2521214) to check the contents of your variables along the way. – Spektre Jun 12 '20 at 06:36
-
-
@GlennMarshall yep and really fun:) just be sure that whole area where you print has the same GLSL outcome for printing otherwise it would be gibberish as each fragment can have different number for printing ... I would never get working stuff like this [GLSL ray tracer](https://stackoverflow.com/a/45140313/2521214) without it ... – Spektre Jun 12 '20 at 07:28
-
oh while you're there - can you help me with the code to extract the x,y values from the rgba above - im trying to this myself at the minute - in java – Glenn Marshall Jun 12 '20 at 07:33
-
basically my shader draws the pixel onto a 1x1 quad - then in my java program - i read this pixel as 4x8 bit values - i.e. red =0...255 green 0..255 etc – Glenn Marshall Jun 12 '20 at 07:44
-
-
-
-
it works! just implementing in my full program now to see there are no errors... – Glenn Marshall Jun 12 '20 at 08:16
-
@GlennMarshall If the answer is solving your problem you should accept it (click on the checker in upper left corner of answer) for others to quickly see what solved your problem or if you still need an answer.. However do not accept if your problem is not fully solved. In such case comment to clarify/request what you need ... Once you got more reputation you will be able to also up/down vote to mark what is helpful and what not ... – Spektre Jun 12 '20 at 08:25
-
it all works! my code now runs twice as fast thank you so much.. – Glenn Marshall Jun 12 '20 at 08:59