5

I'm working on an application where I would like to take a single integer input (basically a color) and, using WebGL shaders, color a box with the given input. I planned, originally, to do this with a combination of shifts & a mask as demonstrated below:

uniform int u_color;

float rValue = (((u_color) >> 16) & 0xFF) / 255.0;
float gValue = (((u_color) >> 8) & 0xFF) / 255.0;
float bValue = ((u_color) & 0xFF) / 255.0;
gl_FragColor = vec4(rValue, gValue, bValue, 1.0);

so given the int 0xFF33CC, red=1.0, green=0.2, blue=0.8

However, I ran into a problem and found out that WebGL shaders can't perform bitwise shifts.

I'm wondering how would I be able to efficiently produce the proper FragColor from the given integer, if that's even possible.

EDIT: After a bit of trial and error, and thanks to @Jongware, I've come up with a solution

uniform int u_color;
float rValue = float(u_color / 256 / 256);
float gValue = float(u_color / 256 - int(rValue * 256.0));
float bValue = float(u_color - int(rValue * 256.0 * 256.0) - int(gValue * 256.0));
gl_FragColor = vec4(rValue / 255.0, gValue / 255.0, bValue / 255.0, 1.0);

Other than a clean up, this code is perfect for the job, however I'd always be interested in any other methods different from the one mentioned above.

genpfault
  • 51,148
  • 11
  • 85
  • 139
Alex Roth
  • 152
  • 2
  • 8
  • 2
    Without bit shifting, you can use `/ 256` and `/ 65536`. (But do check if this does not automatically convert your numbers to floats. If they do, you may also need to use mod `%` instead of and `&`.) – Jongware Apr 06 '14 at 15:10
  • Thanks, I was actually working on that when you suggested that! – Alex Roth Apr 06 '14 at 15:27
  • It seems to be the common accepted answer: http://stackoverflow.com/questions/18453302/how-do-you-pack-one-32bit-int-into-4-8bit-ints-in-glsl-webgl. As "efficiency" goes, I hope your constants get folded by the fragment compiler. – Jongware Apr 06 '14 at 15:30

1 Answers1

5

To add to your own answer, consider staying with integer math until the end.

uniform int u_color;
unsigned rIntValue = (u_color / 256 / 256) % 256;
unsigned gIntValue = (u_color / 256      ) % 256;
unsigned bIntValue = (u_color            ) % 256;
gl_FragColor = vec4(rIntValue / 255.0f, gIntValue / 255.0f, bIntValue / 255.0f, 1.0);
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • I get error "integer modulus operator supported in GLSL ES 3.0 and above only" regardless of whether I'm using floats or ints. – Curtis Sep 02 '19 at 21:40
  • @Curtis T'is a C solution as question is tagged C. [This](https://stackoverflow.com/questions/33908644/get-accurate-integer-modulo-in-webgl-shader#comment86946387_48909461) may help. – chux - Reinstate Monica Sep 02 '19 at 21:51