JSFiddle - React, Tailwind, and code Playground

HTML

<html> 
	<head> 
		<title>FLUID - WebGL demo by boblemarin (https://github.com/boblemarin/FLU)</title> 
		
		<link type="text/css" rel="stylesheet" href="styles/standalone.css">
		
		<script id="shader-fs" type="x-shader/x-fragment">
				#ifdef GL_ES
				  precision highp float;
				  #endif
				  
				 uniform vec4 color;
				 
    		void main(void) {
    		 gl_FragColor = color;
    		}
		</script>
		
		<script id="shader-vs" type="x-shader/x-vertex">
  			attribute vec3 vertexPosition;

			uniform mat4 modelViewMatrix;
			uniform mat4 perspectiveMatrix;

 			void main(void) {
				gl_Position = perspectiveMatrix * modelViewMatrix * vec4(vertexPosition, 1.0);
			}	
		</script>
		
	</head>
	<body>
		<canvas id="webGLCanvas"></canvas>
		<div id="instructions">Click and drag to animate particles, press any key to switch between rendering modes</div>

		<script type="text/javascript" src="js/RequestAnimationFrame.js"></script>
		<script type="text/javascript" src="js/StandAloneDrawParticlesGL.js"></script>
	</body>
</html>

CSS

html, body { height: 100%; }
body { 
	margin: 0px; 
	padding: 0px; 
	overflow: hidden;
	background: #000;
}
canvas { 
	z-index: 2;
	width: 100%; 
	height: 100%; 
	position: absolute;
	-webkit-transform: translateZ(0); 
	cursor: crosshair;/*NW-resize;*/
}  

#connectImg {
	position: absolute;
	top: 0px;
	left: 0px;
	right: 0px;
	height: 44px;
	background: url("../img/join.png") no-repeat center;
	-webkit-transition: all .5s ease-in-out;
	z-index:  5;
}

#connectImg.closed {
	top: -45px;
}


#connect {
	position: absolute;
	top: 0px;
	left: 0px;
	right: 0px;
	padding: 10px;
	background: rgba(0,0,0,0.5);
	color: #FFF;
	text-align: center;
	font-family: "DaxCompact-Medium";
	font-size: 16px;
	-webkit-transition: all .5s ease-out;
	z-index:  5;
}

#connect img {
	vertical-align: middle;
	margin-right: 20px;
}

#connect.closed {
	top: -60px !important; 
}

.wifi, .url {
	font-weight: bold;
	background: #666;
	display: inline-block;
	padding: 3px 8px;
	-webkit-border-radius: 10px;
	-moz-border-radius: 10px;
	border-radius: 10px;
	
	background: #989898;
	background: -moz-linear-gradient(top, #989898 0%, #757575 36%, #282828 100%);
	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#989898), color-stop(36%,#757575), color-stop(100%,#282828));
	background: -webkit-linear-gradient(top, #989898 0%,#757575 36%,#282828 100%);
	background: -o-linear-gradient(top, #989898 0%,#757575 36%,#282828 100%);
	background: -ms-linear-gradient(top, #989898 0%,#757575 36%,#282828 100%);
	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#989898', endColorstr='#282828',GradientType=0 );
	background: linear-gradient(top, #989898 0%,#757575 36%,#282828 100%);
}

#instructions {
	position: absolute;
	left: 0px;
	right: 0px;
	bottom: 0px;
	padding: 5px;
	color: white;
	text-align: center;
	font-family: Helvetica;
	font-size: 14px;
	z-index:  5;
}

JavaScript

(function(){
	/**
	 * Most of the WebGL-related code in this demo 
	 * comes from this tutorial by Dennis Ippel (thanks!) :
	 * http://www.rozengain.com/blog/2010/02/22/beginning-webgl-step-by-step-tutorial/
	 * 
	 */


	var offset = 0,
		deadTimeOut = 1000,
		i, n,
		connectDiv,
		canvas, gl,
		ratio,
		vertices,
		velocities,
		colorLoc,
		cw, 
		ch, 
		cr = 0, cg = 0, cb = 0,
		tr, tg, tb,
		rndX = 0,
		rndY = 0,
		rndOn = false,
		rndSX = 0,
		rndSY = 0,
		lastUpdate = 0,
		IDLE_DELAY = 6000,
		touches = [],
		totalLines = 60000,
		renderMode = 0,
		numLines = totalLines;

	// setup webGL
	loadScene();

	// add listeners
	window.addEventListener( "resize", onResize, false )
	document.addEventListener( "mousedown", onMouseDown, false );
	document.addEventListener( "keydown", onKey, false );
	onResize();

	// start animation
	animate();

	function onResize(e) {
		cw = window.innerWidth; 
		ch = window.innerHeight;
	}  

	function normalize(px, py){
		touches[0] = (px/cw-.5)*3;
		touches[1] = (py/ch-.5)*-2;
	}

	function onMouseDown(e){
		normalize(e.pageX,e.pageY);
		document.addEventListener( "mousemove", onMouseMove );
		document.addEventListener( "mouseup", onMouseUp );
		e.preventDefault();
	}

	function onMouseMove(e) {
		normalize(e.pageX,e.pageY);
	}

	function onMouseUp(e) {
		touches.length = 0;
		document.removeEventListener( "mousemove", onMouseMove );
		document.removeEventListener( "mouseup", onMouseUp );
	}

	function animate() {
		requestAnimationFrame( animate );
		redraw();
	}


	function redraw()
	{

		// declarations
		var player, dx, dy, d,
				tx, ty, bp, p, 
				i = 0, nt, j,
				now = new Date().getTime();
		
		nt = touches.length;
		
		// animate color
		cr = cr * .99 + tr * .01;
		cg = cg * .99 + tg * .01;
		cb = cb * .99 + tb * .01;
		gl.uniform4f( colorLoc, cr, cg, cb, .5 );
		
		// animate and attract particles
		for( i = 0; i < numLines; i+=2 )
		{
			bp = i*3;
			// copy old positions
			vertices[bp] =...