Last active
December 25, 2018 05:29
-
-
Save tchayen/01d5146a944e16ffbdcd8ad3c91555ab to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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