vec3 hueShift( vec3 color, float hueAdjust ){ | |
const vec3 kRGBToYPrime = vec3 (0.299, 0.587, 0.114); | |
const vec3 kRGBToI = vec3 (0.596, -0.275, -0.321); | |
const vec3 kRGBToQ = vec3 (0.212, -0.523, 0.311); | |
const vec3 kYIQToR = vec3 (1.0, 0.956, 0.621); | |
const vec3 kYIQToG = vec3 (1.0, -0.272, -0.647); | |
const vec3 kYIQToB = vec3 (1.0, -1.107, 1.704); | |
float YPrime = dot (color, kRGBToYPrime); | |
float I = dot (color, kRGBToI); | |
float Q = dot (color, kRGBToQ); | |
float hue = atan (Q, I); | |
float chroma = sqrt (I * I + Q * Q); | |
hue += hueAdjust; | |
Q = chroma * sin (hue); | |
I = chroma * cos (hue); | |
vec3 yIQ = vec3 (YPrime, I, Q); | |
return vec3( dot (yIQ, kYIQToR), dot (yIQ, kYIQToG), dot (yIQ, kYIQToB) ); | |
} |
This comment has been minimized.
This comment has been minimized.
For future visitors, the hue value should be in radians, not in degrees (0.0 to 360.0), so if your hue value is in degrees, you will need to convert before passing to the shader add it the shader code. |
This comment has been minimized.
This comment has been minimized.
I know this is an old comment, but someone might still find it useful. Basically the shader uses the YIQ color mode. The constants are conversion matrices between RGB and YIQ, but wikipedia can explain that better than I do: Hue is the angle on the IQ-plane. In other words you fix the Y value, and get a two dimensional IQ-plane, then calculate the angle between those two values. The shift is simply performed by adding the shift value to this angle. |
This comment has been minimized.
This comment has been minimized.
This is an incredibly slow implementation. Here is the same thing, but it works several times faster. Written on HLSL. Porting to GLSL is easy.
|
This comment has been minimized.
This comment has been minimized.
@viruseg Indeed, it is a more elegant solution, and simple to convert to GLSL, thanks. vec3 hueShift(vec3 color, float hue) {
const vec3 k = vec3(0.57735, 0.57735, 0.57735);
float cosAngle = cos(hue);
return vec3(color * cosAngle + cross(k, color) * sin(hue) + k * dot(k, color) * (1.0 - cosAngle));
} |
This comment has been minimized.
This comment has been minimized.
There was a typo, this one works for me: vec3 hueShift(vec3 color, float hue) |
This comment has been minimized.
This comment has been minimized.
Does anyone know where the |
This comment has been minimized.
This comment has been minimized.
@RichardBray it's |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
@janpaul123 Thanks that makes more sense. But yeah I still can't figure out how that formula was reached. |
This comment has been minimized.
This comment has been minimized.
Thank you so much for this! Contrary to what you seem to think though, your original function produces much more natural looking/beautiful results than the cheaper hueshift function provided by @viruseg. Of course it depends on context whether or not that's needed, but I for one deeply appreciate it! vec2 rotate2(vec2 v, float fi) { // YIQ color rotation/hue shift |
This comment has been minimized.
Do you have any recommended reading to explain this? I don't understand how any of it works, especially the constants. It works perfectly though.