3D cube - Fl-Matrix + Gl-Matrix - JSFiddle

Demo

by David Komer

HTML

<script src="https://cdn.rawgit.com/sanctuary-js/sanctuary-type-identifiers/master/index.js"></script>
<script src="https://cdn.rawgit.com/sanctuary-js/sanctuary-type-classes/master/index.js"></script>
<script src="https://cdn.rawgit.com/sanctuary-js/sanctuary-def/master/index.js"></script>
<script src="https://cdn.rawgit.com/sanctuary-js/sanctuary/master/index.js"></script>
<script src="https://unpkg.com/fl-matrix/dist/fl-matrix.browser-production.js"></script>
<script src="https://unpkg.com/gl-matrix/dist/gl-matrix.js"></script>
<canvas id="canvas"></canvas>

CSS

html,
body {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
}

#canvas {
  position: absolute;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

JavaScript

//Globals
const canvas = document.getElementById("canvas");
const gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");

updateCanvasSize();
gl.clearColor(0.4, 0.4, 0.4, 1);
gl.enable(gl.DEPTH_TEST);

//Config
const BOX_SIZE = 200;
const HALF_BOX_SIZE = BOX_SIZE/2;
const ROTATION_SPEED = Math.PI/2;

const S = window.sanctuary.create({
  checkTypes: false,
  env: window.sanctuary.env
});

//Axis changes (to give it variety)
let ROTATION_AXIS = [1,1,1];
const changeAxis = () => {
	console.log("changing axis");
  
	ROTATION_AXIS = 
  	[Math.random(), Math.random(), Math.random()]
    .map(n => n *= (Math.random() < .5) ? -1 : 1);
}

//Functional helpers for creating common transformations

const createPerspective = fov => aspect => near => far =>
	FlMatrix.emptyMatrix (4) (4)
  	.map(es => 
  		mat4.perspective(es, fov, aspect, near, far)
    );

const createEye = origin => dest => up => 
	FlMatrix.emptyMatrix (4) (4)
  	.map(es => 
  		mat4.lookAt(es, origin, dest, up)
    );

const rotateMatrix = m => amount => axis =>
	m.map(es =>	
  	mat4.rotate(es, es, amount, axis)
  );
  
const scaleMatrix = m => scale =>
	m.map(es => 
  	mat4.scale(es, es, scale)
  );
  
const translateMatrix = m => translate =>
	m.map(es => 
  	mat4.translate(es, es, [.5,.5,.5])
  );
  
//Setup our camera matrix - any model composed with it will be rendered with this view
const cameraMatrix = 
	S.compose
  	(createPerspective (Math.PI/2) (canvas.clientWidth/canvas.clientHeight) (1) (3000))
    (createEye ([0,0,-1000]) ([0,0,1]) ([0,1,0]));
    
//accepts any modelMatrix :D
const getTransformMatrix = S.compose(cameraMatrix); //alternatively, cameraMatrix.compose;

//helper for object updates
const updateRotation = (m) => (deltaTime) => 
  	rotateMatrix (m) (deltaTime * ROTATION_SPEED) (ROTATION_AXIS);

//helper to create buffer
const makeSimpleBuffer = program => aName => nComponents => {
  gl.useProgram(program);
  const buffer = gl.createBuffer();
  const location =...