JSFiddle - React, Tailwind, and code Playground

by Sharlin

HTML

<canvas id=c width=640 height=480></canvas>
<div id=perf></div>
<div id=log></div>

CSS

body {
  font: 12px sans-serif;
}

canvas { 
  border: 1px solid black; 
  width: 640px; height: 480px;
}

#log p:nth-child(even) {
  background: white;
}

#log p {
  margin: 0;
  padding: 2px 4px;
}

JavaScript

'use strict';

const c = document.getElementById("c")
const ctx = c.getContext("2d")
const img = ctx.createImageData(c.width, c.height)
const fb = new Uint32Array(img.data.buffer)
const M = Math

const DEBUG = 0

const l = DEBUG ? (function (msg) {
  console.log(msg)
  const log = document.getElementById("log")
  log.innerHTML = "<p>"+msg+"</p>" + log.innerHTML
}) : function(){}

function lerp(t, a, b) {
  return t*b + (1-t)*a
}

function vlerp(t, v, u) {
  return mul(u, t) + mul(v, 1-t);
}

function clamp(x) {
  return M.max(0, M.min(1, x))
}

function add(v, u) {
  return [v[0]+u[0], v[1]+u[1], v[2]+u[2], v[3]+u[3]]
}

function sub(v, u) {
  return [v[0]-u[0], v[1]-u[1], v[2]-u[2], v[3]-u[3]]
}

function mul(v, s) {
  return [s*v[0], s*v[1], s*v[2], s*v[3]]
}

function pt(v) {
  return [v[0], v[1], v[2], 1]
}

function dir(v) {
  return [v[0], v[1], v[2], 0]
}

function dot(v, u) {
  return v[0]*u[0] + v[1]*u[1] + v[2]*u[2] + v[3]*u[3]
}

function cross(v, u) {
  return [v[1]*u[2] - v[2]*u[1],
          v[2]*u[0] - v[0]*u[2],
          v[0]*u[1] - v[1]*u[0],
          0]
}

function normal(v, u, w) {
  //l("normal for " + v + "; " + u + "; " + w)
  return normalize(cross(sub(u, v), sub(w, v)))
}

function normalize(v) {
  v = dir(v)
  var len = M.sqrt(dot(v, v))
  return [v[0]/len, v[1]/len, v[2]/len, 0]
}

function id() {
  return [1, 0, 0, 0,
          0, 1, 0, 0,
          0, 0, 1, 0,
          0, 0, 0, 1]
}

function scale(x, y, z) {
  return [x, 0, 0, 0,
          0, y, 0, 0,
          0, 0, z, 0,
          0, 0, 0, 1]
}

function translate(x, y, z) {
  return [1, 0, 0, 0,
          0, 1, 0, 0,
          0, 0, 1, 0,
          x, y, z, 1]
}

function rotateX(theta) {
  return [1, 0,             0,            0,
          0, M.cos(theta), -M.sin(theta), 0,
          0, M.sin(theta),  M.cos(theta), 0,
          0, 0,             0,            1]
}

function rotateY(theta) {
  return [M.cos(theta), 0, -M.sin(theta), 0,
  				0,            1,             0, 0,
...