Estoy tratando de cambiar el tono de una imagen usando un sombreador de fragmentos GLSL. Quiero lograr algo similar a la capa de ajuste de tono / saturación de Photoshop.
En la siguiente imagen puedes ver lo que tengo hasta ahora. Quiero cambiar el tono del cuadrado verde para que se vea como el cuadrado rojo a la derecha, pero con este sombreador obtengo un cuadrado medio rojo medio rosado (el cuadrado en el medio).
Lo que estoy haciendo en el sombreador de fragmentos es convertir el color de la textura a HSV, luego agrego el color HSV que obtengo del sombreador de vértices y vuelvo a convertir el color a RGB.
¿Qué estoy haciendo mal?
Sombreador de fragmentos:
precision mediump float;
varying vec2 vTextureCoord;
varying vec3 vHSV;
uniform sampler2D sTexture;
vec3 convertRGBtoHSV(vec3 rgbColor) {
float r = rgbColor[0];
float g = rgbColor[1];
float b = rgbColor[2];
float colorMax = max(max(r,g), b);
float colorMin = min(min(r,g), b);
float delta = colorMax - colorMin;
float h = 0.0;
float s = 0.0;
float v = colorMax;
vec3 hsv = vec3(0.0);
if (colorMax != 0.0) {
s = (colorMax - colorMin ) / colorMax;
}
if (delta != 0.0) {
if (r == colorMax) {
h = (g - b) / delta;
} else if (g == colorMax) {
h = 2.0 + (b - r) / delta;
} else {
h = 4.0 + (r - g) / delta;
}
h *= 60.0;
if (h < 0.0) {
h += 360.0;
}
}
hsv[0] = h;
hsv[1] = s;
hsv[2] = v;
return hsv;
}
vec3 convertHSVtoRGB(vec3 hsvColor) {
float h = hsvColor.x;
float s = hsvColor.y;
float v = hsvColor.z;
if (s == 0.0) {
return vec3(v, v, v);
}
if (h == 360.0) {
h = 0.0;
}
int hi = int(h);
float f = h - float(hi);
float p = v * (1.0 - s);
float q = v * (1.0 - (s * f));
float t = v * (1.0 - (s * (1.0 - f)));
vec3 rgb;
if (hi == 0) {
rgb = vec3(v, t, p);
} else if (hi == 1) {
rgb = vec3(q, v, p);
} else if (hi == 2) {
rgb = vec3(p, v, t);
} if(hi == 3) {
rgb = vec3(p, q, v);
} else if (hi == 4) {
rgb = vec3(t, p, v);
} else {
rgb = vec3(v, p, q);
}
return rgb;
}
void main() {
vec4 textureColor = texture2D(sTexture, vTextureCoord);
vec3 fragRGB = textureColor.rgb;
vec3 fragHSV = convertRGBtoHSV(fragRGB);
fragHSV += vHSV;
fragHSV.x = mod(fragHSV.x, 360.0);
fragHSV.y = mod(fragHSV.y, 1.0);
fragHSV.z = mod(fragHSV.z, 1.0);
fragRGB = convertHSVtoRGB(fragHSV);
gl_FragColor = vec4(convertHSVtoRGB(fragHSV), textureColor.w);
}
EDITAR: Usando las funciones que Sam Hocevar proporcionó en su respuesta, el problema con las bandas de color rosa está resuelto, pero solo puedo alcanzar la mitad del espectro de color. Puedo cambiar el tono de rojo a verde, pero no puedo cambiarlo a azul o rosa.
En el fragment shader, estoy haciendo esto ahora:
void main() {
vec4 textureColor = texture2D(sTexture, vTextureCoord);
vec3 fragRGB = textureColor.rgb;
vec3 fragHSV = rgb2hsv(fragRGB);
float h = vHSV.x / 360.0;
fragHSV.x *= h;
fragHSV.yz *= vHSV.yz;
fragHSV.x = mod(fragHSV.x, 1.0);
fragHSV.y = mod(fragHSV.y, 1.0);
fragHSV.z = mod(fragHSV.z, 1.0);
fragRGB = hsv2rgb(fragHSV);
gl_FragColor = vec4(hsv2rgb(fragHSV), textureColor.w);
}
int hi = int(h/60.0); float f = h/60.0 - float(hi);
lugar deint hi = int(h); float f = h - float(hi);
? Sin embargo, no sé si eso lo está causando.