Search code examples
androidopengl-esopengl-es-2.0mask

Desaturate texture using mask in OpenGL 2


I have a very large texture i am using as background and i want to apply a filter to a small part of it, the "small part" is defined by the alpha layer of another texture i have (which is still RGB8888), i am not sure what's the best approach to do this. I'd like to keep the same (very simple) shader i am already using for other sprites, which is similar to the basic one, i.e.:

precision mediump float;
uniform sampler2D uTexture;
varying vec2 vTexPos;
void main() {
  gl_FragColor = texture2D(uTexture, vTexPos);
}

So, i have some questions

  • How can i apply my filter only to "masked" region and avoid drawing others?
  • Do i have any performance loss if i draw the big texture again once loaded to just apply it to a small portion of the screen?
  • Can i map a second texture to the shader and use something like "if uTexture2 != null" -> apply as mask? Will this give me any performance gain compared to using a second shader?
  • Both textures are premultiplied, how should i handle alpha masking?

What id like to do is something like this (original, mask, result):

Base Texture Alpha Mask Result

My environment is Android 4.0, im using GLES20.


Solution

  • You need to use color testing of additional mask texture sampler, and some desaturation filter based on condition.

    This fragment shader should work:

    precision mediump float;
    uniform sampler2D uTexture;
    uniform sampler2D uMask;
    varying vec2 vTexPos;
    
    void main() {
        vec4 mask = texture2D(uMask, vTexPos);
        if(mask.r < 0.9) { // black mask
            gl_FragColor = texture2D(uTexture, vTexPos);
        } else { // white mask
            vec4 texelColor = texture2D(uTexture, vTexPos); // original color
            vec4 scaledColor = texelColor * vec4(0.3, 0.59, 0.11, 1.0); // weights calculation
            float luminance = scaledColor.r + scaledColor.g + scaledColor.b; // greyscale
            gl_FragColor = vec4(luminance, luminance, luminance, texelColor.a); // final color with original alpha value
        }
    }
    

    Desaturation code is from this great article: http://franzzle.wordpress.com/2013/03/25/use-a-opengl-es-2-0-shader-to-show-a-desaturated-sprite-in-cocos2d-2-0/