JSFiddle - React, Tailwind, and code Playground

by Lucas Thomas

HTML

<script src="http://greggman.github.io/webgl-fundamentals/webgl/resources/webgl-utils.js"></script>
<!-- vertex shader -->
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;
attribute vec2 a_texCoord;

uniform vec2 u_resolution;

varying vec2 v_texCoord;

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, -1), 0, 1);

   // pass the texCoord to the fragment shader
   // The GPU will interpolate this value between points.
   v_texCoord = a_texCoord;
}
</script>
<!-- fragment shader -->
<script id="2d-fragment-shader" type="x-shader/x-fragment">
    precision mediump float;

    // our 2 canvases
    uniform sampler2D u_canvas1;
    uniform sampler2D u_canvas2;

    // the texCoords passed in from the vertex shader.
    // note: we're only using 1 set of texCoords which means
    //   we're assuming the canvases are the same size.
    varying vec2 v_texCoord;

    void main() {
         // Look up a pixel from first canvas
         vec4 color1 = texture2D(u_canvas1, v_texCoord);

         // Look up a pixel from second canvas
         vec4 color2 = texture2D(u_canvas2, v_texCoord);

         // return the 2 colors multiplied
         gl_FragColor = color1 * color2;
    }
</script>

<canvas id="canvasBuffer" width="128" height="128"></canvas>
<canvas id="canvasDest" width="128" height="128"></canvas>

CSS

canvas {
    border: 2px solid black;
    width: 128px;
    height: 128px;
}

JavaScript

var canvasBuff = document.getElementById("canvasBuffer");
var canvasDest = document.getElementById("canvasDest");
var bufferCtx = canvasBuff.getContext("2d");
var gl = getWebGLContext(canvasDest);

var interval = {};
function startGameLoop(){
	initializeShaders();
	interval = setInterval(() => {
  					circleX = Math.random()*127;
  					circleY = Math.random()*127;
  					bufferCtx.clearRect(0,0,canvasBuff.width,canvasBuff.height);
            bufferCtx.fillStyle = "red";
            bufferCtx.moveTo(circleX, circleY)
            bufferCtx.arc(circleY, circleX, 3, 0, Math.PI * 2, false);
            bufferCtx.fill();
            paintCanvas(0,0,canvasBuff.width,canvasBuff.height);
        }, 200);
}

function initializeShaders(){

    // Get A WebGL context
    this.gl = gl;
    if (!gl) {
    		console.error('no gl')
        return;
    }

    // setup GLSL program
    vertexShader = createShaderFromScriptElement(gl, "2d-vertex-shader");
    fragmentShader = createShaderFromScriptElement(gl, "2d-fragment-shader");
    program = createProgram(gl, [vertexShader, fragmentShader]);
    gl.useProgram(program);

    // look up where the vertex data needs to go.
    var positionLocation = gl.getAttribLocation(program, "a_position");
    var texCoordLocation = gl.getAttribLocation(program, "a_texCoord");

    // provide texture coordinates for the rectangle.
    var texCoordBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
      0.0, 0.0,
      1.0, 0.0,
      0.0, 1.0,
      0.0, 1.0,
      1.0, 0.0,
      1.0, 1.0]), gl.STATIC_DRAW);
    gl.enableVertexAttribArray(texCoordLocation);
    gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);

    // lookup uniforms
    var resolutionLocation = gl.getUniformLocation(program, "u_resolution");

    // set the resolution
    gl.uniform2f(resolutionLocation, canvasDest.width, canvasDest.height);

    // Create a buffer for the...