JSFiddle - React, Tailwind, and code Playground

HTML

<!-- https://caiorss.github.io/C-Cpp-Notes/computer-graphics.html -->
<h1>WebGL 3D Scene with Cube</h1>
OpenGL version:  <label id="output1"></label>          <br/>
Shading language version: <label id="output2"></label> <br/> 
Camera Positon: <label id="output-camera"></label> <br/><canvas id="glCanvas" width="600" height="480">

JavaScript

// Source: https://caiorss.github.io/C-Cpp-Notes/computer-graphics.html

// eye = [3, 10, 20]; at = [50, 25, 10]; up = [0, 1, 0];

// RGB color constants (Red, Gree, Blue) (R, G, B) tuples
const COLOR_RED        = [1.0, 0.0, 0.0];
const COLOR_GREEN      = [0.0, 1.0, 0.0];
const COLOR_BLUE       = [0.0, 0.0, 1.0];
const COLOR_YELLLOW    = [ 0.80,  1.000, 0.100 ];
const COLOR_GRAY       = [ 0.47,  0.390, 0.380 ];
const COLOR_DARK_GREEN = [ 0.027, 0.392, 0.050 ];
const COLOR_DARK_BLUE  = [ 0.109, 0.066, 0.411 ];


// Normalize a vector 3x1 column vector (3 rows and 1 column)  
function normalize(vector)
{
  let [x, y, z] = vector;
  let norm = Math.sqrt( x * x + y * y + z * z);
  return [ x / norm, y / norm, z / norm ];
}

// Computes the dot product (aka scalar) product between two vectors  
function dot(vectorA, vectorB)
{
  let [xa, ya, za] = vectorA;
  let [xb, yb, zb] = vectorB;
  return xa * xb  + ya * yb + za * zb;
}

// Computs the cross product between two vectors 
function cross(vectorA, vectorB)
{
  let [xa, ya, za] = vectorA;
  let [xb, yb, zb] = vectorB;
  return [ ya * zb - za * yb, za * xb - xa * zb, xa * yb - ya * xb ];
}

// Difference between two vectors 
function diff(vectorA, vectorB)
{
  let [xa, ya, za] = vectorA;
  let [xb, yb, zb] = vectorB;
  return [xa - xb, ya - yb, za - zb];
}

class Quaternion
{
  constructor(w, x, y, z)
  {
    // Default is the unit quaternion 
    this._quat = [w, x, y, z];
  }

  /** @param {number} w
  /*  @param {number} x 
  /*  @param {number} y 
  /*  @param {number} z 
   */ 
  static create(w, x, y, z)
  {
    return new Quaternion(w, x, y, z);
  }

  /** Create unit quaternion  */
  static createUnit()
  {
    return new Quaternion(1.0, 0.0, 0.0, 0.0);
  }

  /** Create a imaginary quaternion */
  static createFromVector(x, y, z)
  {
    return new Quaternion(0.0, x, y, z);
  }

  /** Create quaternion represeting a rotation around some axis 
   * @param {number}   angle - Rotation angle in degrees 
   *...