TL;DR: Go here to get the RGB->HSV and HSV->RGB conversion functions for shaders.
The other day I tried to tint a colour in a texture (or rather all texture) with a different colour. It's quite easy to rotate things around, but, if you want to do it parametrically, you'll need something a bit more complex.
HSV
The easiest way (?!?!) I could come up with was to shift the hue off all colors using a RGB<->HSV conversion. The algorithm in a shader would be quite simple:
for pixel in texture:
rgb = pixel.rgb
hsv = rgb_to_hsv(rgb)
hsv.h += parameter # parameter is 0-1
if hsv.h > 1:
hsv.h -= 1
pixel.set_color(hsv_to_rgb(hsv))
Simple, right?
Now, the two functions are:
-
RGB -> HSV:
vec3 rgb2hsv(vec3 c) { vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); float d = q.x - min(q.w, q.y); float e = 1.0e-10; return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); }
-
HSV -> RGB:
vec3 hsv2rgb(vec3 c) { vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); }
Now, all you have to do is place them in a fragment shader and apply the above algorithm.
Vertex shader
The vertex shader is quite basic (done in the OS X's OpenGL Shader Builder):
//1
attribute vec4 a_position;
attribute vec2 a_texCoord;
void main()
{
gl_FrontColor = gl_Color;
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}
Fragment shader
The fragment shader is like this (sand the two above methods for brevity)
uniform sampler2D tex;
uniform vec3 hue;
// Add the two methods here
void main() {
vec4 textureColor = texture2D(tex, vTextureCoord);
vec3 fragRGB = textureColor.rgb;
vec3 fragHSV = rgb2hsv(fragRGB).xyz;
fragHSV.x += hue.x;
fragHSV.yz *= hue.yz;
fragHSV.xyz = mod(fragHSV.xyz, 1.0);
fragRGB = hsv2rgb(fragHSV);
gl_FragColor = vec4(fragRGB, textureColor.w);
}
Yes, it's like the one from SO, but with the difference that values for hue are between 0 and 1 (rather than 0-360).
Now, all we have to do is to tint only some of the colours... :)
Member discussion: