JSFiddle - React, Tailwind, and code Playground

HTML

<script src="https://raw.githubusercontent.com/toji/gl-matrix/master/dist/gl-matrix-min.js"></script>
<script id="shader-vs" type="x-shader/x-vertex">
precision mediump float;

attribute vec4 aVertexPosition;
attribute vec3 aNormalDirection;
attribute vec2 aTextureCoord; //not used for now

uniform mat4 uMVPMatrix;
//uniform mat4 uMVMatrix;
uniform mat3 uNMatrix;

varying vec3 nrm;

void main(void) {
	gl_Position = uMVPMatrix * aVertexPosition;
	nrm = aNormalDirection * uNMatrix;
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;

varying vec3 nrm;

void main(void) {
	gl_FragColor.rgb = nrm;
	gl_FragColor.a = 1.0;
}
</script>
<body>
<canvas id="c" width="768" height="768"></canvas>
<div id="objfile" style="display:none">
g Torus
v 1.3 0 0
v 1.212132 0.212132 0
v 1 0.3 0
v 0.787868 0.212132 0
v 0.7 0 0
v 0.787868 -0.212132 0
v 1 -0.3 0
v 1.212132 -0.212132 0
v 1.201043 0 -0.497488
v 1.119864 0.212132 -0.463863
v 0.92388 0.3 -0.382683
v 0.727895 0.212132 -0.301504
v 0.646716 0 -0.267878
v 0.727895 -0.212132 -0.301504
v 0.92388 -0.3 -0.382683
v 1.119864 -0.212132 -0.463863
v 0.919239 0 -0.919239
v 0.857107 0.212132 -0.857107
v 0.707107 0.3 -0.707107
v 0.557107 0.212132 -0.557107
v 0.494975 0 -0.494975
v 0.557107 -0.212132 -0.557107
v 0.707107 -0.3 -0.707107
v 0.857107 -0.212132 -0.857107
v 0.497488 0 -1.201043
v 0.463863 0.212132 -1.119864
v 0.382683 0.3 -0.92388
v 0.301504 0.212132 -0.727895
v 0.267878 0 -0.646716
v 0.301504 -0.212132 -0.727895
v 0.382683 -0.3 -0.92388
v 0.463863 -0.212132 -1.119864
v 0 0 -1.3
v 0 0.212132 -1.212132
v 0 0.3 -1
v 0 0.212132 -0.787868
v 0 0 -0.7
v 0 -0.212132 -0.787868
v 0 -0.3 -1
v 0 -0.212132 -1.212132
v -0.497488 0 -1.201043
v -0.463863 0.212132 -1.119864
v -0.382683 0.3 -0.92388
v -0.301504 0.212132 -0.727895
v -0.267878 0 -0.646716
v -0.301504 -0.212132 -0.727895
v -0.382683 -0.3 -0.92388
v -0.463863 -0.212132 -1.119864
v -0.919239 0 -0.919239
v -0.857107 0.212132 -0.857107
v -0.707107 0.3...

CSS

#c{
	display: block;
	margin: auto;
	border: 1px dotted black;
}

JavaScript

window.requestAnimFrame = (function() {
	  return window.requestAnimationFrame ||
	     window.webkitRequestAnimationFrame ||
	     window.mozRequestAnimationFrame ||
	     window.oRequestAnimationFrame ||
	     window.msRequestAnimationFrame ||
	     function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
	       window.setTimeout(callback, 1000/60);
	     };
	})();
                   
                   
var c, gl;

var running = false;
var forceRefresh = false;
var start;

//gl vars
var shaderProgram;
var vertexPositionAttribute, normalDirectionAttribute, tcPositionAttribute;
var vertexBuffer, indexBuffer, indexcount;

var pMatrix, mvMatrix, mvpMatrix, nMatrix;
var rot;
var pos = vec3.fromValues(0, 0, -5);
var clipNear = 0.1, clipFar = 10;

//input
var rotscale = 0.003;
var mousedown = false;
var mousex=0, mousey=0;
var lastmousex=0; lastmousey=0;

//function onLoad(){
    start = Date.now();
	c = document.getElementById("c");
	log = document.getElementById("log");
	gl = c.getContext("webgl") || c.getContext("experimental-webgl");
	gl.viewport(0, 0, c.width, c.height);
	
	glMatrix.setMatrixArrayType(Float32Array);
	rot = quat.create();
	nMatrix = mat3.create();
	pMatrix = mat4.create();
	mvMatrix= mat4.create();
	mvpMatrix = mat4.create();
	
	mat4.perspective(pMatrix, Math.PI*0.25, c.width/c.height, clipNear, clipFar);
	
	
	c.addEventListener("mousedown", function(e){ if( e.button!==0 ) return; mousedown=true;});
	c.addEventListener("mousemove", function(e){ mousex=e.clientX; mousey=e.clientY; }, false);
	window.addEventListener("mouseup", function(e){ mousedown=false; });
	
	if( gl ){
		gl.clearColor(0.0, 0.0, 0.0, 1.0);
		gl.clearDepth(1.0);
		gl.enable(gl.DEPTH_TEST);
		gl.depthFunc(gl.LEQUAL);
		
		initShaders();
		initBuffers();
		
 		running = true;
 		forceRefresh = true;
		update();
	}
	else{
		throw "No support for WebGL!";
	}
//}

function update(){
	var changed = handleInput();
	
	if( changed || forceRefresh...