JSFiddle - React, Tailwind, and code Playground

HTML

<button id="stop">Stop/start</button>
<script id="vertex-shader" type="x-shader/x-vertex">
    attribute vec2 a_position;
    attribute vec2 a_texCoord;
    varying vec2 v_texCoord;
    uniform vec2 u_resolution;
    uniform float u_flipY;

    void main() {

        // convert the rectangle from pixels to 0.0 to 1.0
        vec2 zeroToOne = a_position / u_resolution;

        // convert from 0->1 to 0->2
        vec2 zeroToTwo = zeroToOne * 2.0;

        // convert from 0->2 to -1->+1 (clipspace)
        vec2 clipSpace = zeroToTwo - 1.0;

        gl_Position = vec4(clipSpace * vec2(1, u_flipY), 0, 1);

        v_texCoord = a_texCoord;
    }
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
    precision mediump float;

    // our texture
    uniform sampler2D u_image;

    // the texCoords passed in from the vertex shader.
    varying vec2 v_texCoord;

    void main() {
        // Look up a color from the texture.
        vec4 color = texture2D(u_image, v_texCoord);

        if (color.a < 1.0) {
            color.a -= 0.01;
        }

        gl_FragColor = color;
    }
</script>
<script id="fbo-fragment-shader" type="x-shader/x-fragment">
    precision mediump float;

    // our texture
    uniform sampler2D u_image;
    // the texCoords passed in from the vertex shader.
    varying vec2 v_texCoord;

    void main() {

        vec4 color = texture2D(u_image, v_texCoord);

        // if (color.r > 0.1) color.a = 0.01;
        color.a = 1.0 - color.r;

        gl_FragColor = color;
    }
</script>

JavaScript

// custom fn

function createShaderFromScriptElement(gl, scriptId) {
    var shaderSource = "",
        shaderType;
    var shaderScript = document.getElementById(scriptId);
    if (!shaderScript) {
        throw ("*** Error: unknown script element" + scriptId);
    }
    shaderSource = shaderScript.text;

    if (shaderScript.type == "x-shader/x-vertex") {
        shaderType = gl.VERTEX_SHADER;
    } else if (shaderScript.type == "x-shader/x-fragment") {
        shaderType = gl.FRAGMENT_SHADER;
    } else if (shaderType != gl.VERTEX_SHADER && shaderType != gl.FRAGMENT_SHADER) {
        throw ("*** Error: unknown shader type");
        return null;
    }

    var shader = gl.createShader(shaderType);

    // Load the shader source
    gl.shaderSource(shader, shaderSource);

    // Compile the shader
    gl.compileShader(shader);

    // Check the compile status
    var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
    if (!compiled) {
        // Something went wrong during compilation; get the error
        var lastError = gl.getShaderInfoLog(shader);
        errFn("*** Error compiling shader '" + shader + "':" + lastError);
        gl.deleteShader(shader);
        return null;
    }

    return shader;
}

function createProgram(gl, shaders) {

    var shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, shaders[0]);
    gl.attachShader(shaderProgram, shaders[1]);
    gl.linkProgram(shaderProgram);

    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
        alert("Could not initialise shaders");
    }
    // HINT dont use program here
    return shaderProgram;
}

// origin source code

var sketch;

function init() {

    sketch = new Sketch();
    document.body.appendChild(sketch);

    sketch.width = window.innerWidth;
    sketch.height = window.innerHeight;

    loop();
}

function loop() {
    requestAnimationFrame(loop);
    sketch.draw();
}


var Sketch = function () {

    var _canvas =...