okay, i got it. I think you don’t have to improve the performance for this.
If I was doing this, i would either write monocrhome color into the uniform upon the toggle, or I would implement HSL filter, where I would break-down rgb color into HSL and combine it with some specified HSL uniform, this essentially gives you 3 filters:
- tint / hue-roate
Generally a few conditions (branches) inside the shader are ok, they are not evil. If your condition is not nested and it evaluates to the same value for every pixel (fragment) it should have little to no overhead.
I suggest you pick a target device, run your shader there and see how long it takes to render a frame, if it’s below 15ms (for 60fps) - you’re pretty much golden. There are caveats, such as browser doing it’s thing, and having budget to handle user input etc. I would recommend that anything that renders in 7ms or so doesn’t need optimization, your users won’t feel it.
for HSL stuff, here’s example pseudo-code:
vec3 uniform uFilterHSL;
vec3 color_rgb = ...
vec3 color_hsl = rgb2hsl(color_rgb);
vec3 color_hsl_filtered = vec3( mod(color_hsl.x + uFilterHSL.x, 1.0), color_hsl.y * uFilterHSL.y, color_hsl.z * uFilterHSL.z);
gl_FragColor = vec4( hsl2rgb(color_hsl_filtered) , 1.0);
uFilterHSL will have following components:
- x - hue offset
- y - saturation (1 - full color, 0 - monochome, 2 - oversaturate by 200%)
- z - brightness (1 - normal, 0 - black, 0.5 - dim, 2 - brightened by 200%)