Skip to content

Instantly share code, notes, and snippets.

@daltonks
Created February 19, 2016 15:33
Show Gist options
  • Save daltonks/4c2d1c5e6fd5017ea9f0 to your computer and use it in GitHub Desktop.
Save daltonks/4c2d1c5e6fd5017ea9f0 to your computer and use it in GitHub Desktop.
public void draw() {
GLES20.glEnable(GLES20.GL_STENCIL_TEST);
//Disable writing to the color and depth buffers: this is just for creating the stencil
GLES20.glColorMask(false, false, false, false);
GLES20.glDepthMask(false);
/*
GLES20.GL_NEVER: For every pixel, fail the stencil test (so we automatically overwrite the pixel's stencil buffer value)
1: write a '1' to the stencil buffer for every drawn pixel because glStencilOp has 'GLES20.GL_REPLACE'
0xFF: function mask, you'll usually use 0xFF
*/
GLES20.glStencilFunc(GLES20.GL_NEVER, 1, 0xFF);
GLES20.glStencilOp(GLES20.GL_REPLACE, GLES20.GL_KEEP, GLES20.GL_KEEP);
//Stencil mask must be set to 0xFF before clearing the buffer
GLES20.glStencilMask(0xFF);
//Clear the buffer
GLES20.glClear(GLES20.GL_STENCIL_BUFFER_BIT);
//"Drawing" the objects only ends up writing 1's to the stencil buffer no matter what color or depth they are
drawAllObjectsThatNeedAnOutline();
//Enable writing to the color and depth buffers
GLES20.glColorMask(true, true, true, true);
GLES20.glDepthMask(true);
//Disable writing to the stencil buffer
GLES20.glStencilMask(0x00);
//Test the stencil buffer: if the pixel's stencil value equals 0, draw it
GLES20.glStencilFunc(GLES20.GL_EQUAL, 0, 0xFF);
//Scale the objects to draw their outlines (also change their color if you want)
//Because of the new stencil function, pixels only get drawn if their stencil buffer values haven't been changed to 1
drawScaledVersionsOfObjects();
//Disable stencil testing, because we're done using it!
GLES20.glDisable(GLES20.GL_STENCIL_TEST);
//Draw everything, including objects that need an outline (because we haven't really "drawn" them yet)
drawEverything();
}
@automenta
Copy link

thanks!

/**
 * utility for stencil painting
 *    include = only draw inside the stencil
 *    exclude = only draw outside the stencil
 * adapted from: https://gist.github.com/daltonks/4c2d1c5e6fd5017ea9f0
 */
public static void stencilMask(GL2 gl, boolean includeOrExclude, Consumer<GL2> paintTheStencilRegion, Consumer<GL2> paintStenciled) {
    gl.glEnable(gl.GL_STENCIL_TEST);

    //Disable writing to the color and depth buffers: this is just for creating the stencil
    gl.glColorMask(false, false, false, false);
    gl.glDepthMask(false);

    /*
        gl.GL_NEVER: For every pixel, fail the stencil test (so we automatically overwrite the pixel's stencil buffer value)
        1: write a '1' to the stencil buffer for every drawn pixel because glStencilOp has 'gl.GL_REPLACE'
        0xFF: function mask, you'll usually use 0xFF
    */

    gl.glStencilFunc(gl.GL_NEVER, 1, 0xFF);
    gl.glStencilOp(gl.GL_REPLACE, gl.GL_KEEP, gl.GL_KEEP);

    //Stencil mask must be set to 0xFF before clearing the buffer
    gl.glStencilMask(0xFF);

    //Clear the buffer
    gl.glClear(gl.GL_STENCIL_BUFFER_BIT);

    //"Drawing" the objects only ends up writing 1's to the stencil buffer no matter what color or depth they are
    paintTheStencilRegion.accept(gl);

    //Enable writing to the color and depth buffers
    gl.glColorMask(true, true, true, true);
    gl.glDepthMask(true);

    //Disable writing to the stencil buffer
    gl.glStencilMask(0x00);

    //Test the stencil buffer: if the pixel's stencil value equals 0, draw it
    gl.glStencilFunc(includeOrExclude ? GL2.GL_NOTEQUAL : GL2.GL_EQUAL, 0, 0xFF);

    paintStenciled.accept(gl);

    //Disable stencil testing, because we're done using it!
    gl.glDisable(gl.GL_STENCIL_TEST);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment