WebGL Masking

Masking content using the `FUNC_REVERSE_SUBTRACT` blend equation.

HTML

<script src="https://rawgithub.com/toji/gl-matrix/master/dist/gl-matrix-min.js"></script>
<script src="https://rawgithub.com/soulwire/sketch.js/master/js/sketch.min.js"></script>
<label>
    <input id="mask-cb" type="checkbox" checked>Mask
</label>

CSS

html, body {
    font-family: Courier;
    font-size: 13px;
    background: #ccc;
    overlay: hidden;
    margin: 0;
}

JavaScript

var GLU = (function () {

    var unit = 0;

    function defaults(target, source) {

        for (var key in source)

        if (!target.hasOwnProperty(key))

        target[key] = source[key];

        return target;
    }

    function shader(gl, source, type) {

        var shader = gl.createShader(type);

        gl.shaderSource(shader, source);
        gl.compileShader(shader);

        if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))

        throw gl.getShaderInfoLog(shader);

        return shader;
    }

    function program(gl, vertexSource, fragmentSource, attributes, uniforms) {

        var vs = shader(gl, vertexSource, gl.VERTEX_SHADER);
        var fs = shader(gl, fragmentSource, gl.FRAGMENT_SHADER);

        var program = gl.createProgram();

        gl.attachShader(program, vs);
        gl.attachShader(program, fs);
        gl.linkProgram(program);

        if (!gl.getProgramParameter(program, gl.LINK_STATUS))

        throw gl.getProgramInfoLog(program);

        if (attributes) for (var i = 0; i < attributes.length; i++)

        program[attributes[i]] = gl.getAttribLocation(program, attributes[i]);

        if (uniforms) for (var i = 0; i < uniforms.length; i++)

        program[uniforms[i]] = gl.getUniformLocation(program, uniforms[i]);

        gl.useProgram(program);

        return program;
    }

    function vbo(gl, index, data, options) {

        options = defaults(options || {}, {
            type: gl.STATIC_DRAW,
            size: 3
        });

        var vbo = gl.createBuffer();

        vbo.bind = function () {
            gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
            gl.vertexAttribPointer(index, options.size, gl.FLOAT, false, 0, 0);
        };

        vbo.bind();

        gl.bufferData(gl.ARRAY_BUFFER, data, options.type);
        gl.enableVertexAttribArray(index);

        return vbo;
    }

    return {
        program: program,
        shader: shader,
        vbo: vbo
    };

})();

var gl = Sketch.create({
   ...