I have a simple fragment shader that looks like this:
#ifdef GL_ES
precision lowp float;
#endif
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
uniform vec4 u_desiredColor;
uniform sampler2D u_texture;
void main()
{
gl_FragColor = texture2D(u_texture, v_texCoord) * u_desiredColor;
}
My goal is to take a grayscale image and apply a color to it, but maintain luminance. There was a stackoverflow post from years ago where the poster was after exactly what I want:
The answers however are outdated (OpenGL ES 1.0) and also I am a little confused by them. The accepted answer says to use multi-texturing, and the 2nd answer says that is "nonsense". Regardless, the code example there is incompatible with the version of OpenGL ES 2.0 that my game is using with cocos2d v2.x.
Here are my original grayscale sprites:
With my simple shader applied and setting u_desiredColor to vec4(1.0, 0.0, 0.0, 1.0), you can see it does exactly what I don't want it to do-- it completely tints the entire image, turning everything red, including the white.
What I really want is for the darker shades of gray have the richest color, but as the sampled grayscale pixel approaches white, the colorized pixels lose saturation, where ultimately a sampled pixel of white has 0% saturation-- but a sampled pixel of dark gray would be 100% saturation.
My desired output is:
My thought was that the simplest approach would be to have my shader make the output pixel color's saturation be something like (1.0 - samplePixelIntensity). So, if the sample pixel's intensity was 1.0, that would mean 0% saturation in the output, if the sample pixel's intensity was 0.5, it would have 50% saturation.. if the sample pixel's intensity was 0.2, then it would have 80% saturation.
However, I am not very familiar with writing shaders, so I am wondering how I might construct something like this?