Skip to content

Instantly share code, notes, and snippets.

@tchayen
Last active December 25, 2018 05:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tchayen/01d5146a944e16ffbdcd8ad3c91555ab to your computer and use it in GitHub Desktop.
Save tchayen/01d5146a944e16ffbdcd8ad3c91555ab to your computer and use it in GitHub Desktop.
document.documentElement.style.overflow = 'hidden'
const vertices = new Float32Array([
-1, -1, -1,
1, -1, -1,
-1, -1, 1,
-1, -1, 1,
1, -1, -1,
1, -1, 1,
1, -1, -1,
1, 1, -1,
1, -1, 1,
1, -1, 1,
1, 1, -1,
1, 1, 1,
-1, -1, -1,
1, -1, -1,
-1, 1, -1,
-1, 1, -1,
1, -1, -1,
1, 1, -1,
-1, -1, -1,
-1, 1, -1,
-1, -1, 1,
-1, -1, 1,
-1, 1, -1,
-1, 1, 1,
-1, 1, -1,
1, 1, -1,
-1, 1, 1,
-1, 1, 1,
1, 1, -1,
1, 1, 1,
-1, -1, 1,
1, -1, 1,
-1, 1, 1,
-1, 1, 1,
1, -1, 1,
1, 1, 1,
])
const vertex = `
attribute vec4 a_position;
uniform mat4 u_matrix;
void main() {
gl_Position = u_matrix * a_position;
}`
const fragment = `
precision mediump float;
void main() {
gl_FragColor = vec4(0, 0, 0, 1);
}`
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 projection = (w, h, d) => [2 / w, 0, 0, 0, 0, -h / 2, 0, 0, 0, 0, 2 / d, 0, -1, 1, 0, 1]
const setup = (gl, program, vertices) => {
gl.clearColor(0, 0, 0, 0)
// gl.enable(gl.CULL_FACE)
gl.enable(gl.DEPTH_TEST)
const positionLocation = gl.getAttribLocation(program, 'a_position')
const positionBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
const matrixLocation = gl.getUniformLocation(program, 'u_matrix');
return {
positionLocation,
positionBuffer,
matrixLocation,
}
}
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.enableVertexAttribArray(scene.positionLocation)
gl.bindBuffer(gl.ARRAY_BUFFER, scene.positionBuffer)
gl.vertexAttribPointer(scene.positionLocation, 3, gl.FLOAT, false, 0, 0)
const matrix = multiply(
projection(2, 2, 2),
translation(1, 1, 0),
xRotation(degreesToRadians(45)),
zRotation(degreesToRadians(45)),
yRotation(degreesToRadians(0)),
scaling(0.3, 0.3, 0.3)
)
gl.uniformMatrix4fv(scene.matrixLocation, false, matrix)
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)
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