Skip to content

Instantly share code, notes, and snippets.

@tchayen
Last active December 25, 2018 04:25
Show Gist options
  • Save tchayen/6cea3d7d538ca1e2a6a5808646b5e64e to your computer and use it in GitHub Desktop.
Save tchayen/6cea3d7d538ca1e2a6a5808646b5e64e to your computer and use it in GitHub Desktop.
document.documentElement.style.overflow = 'hidden'
const obj = `
v 0.5 -0.12 -0.26
v 0.5 -0.12 -0.12
v -0.5 -0.12 -0.26
v -0.5 -0.12 -0.26
v 0.5 -0.12 -0.12
v -0.5 -0.12 -0.12
v -0.5 -0.5 -0.12
v -0.5 -0.5 0.5
v -0.5 -0.12 -0.12
v -0.5 -0.12 -0.12
v -0.5 -0.5 0.5
v -0.5 0.5 0.5
v -0.5 -0.12 -0.12
v -0.5 0.5 0.5
v -0.5 0.5 -0.5
v -0.5 -0.12 -0.12
v -0.5 0.5 -0.5
v -0.5 -0.12 -0.26
v -0.5 -0.12 -0.26
v -0.5 0.5 -0.5
v -0.5 -0.5 -0.5
v -0.5 -0.12 -0.26
v -0.5 -0.5 -0.5
v -0.5 -0.5 -0.26
v 0.5 -0.5 0.26
v 0.5 -0.5 0.5
v -0.26 -0.5 0.26
v -0.26 -0.5 0.26
v 0.5 -0.5 0.5
v -0.5 -0.5 0.5
v -0.26 -0.5 0.26
v -0.5 -0.5 0.5
v -0.5 -0.5 -0.12
v -0.26 -0.5 0.26
v -0.5 -0.5 -0.12
v -0.26 -0.5 0.12
v -0.26 -0.5 0.12
v -0.5 -0.5 -0.12
v 0.5 -0.5 -0.12
v -0.26 -0.5 0.12
v 0.5 -0.5 -0.12
v 0.5 -0.5 0.12
v 0.5 -0.5 -0.5
v 0.5 0.12 -0.5
v 0.5 -0.12 -0.26
v 0.5 -0.12 -0.26
v 0.5 0.12 -0.5
v 0.5 0.12 0.12
v 0.5 -0.12 -0.26
v 0.5 0.12 0.12
v 0.5 -0.12 -0.12
v 0.5 -0.12 -0.12
v 0.5 0.12 0.12
v 0.5 -0.5 0.12
v 0.5 -0.12 -0.12
v 0.5 -0.5 0.12
v 0.5 -0.5 -0.12
v 0.5 -0.12 -0.26
v 0.5 -0.5 -0.26
v 0.5 -0.5 -0.5
v 0.5 0.26 -0.5
v -0.26 0.26 -0.5
v 0.5 0.5 -0.5
v 0.5 0.5 -0.5
v -0.26 0.26 -0.5
v -0.5 0.5 -0.5
v -0.26 0.26 -0.5
v -0.26 0.12 -0.5
v -0.5 0.5 -0.5
v -0.5 0.5 -0.5
v -0.26 0.12 -0.5
v -0.5 -0.5 -0.5
v 0.5 0.12 -0.5
v 0.5 -0.5 -0.5
v -0.26 0.12 -0.5
v -0.26 0.12 -0.5
v 0.5 -0.5 -0.5
v -0.5 -0.5 -0.5
v -0.26 0.12 -0.5
v -0.26 0.12 0.12
v 0.5 0.12 -0.5
v 0.5 0.12 -0.5
v -0.26 0.12 0.12
v 0.5 0.12 0.12
v -0.26 -0.5 0.26
v -0.26 0.26 0.26
v 0.5 -0.5 0.26
v 0.5 -0.5 0.26
v -0.26 0.26 0.26
v 0.5 0.26 0.26
v -0.26 0.12 0.12
v -0.26 -0.5 0.12
v 0.5 0.12 0.12
v 0.5 0.12 0.12
v -0.26 -0.5 0.12
v 0.5 -0.5 0.12
v 0.5 -0.5 -0.5
v 0.5 -0.5 -0.26
v -0.5 -0.5 -0.5
v -0.5 -0.5 -0.5
v 0.5 -0.5 -0.26
v -0.5 -0.5 -0.26
v 0.5 0.26 -0.5
v 0.5 0.5 -0.5
v 0.5 0.26 0.26
v 0.5 0.26 0.26
v 0.5 0.5 -0.5
v 0.5 0.5 0.5
v 0.5 0.26 0.26
v 0.5 0.5 0.5
v 0.5 -0.5 0.5
v 0.5 -0.5 0.5
v 0.5 -0.5 0.26
v 0.5 0.26 0.26
v 0.5 0.5 0.5
v 0.5 0.5 -0.5
v -0.5 0.5 0.5
v -0.5 0.5 0.5
v 0.5 0.5 -0.5
v -0.5 0.5 -0.5
v 0.5 -0.5 0.5
v 0.5 0.5 0.5
v -0.5 -0.5 0.5
v -0.5 -0.5 0.5
v 0.5 0.5 0.5
v -0.5 0.5 0.5
v 0.5 -0.5 -0.26
v 0.5 -0.12 -0.26
v -0.5 -0.5 -0.26
v -0.5 -0.5 -0.26
v 0.5 -0.12 -0.26
v -0.5 -0.12 -0.26
v -0.26 0.26 0.26
v -0.26 0.26 -0.5
v 0.5 0.26 0.26
v 0.5 0.26 0.26
v -0.26 0.26 -0.5
v 0.5 0.26 -0.5
v -0.26 0.12 -0.5
v -0.26 0.26 -0.5
v -0.26 0.12 0.12
v -0.26 0.12 0.12
v -0.26 0.26 -0.5
v -0.26 0.26 0.26
v -0.26 0.12 0.12
v -0.26 0.26 0.26
v -0.26 -0.5 0.26
v -0.26 -0.5 0.26
v -0.26 -0.5 0.12
v -0.26 0.12 0.12
v 0.5 -0.12 -0.12
v 0.5 -0.5 -0.12
v -0.5 -0.12 -0.12
v -0.5 -0.12 -0.12
v 0.5 -0.5 -0.12
v -0.5 -0.5 -0.12
vn 0.0 -1.0 -0.0
vn -1.0 0.0 -0.0
vn 1.0 0.0 0.0
vn 0.0 0.0 -1.0
vn 0.0 1.0 0.0
vn 0.0 -0.0 1.0
f 1//1 2//1 3//1
f 4//1 5//1 6//1
f 7//2 8//2 9//2
f 10//2 11//2 12//2
f 13//2 14//2 15//2
f 16//2 17//2 18//2
f 19//2 20//2 21//2
f 22//2 23//2 24//2
f 25//1 26//1 27//1
f 28//1 29//1 30//1
f 31//1 32//1 33//1
f 34//1 35//1 36//1
f 37//1 38//1 39//1
f 40//1 41//1 42//1
f 43//3 44//3 45//3
f 46//3 47//3 48//3
f 49//3 50//3 51//3
f 52//3 53//3 54//3
f 55//3 56//3 57//3
f 58//3 59//3 60//3
f 61//4 62//4 63//4
f 64//4 65//4 66//4
f 67//4 68//4 69//4
f 70//4 71//4 72//4
f 73//4 74//4 75//4
f 76//4 77//4 78//4
f 79//5 80//5 81//5
f 82//5 83//5 84//5
f 85//4 86//4 87//4
f 88//4 89//4 90//4
f 91//6 92//6 93//6
f 94//6 95//6 96//6
f 97//1 98//1 99//1
f 100//1 101//1 102//1
f 103//3 104//3 105//3
f 106//3 107//3 108//3
f 109//3 110//3 111//3
f 112//3 113//3 114//3
f 115//5 116//5 117//5
f 118//5 119//5 120//5
f 121//6 122//6 123//6
f 124//6 125//6 126//6
f 127//6 128//6 129//6
f 130//6 131//6 132//6
f 133//1 134//1 135//1
f 136//1 137//1 138//1
f 139//3 140//3 141//3
f 142//3 143//3 144//3
f 145//3 146//3 147//3
f 148//3 149//3 150//3
f 151//4 152//4 153//4
f 154//4 155//4 156//4
`
const separateNumbers = string => string.split(/\s+/).slice(1).map(Number)
const loaded = obj
.split('\n')
.map(line => line.trim())
.reduce((acc, line) => {
if (line === '') return acc
const type = line.split(/\s+/)[0]
switch (type) {
case 'v':
const [x, y, z] = separateNumbers(line)
const v = { x, y, z }
if (acc.vs) {
acc.vs.push(v)
} else {
acc.vs = [v]
}
break
case 'vn':
const [xn, yn, zn] = separateNumbers(line)
const n = { x: xn, y: yn, z: zn }
if (acc.vns) {
acc.vns.push(n)
} else {
acc.vns = [n]
}
break
case 'f':
const vertices = []
const normals = []
line.split(/\s+/).slice(1).forEach(token => {
const [v, n] = token.split('//').map(Number)
vertices.push(...Object.values(acc.vs[v - 1]))
normals.push(...Object.values(acc.vns[n - 1]))
})
if (acc.vertices) {
acc.vertices.push(...vertices)
} else {
acc.vertices = [...vertices]
}
if (acc.normals) {
acc.normals.push(...normals)
} else {
acc.normals = [...normals]
}
break
default:
throw new Error(`Unrecognized type: ${type}`)
}
return acc
}, {})
const vertices = new Float32Array(loaded.vertices)
const normals = new Float32Array(loaded.normals)
const vertex = `
attribute vec4 a_position;
attribute vec3 a_normal;
uniform mat4 u_worldViewProjection;
uniform mat4 u_worldInverseTranspose;
varying vec3 v_normal;
void main() {
gl_Position = u_worldViewProjection * a_position;
v_normal = mat3(u_worldInverseTranspose) * a_normal;
}
`
const fragment = `
precision mediump float;
varying vec3 v_normal;
uniform vec3 u_reverseLightDirection;
uniform vec4 u_color;
void main() {
vec3 normal = normalize(v_normal);
float light = dot(normal, u_reverseLightDirection);
gl_FragColor = u_color;
gl_FragColor.rgb *= light * 1.5;
}
`
const setUpCanvas = () => {
const canvas = document.createElement('canvas')
canvas.setAttribute('style', `width: 100vw; height: 100vh`)
document.body.appendChild(canvas)
return canvas
}
const createShader = (gl, type, source) => {
const shader = gl.createShader(type)
gl.shaderSource(shader, source)
gl.compileShader(shader)
const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS)
if (success) return shader
console.error(gl.getShaderInfoLog(shader))
gl.deleteShader(shader)
}
const createProgram = (gl, vertexShader, fragmentShader) => {
const program = gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
const success = gl.getProgramParameter(program, gl.LINK_STATUS)
if (success) return program
console.error(gl.getProgramInfoLog(program))
gl.deleteProgram(program)
}
const degreesToRadians = angle => angle * Math.PI / 180.0
const _multiply = (a, b) => {
const a00 = a[0 * 4 + 0]
const a01 = a[0 * 4 + 1]
const a02 = a[0 * 4 + 2]
const a03 = a[0 * 4 + 3]
const a10 = a[1 * 4 + 0]
const a11 = a[1 * 4 + 1]
const a12 = a[1 * 4 + 2]
const a13 = a[1 * 4 + 3]
const a20 = a[2 * 4 + 0]
const a21 = a[2 * 4 + 1]
const a22 = a[2 * 4 + 2]
const a23 = a[2 * 4 + 3]
const a30 = a[3 * 4 + 0]
const a31 = a[3 * 4 + 1]
const a32 = a[3 * 4 + 2]
const a33 = a[3 * 4 + 3]
const b00 = b[0 * 4 + 0]
const b01 = b[0 * 4 + 1]
const b02 = b[0 * 4 + 2]
const b03 = b[0 * 4 + 3]
const b10 = b[1 * 4 + 0]
const b11 = b[1 * 4 + 1]
const b12 = b[1 * 4 + 2]
const b13 = b[1 * 4 + 3]
const b20 = b[2 * 4 + 0]
const b21 = b[2 * 4 + 1]
const b22 = b[2 * 4 + 2]
const b23 = b[2 * 4 + 3]
const b30 = b[3 * 4 + 0]
const b31 = b[3 * 4 + 1]
const b32 = b[3 * 4 + 2]
const b33 = b[3 * 4 + 3]
return [
b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30,
b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31,
b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32,
b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33,
b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30,
b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31,
b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32,
b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33,
b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30,
b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31,
b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32,
b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33,
b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30,
b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31,
b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32,
b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33,
]
}
const multiply = (...args) => {
let matrix = _multiply(args[0], args[1])
let i = 2
while (i < args.length) {
matrix = _multiply(matrix, args[i])
i += 1
}
return matrix
}
const inverse = m => {
const m00 = m[0 * 4 + 0]
const m01 = m[0 * 4 + 1]
const m02 = m[0 * 4 + 2]
const m03 = m[0 * 4 + 3]
const m10 = m[1 * 4 + 0]
const m11 = m[1 * 4 + 1]
const m12 = m[1 * 4 + 2]
const m13 = m[1 * 4 + 3]
const m20 = m[2 * 4 + 0]
const m21 = m[2 * 4 + 1]
const m22 = m[2 * 4 + 2]
const m23 = m[2 * 4 + 3]
const m30 = m[3 * 4 + 0]
const m31 = m[3 * 4 + 1]
const m32 = m[3 * 4 + 2]
const m33 = m[3 * 4 + 3]
const tmp_0 = m22 * m33
const tmp_1 = m32 * m23
const tmp_2 = m12 * m33
const tmp_3 = m32 * m13
const tmp_4 = m12 * m23
const tmp_5 = m22 * m13
const tmp_6 = m02 * m33
const tmp_7 = m32 * m03
const tmp_8 = m02 * m23
const tmp_9 = m22 * m03
const tmp_10 = m02 * m13
const tmp_11 = m12 * m03
const tmp_12 = m20 * m31
const tmp_13 = m30 * m21
const tmp_14 = m10 * m31
const tmp_15 = m30 * m11
const tmp_16 = m10 * m21
const tmp_17 = m20 * m11
const tmp_18 = m00 * m31
const tmp_19 = m30 * m01
const tmp_20 = m00 * m21
const tmp_21 = m20 * m01
const tmp_22 = m00 * m11
const tmp_23 = m10 * m01
const t0 = (tmp_0 * m11 + tmp_3 * m21 + tmp_4 * m31) -
(tmp_1 * m11 + tmp_2 * m21 + tmp_5 * m31)
const t1 = (tmp_1 * m01 + tmp_6 * m21 + tmp_9 * m31) -
(tmp_0 * m01 + tmp_7 * m21 + tmp_8 * m31)
const t2 = (tmp_2 * m01 + tmp_7 * m11 + tmp_10 * m31) -
(tmp_3 * m01 + tmp_6 * m11 + tmp_11 * m31)
const t3 = (tmp_5 * m01 + tmp_8 * m11 + tmp_11 * m21) -
(tmp_4 * m01 + tmp_9 * m11 + tmp_10 * m21)
const d = 1.0 / (m00 * t0 + m10 * t1 + m20 * t2 + m30 * t3)
return [
d * t0,
d * t1,
d * t2,
d * t3,
d * ((tmp_1 * m10 + tmp_2 * m20 + tmp_5 * m30) -
(tmp_0 * m10 + tmp_3 * m20 + tmp_4 * m30)),
d * ((tmp_0 * m00 + tmp_7 * m20 + tmp_8 * m30) -
(tmp_1 * m00 + tmp_6 * m20 + tmp_9 * m30)),
d * ((tmp_3 * m00 + tmp_6 * m10 + tmp_11 * m30) -
(tmp_2 * m00 + tmp_7 * m10 + tmp_10 * m30)),
d * ((tmp_4 * m00 + tmp_9 * m10 + tmp_10 * m20) -
(tmp_5 * m00 + tmp_8 * m10 + tmp_11 * m20)),
d * ((tmp_12 * m13 + tmp_15 * m23 + tmp_16 * m33) -
(tmp_13 * m13 + tmp_14 * m23 + tmp_17 * m33)),
d * ((tmp_13 * m03 + tmp_18 * m23 + tmp_21 * m33) -
(tmp_12 * m03 + tmp_19 * m23 + tmp_20 * m33)),
d * ((tmp_14 * m03 + tmp_19 * m13 + tmp_22 * m33) -
(tmp_15 * m03 + tmp_18 * m13 + tmp_23 * m33)),
d * ((tmp_17 * m03 + tmp_20 * m13 + tmp_23 * m23) -
(tmp_16 * m03 + tmp_21 * m13 + tmp_22 * m23)),
d * ((tmp_14 * m22 + tmp_17 * m32 + tmp_13 * m12) -
(tmp_16 * m32 + tmp_12 * m12 + tmp_15 * m22)),
d * ((tmp_20 * m32 + tmp_12 * m02 + tmp_19 * m22) -
(tmp_18 * m22 + tmp_21 * m32 + tmp_13 * m02)),
d * ((tmp_18 * m12 + tmp_23 * m32 + tmp_15 * m02) -
(tmp_22 * m32 + tmp_14 * m02 + tmp_19 * m12)),
d * ((tmp_22 * m22 + tmp_16 * m02 + tmp_21 * m12) -
(tmp_20 * m12 + tmp_23 * m22 + tmp_17 * m02))
]
}
const translation = (x, y, z) => [
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
x, y, z, 1,
]
const scaling = (x, y, z) => [
x, 0, 0, 0,
0, y, 0, 0,
0, 0, z, 0,
0, 0, 0, 1,
]
const xRotation = (angleInRadians) => {
const c = Math.cos(angleInRadians)
const s = Math.sin(angleInRadians)
return [
1, 0, 0, 0,
0, c, s, 0,
0, -s, c, 0,
0, 0, 0, 1,
]
}
const yRotation = (angleInRadians) => {
const c = Math.cos(angleInRadians)
const s = Math.sin(angleInRadians)
return [
c, 0, -s, 0,
0, 1, 0, 0,
s, 0, c, 0,
0, 0, 0, 1,
]
}
const zRotation = (angleInRadians) => {
const c = Math.cos(angleInRadians)
const s = Math.sin(angleInRadians)
return [
c, s, 0, 0,
-s, c, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]
}
const transpose = m => [
m[0], m[4], m[8], m[12],
m[1], m[5], m[9], m[13],
m[2], m[6], m[10], m[14],
m[3], m[7], m[11], m[15],
]
const perspective = (fieldOfViewInRadians, aspect, near, far) => {
const f = Math.tan(Math.PI * 0.5 - 0.5 * fieldOfViewInRadians)
const rangeInv = 1.0 / (near - far)
return [
f / aspect, 0, 0, 0,
0, f, 0, 0,
0, 0, (near + far) * rangeInv, -1,
0, 0, near * far * rangeInv * 2, 0,
]
}
const cross = (a, b) => [
a[1] * b[2] - a[2] * b[1],
a[2] * b[0] - a[0] * b[2],
a[0] * b[1] - a[1] * b[0],
]
const subtractVectors = (a, b) => [a[0] - b[0], a[1] - b[1], a[2] - b[2]]
const normalize = v => {
const length = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2])
// make sure we don't divide by 0.
if (length > 0.00001) {
return [v[0] / length, v[1] / length, v[2] / length]
} else {
return [0, 0, 0]
}
}
const lookAt = (cameraPosition, target, up) => {
var zAxis = normalize(subtractVectors(cameraPosition, target))
var xAxis = cross(up, zAxis)
var yAxis = cross(zAxis, xAxis)
return [
xAxis[0], xAxis[1], xAxis[2], 0,
yAxis[0], yAxis[1], yAxis[2], 0,
zAxis[0], zAxis[1], zAxis[2], 0,
cameraPosition[0],
cameraPosition[1],
cameraPosition[2],
1,
]
}
const setup = (gl, program, vertices, normals) => {
gl.clearColor(0, 0, 0, 0)
gl.enable(gl.CULL_FACE)
gl.enable(gl.DEPTH_TEST)
const positionLocation = gl.getAttribLocation(program, 'a_position')
const normalLocation = gl.getAttribLocation(program, 'a_normal')
const worldViewProjectionLocation = gl.getUniformLocation(program, 'u_worldViewProjection');
const worldInverseTransposeLocation = gl.getUniformLocation(program, 'u_worldInverseTranspose');
const colorLocation = gl.getUniformLocation(program, 'u_color');
const reverseLightDirectionLocation = gl.getUniformLocation(program, 'u_reverseLightDirection');
const positionBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
const normalBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer)
gl.bufferData(gl.ARRAY_BUFFER, normals, gl.STATIC_DRAW)
return {
positionLocation,
normalLocation,
worldViewProjectionLocation,
worldInverseTransposeLocation,
colorLocation,
reverseLightDirectionLocation,
positionBuffer,
normalBuffer,
}
}
const resize = gl => {
const displayWidth = Math.floor(gl.canvas.clientWidth * window.devicePixelRatio)
const displayHeight = Math.floor(gl.canvas.clientHeight * window.devicePixelRatio)
if (gl.canvas.width !== displayWidth || gl.canvas.height !== displayHeight) {
gl.canvas.width = displayWidth
gl.canvas.height = displayHeight
}
}
const draw = (gl, program, scene) => {
resize(gl)
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height)
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
gl.useProgram(program)
gl.uniform4fv(scene.colorLocation, [0.38, 0.55, 0.53, 1])
gl.uniform3fv(scene.reverseLightDirectionLocation, normalize([0.5, 0.7, 1]))
gl.enableVertexAttribArray(scene.positionLocation)
gl.bindBuffer(gl.ARRAY_BUFFER, scene.positionBuffer)
gl.vertexAttribPointer(scene.positionLocation, 3, gl.FLOAT, false, 0, 0)
gl.enableVertexAttribArray(scene.normalLocation)
gl.bindBuffer(gl.ARRAY_BUFFER, scene.normalBuffer)
gl.vertexAttribPointer(scene.normalLocation, 3, gl.FLOAT, false, 0, 0)
const fieldOfViewInRadians = degreesToRadians(60.0)
const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight
const zNear = 1
const zFar = 2000
const projectionMatrix = perspective(fieldOfViewInRadians, aspect, zNear, zFar)
const camera = [1.3, 1.3, 1.3]
const target = [0, 0, 0]
const up = [0, 1, 0]
const cameraMatrix = lookAt(camera, target, up)
const viewMatrix = inverse(cameraMatrix)
const viewProjectionMatrix = multiply(projectionMatrix, viewMatrix)
const worldMatrix = multiply(
zRotation(degreesToRadians(-180)),
yRotation(degreesToRadians(180)),
xRotation(degreesToRadians(90))
)
const worldViewProjectionMatrix = multiply(viewProjectionMatrix, worldMatrix)
const worldInverseMatrix = inverse(worldMatrix)
const worldInverseTransposeMatrix = transpose(worldInverseMatrix)
gl.uniformMatrix4fv(scene.worldViewProjectionLocation, false, worldViewProjectionMatrix)
gl.uniformMatrix4fv(scene.worldInverseTransposeLocation, false, worldInverseTransposeMatrix)
gl.drawArrays(gl.TRIANGLES, 0, vertices.length / 3)
}
const canvas = setUpCanvas()
const gl = canvas.getContext('webgl')
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertex)
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragment)
const program = createProgram(gl, vertexShader, fragmentShader)
const scene = setup(gl, program, vertices, normals)
const render = () => draw(gl, program, scene)
render()
window.addEventListener('resize', render)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment