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...