JSFiddle - React, Tailwind, and code Playground

HTML

<title>WebGL Particle System</title>
<script type="text/javascript" src="https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/sdk/demos/common/webgl-utils.js"></script>
<script type="text/javascript" src="https://www.khronos.org/registry/webgl/sdk/debug/webgl-debug.js"></script>
<script src="https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/sdk/demos/webkit/resources/J3DI.js"> </script>
<script src="https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/sdk/demos/webkit/resources/J3DIMath.js"
type="text/javascript"> </script>
<canvas id="example">
    If you're seeing this your web browser doesn't support the &lt;canvas>&gt; element. Ouch!
</canvas>
<div id="framerate"></div>

<script id="render_vshader" type="x-shader/x-vertex">
    attribute vec4 vPosition;

    uniform mat4 u_modelViewProjMatrix;
    
    uniform sampler2D mParticleTex;

    void main()
    {
        vec2 particleSampleCoords = vPosition.xy;
        vec4 particlePos = texture2D(mParticleTex, particleSampleCoords);
        gl_Position = u_modelViewProjMatrix * particlePos;
        gl_PointSize = 10.0;
    }
</script>

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

    uniform sampler2D mSpriteTex;
    
    void main()
    {
        vec4 texColor = texture2D(mSpriteTex, gl_PointCoord);
        gl_FragColor = texColor;
    }
</script>


<script id="particle_vshader" type="x-shader/x-vertex">
    attribute vec4 vPosition;
        
    void main()
    {
        // Dummy VS
        gl_Position = vPosition;
    }
</script>

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

    uniform sampler2D mParticleTex;

    void main()
    {
        // Current pixel is the particle's position on the texture
        vec2 particleSampleCoords = gl_FragCoord.xy;
        vec4 particlePos = texture2D(mParticleTex, particleSampleCoords);

        // Move the particle up
        particlePos.y += 0.1;
       ...

CSS

body, html {
  margin: 0px;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
#framerate {
  position: absolute;
  top: 10px;
  left: 10px;
  background-color: rgba(0,0,0,0.3);
  padding: 1em;
  color: white;
}
#example {
  width: 100%;
  height: 100%;
}
canvas {
    border: 2px solid black;
}

JavaScript

var g = { };
var numParticles = 512;
var particleSize = 0.1;
var particleSpread = 4.0;

var maxTex = 16384;

start();

// Get best texture size (must be square powers of 2)
function getTexSize(n)
{
    var retval = { };
    for(var height = 1; height<maxTex; height *= 2)
    {
        for(var width = 1; width<maxTex; width *= 2)
        {
            if(width*height >= n)
            {
                retval.width = width;
                retval.height = height;
                return retval;
            }
        }
    }

    retval.width = -1;
    retval.height = -1;
    return retval;
}

function createScreenQuad(gl)
{
    // Returned particle system object
    var retval = { };

    // 4 3D corners = 12 vertices / particle
    var vertexBuffer = new Float32Array(12);

    // -1,-1 to 1,1 screen quad
    vertexBuffer[0] = -1;
    vertexBuffer[1] = -1;

    vertexBuffer[2] = -1;
    vertexBuffer[3] = 1;

    vertexBuffer[4] = 1;
    vertexBuffer[5] = 1;

    vertexBuffer[6] = -1;
    vertexBuffer[7] = -1;

    vertexBuffer[8] = 1;
    vertexBuffer[9] = 1;

    vertexBuffer[10] = 1;
    vertexBuffer[11] = -1;

    // Create GL buffers with this data
    retval.vertexObject = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, retval.vertexObject);
    gl.bufferData(gl.ARRAY_BUFFER, vertexBuffer, gl.STATIC_DRAW);
    
    return retval;
}

// Loads a texture from the absolute or relative URL "src".
// Returns a WebGLTexture object.
// The texture is downloaded in the background using the browser's
// built-in image handling. Upon completion of the download, our
// onload event handler will be called which uploads the image into
// the WebGLTexture.
function loadTexture(src) {
    // Create and initialize the WebGLTexture object.
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    //...