Is there a way to efficiently change hue of a 2D OpenGL texture using GLSL (fragment shader)?
Do someone have some code for it?
UPDATE: This is the code resulting from user1118321 suggestion:
uniform sampler2DRect texture;
const mat3 rgb2yiq = mat3(0.299, 0.587, 0.114, 0.595716, -0.274453, -0.321263, 0.211456, -0.522591, 0.311135);
const mat3 yiq2rgb = mat3(1.0, 0.9563, 0.6210, 1.0, -0.2721, -0.6474, 1.0, -1.1070, 1.7046);
uniform float hue;
void main() {
vec3 yColor = rgb2yiq * texture2DRect(texture, gl_TexCoord[0].st).rgb;
float originalHue = atan(yColor.b, yColor.g);
float finalHue = originalHue + hue;
float chroma = sqrt(yColor.b*yColor.b+yColor.g*yColor.g);
vec3 yFinalColor = vec3(yColor.r, chroma * cos(finalHue), chroma * sin(finalHue));
gl_FragColor = vec4(yiq2rgb*yFinalColor, 1.0);
}
And this is the result compared with a reference:

I have tried to switch I with Q inside atan but the result is wrong even around 0°
Have you got any hint?
If needed for comparison, this is the original unmodified image:

While what @awoodland says is correct, that method may cause issues with changes in luminance, I believe.
HSV and HLS color systems are problematic for a number of reasons. I talked with a color scientist about this recently, and his recommendation was to convert to YIQ or YCbCr space and adjust the the chroma channels (I&Q, or Cb&Cr) accordingly. (You can learn how to do that here and here.)
Once in one of those spaces, you can get the hue from the angle formed by the chroma channels, by doing
hue = atan(cr/cb)(watching for cb == 0). This gives you a value in radians. Simply rotate it by adding the hue rotation amount. Once you’ve done that, you can calculate the magnitude of the chroma withchroma = sqrt(cr*cr+cb*cb). To get back to RGB, calculate the new Cb and Cr (or I & Q) usingCr = chroma * sin (hue),Cb = chroma * cos (hue). Then convert back to RGB as described on the above web pages.EDIT: Here’s a solution that I’ve tested and seems to give me the same results as your reference. You can probably collapse some of the dot products into matrix multiplies: