Skip to content

80. Shaders – creating an image mask

June 8, 2013

One thing Codea doesn’t provide is the ability to use one image as a mask, or stencil, for another, so you get this kind of cut out effect.

Shaders can do it for us, however.

What we need is two images. We will draw the first image, using the second image as a stencil. What this means is that as we draw the first image, pixel by pixel, we will check whether the second image has a non blank pixel in that position. If it does, we draw the pixel from the first image. If it doesn’t, we discard the pixel.

The image above uses one of the Planet Cute images as a stencil, and you can see the starry background is only drawn where it overlaps with that image.

We can also use an inverted stencil, ie only draw the first image where it doesn’t overlap the second image.

This will be a fragment shader, and first, we need to define two variables that will come from Codea. The first, texture2, is the stencil image, and the second (true/false) is whether the stencil is normal or inverted.

    uniform lowp sampler2D texture2;
    uniform bool negative;

Now the code inside main. The first two lines read in the colour of the current pixel in both images.

    lowp vec4 col1 = texture2D( texture, vTexCoord );
    lowp vec4 col2 = texture2D( texture2, vTexCoord );
    if (negative)
        {if (col2.a>0.)  gl_FragColor = col1; else discard;}
    else if (col2.a==0.) gl_FragColor = col1; else discard;

If the variable negative is true, then we draw the pixel from the first image if there is also a non blank pixel in image 2. We use the alpha value to test for blanks.

If the variable negative is false, we draw the pixel from the first image if the pixel from image 2 is blank.

In Codea, we need to set two variables.

    myMesh.shader.negative=true --or false

And that’s all there is to it. Sample code is here.

In case you wondered, here is the effect if you invert the shader.

You might want to move the mask around on the image you’re drawing, ie offset it from the bottom left of the image by x,y pixels, in which case you could add another uniform vec2 to provide the offset to the shader. The offset would need to be shown as a fraction of the image you’re drawing, ie vec2(x/img.width,y/img.height). Then, in the shader, you would have this

uniform vec2 offset;

//and in main
lowp vec4 col2 = texture2D( texture2,

Note how you subtract the offset from the current pixel position (if this isn’t clear, just think about for a bit).

Then you can slide your mask all over your drawing image, if you want, like a cookie cutter.


From → Shaders

One Comment
  1. I believe what you typed made a lot of sense. However, what about this? what if you added a little information? I am not suggesting your content isn’t solid., however what if you added something that makes people desire more? I mean %BLOG_TITLE% is a little boring. You should peek at Yahoo’s home page and see how they create article titles to grab viewers interested. You might add a related video or a related picture or two to grab readers excited about what you’ve written. In my opinion, it would bring your website a little bit more interesting.|

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: