Demonstrates the fundamentals of using the WebGL API.
Last active
February 11, 2018 13:50
-
-
Save mathdoodle/69a4edb74810531611d1 to your computer and use it in GitHub Desktop.
WebGL Fundamentals
This file contains hidden or 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
/** | |
* Converts a null argument into an exception. | |
* reason is the error message reported if the arg is null. | |
*/ | |
export function denullify<T>(reason: string, arg: T | null): T { | |
if (arg !== null) { | |
return arg | |
} | |
else { | |
throw new Error(reason) | |
} | |
} | |
/** | |
* Interprets a null argument as an out of memory condition. | |
*/ | |
export function memcheck<T>(arg: T | null): T { | |
return denullify("Out of memory", arg) | |
} |
This file contains hidden or 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
<!DOCTYPE html> | |
<html> | |
<head> | |
<base href='/'> | |
<script src='https://jspm.io/[email protected]'></script> | |
<link rel='stylesheet' href='style.css'> | |
</head> | |
<body> | |
<canvas id='my-canvas' width='500' height='500'> | |
Your browser does not support the HTML5 canvas element. | |
</canvas> | |
<script> | |
System.defaultJSExtensions = true | |
System.import('./script') | |
</script> | |
</body> | |
</html> |
This file contains hidden or 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
/** | |
* | |
*/ | |
export function initWebGL(canvas: HTMLCanvasElement): WebGLRenderingContext { | |
// Try to grab the standard context. If it fails, fallback to experimental. | |
const context = canvas.getContext('webgl') || canvas.getContext('experimental-webgl') | |
if (context) { | |
return context | |
} | |
else { | |
throw new Error("Unable to initialize WebGL. Your browser may not support it.") | |
} | |
} |
This file contains hidden or 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
import { memcheck } from './denullify' | |
/** | |
* Creates a WebGLProgram with compiled and linked shaders. | |
*/ | |
export function makeProgram(gl: WebGLRenderingContext, vertexShader: string, fragmentShader: string): WebGLProgram { | |
const vs = memcheck(gl.createShader(gl.VERTEX_SHADER)) | |
gl.shaderSource(vs, vertexShader) | |
gl.compileShader(vs) | |
if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) { | |
throw new Error(memcheck(gl.getShaderInfoLog(vs))) | |
} | |
const fs = memcheck(gl.createShader(gl.FRAGMENT_SHADER)) | |
gl.shaderSource(fs, fragmentShader) | |
gl.compileShader(fs) | |
if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) { | |
throw new Error(memcheck(gl.getShaderInfoLog(fs))) | |
} | |
const program = memcheck(gl.createProgram()) | |
gl.attachShader(program, vs) | |
gl.attachShader(program, fs) | |
gl.linkProgram(program) | |
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { | |
throw new Error(memcheck(gl.getProgramInfoLog(program))) | |
} | |
return program | |
} |
This file contains hidden or 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
{ | |
"name": "webgl", | |
"version": "1.0.0", | |
"description": "WebGL Fundamentals", | |
"dependencies": { | |
"DomReady": "1.0.0", | |
"gl-matrix": "2.3.2" | |
}, | |
"author": "David Geo Holmes", | |
"keywords": [ | |
"WebGL", | |
"shaders", | |
"low level", | |
"GLSL", | |
"Graphics", | |
"mathdoodle" | |
], | |
"linting": true, | |
"hideConfigFiles": true | |
} |
This file contains hidden or 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
import { denullify, memcheck } from './denullify' | |
import { initWebGL } from './initWebGL' | |
import { makeProgram } from './makeProgram' | |
DomReady.ready(main) | |
function main() { | |
const canvas = <HTMLCanvasElement> document.getElementById('my-canvas') | |
const gl: WebGLRenderingContext = initWebGL(canvas) | |
// Compile and link the shaders into a program. | |
const vs_source = denullify('shader-vs does not exist in DOM', document.getElementById('shader-vs')).innerText | |
const fs_source = denullify('shader-fs does not exist in DOM', document.getElementById('shader-fs')).innerText | |
const program = makeProgram(gl, vs_source, fs_source) | |
gl.useProgram(program) | |
const colors: number[] = [ | |
// front face | |
1.0, 0.0, 0.0, // 0 | |
1.0, 0.0, 0.0, // 1 | |
1.0, 0.0, 0.0, // 2 | |
0.0, 0.0, 1.0, // 3 | |
0.0, 0.0, 1.0, // 4 | |
0.0, 0.0, 1.0, // 5 | |
// rear face | |
1.0, 0.0, 0.0, // 6 | |
1.0, 0.0, 0.0, // 7 | |
1.0, 0.0, 0.0, // 8 | |
0.0, 0.0, 1.0, // 9 | |
0.0, 0.0, 1.0, // 10 | |
0.0, 0.0, 1.0 // 11 | |
] | |
const cbo = memcheck(gl.createBuffer()) | |
gl.bindBuffer(gl.ARRAY_BUFFER, cbo) | |
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW) | |
const vertices: number[] = [ | |
0.0, 0.0, 0.0, // 0 | |
1.0, 0.0, 0.0, // 1 | |
2.0, 0.0, 0.0, // 2 | |
0.5, 1.0, 0.0, // 3 | |
1.5, 1.0, 0.0, // 4 | |
1.0, 2.0, 0.0, // 5 | |
0.0, 0.0, -2.0, // 6 | |
1.0, 0.0, -2.0, // 7 | |
2.0, 0.0, -2.0, // 8 | |
0.5, 1.0, -2.0, // 9 | |
1.5, 1.0, -2.0, // 10 | |
1.0, 2.0, -2.0 // 11 | |
] | |
const vbo = memcheck(gl.createBuffer()) | |
gl.bindBuffer(gl.ARRAY_BUFFER, vbo) | |
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW) | |
const indices: number[] = [ | |
// front face | |
0, 1, 3, // 0 | |
1, 3, 4, // 1 | |
1, 2, 4, // 2 | |
3, 4, 5, // 3 | |
// rear face | |
6, 7, 9, // 4 | |
7, 9, 10, // 5 | |
7, 8, 10, // 6 | |
9, 10, 11, // 7 | |
// left side | |
0, 3, 6, // 8 | |
3, 6, 9, // 9 | |
3, 5, 9, // 10 | |
5, 9, 11, // 11 | |
// right side | |
2, 4, 8, // 12 | |
4, 8, 10, // 13 | |
4, 5, 10, // 14 | |
5, 10, 11, // 15 | |
// bottom | |
0, 6, 8, // 16 | |
8, 2, 0 // 17 | |
] | |
const ibo = memcheck(gl.createBuffer()) | |
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo) | |
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW) | |
const mvMatrix = <Float32Array> mat4.create() | |
const pMatrix = <Float32Array> mat4.create() | |
const uMVMatrix = denullify('uMVMatrix does not exist in program', gl.getUniformLocation(program, 'uMVMatrix')) | |
const uPMatrix = denullify('uPMatrix does not exist in program', gl.getUniformLocation(program, 'uPMatrix')) | |
let angle = 0 | |
function animLoop() { | |
// Clear the viewport. | |
gl.clearColor(0.5, 0.5, 0.6, 1.0) | |
gl.enable(gl.DEPTH_TEST) | |
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) | |
gl.viewport(0, 0, canvas.width, canvas.height) | |
mat4.perspective(pMatrix, 45, canvas.width / canvas.height, 0.1, 100.0) | |
mat4.identity(mvMatrix) | |
mat4.translate(mvMatrix, mvMatrix, [-1.0, -1.0, -7.0]) | |
mat4.rotate(mvMatrix, mvMatrix, angle, [0.0, 1.0, 0.0]) | |
const aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition') | |
gl.enableVertexAttribArray(aVertexPosition) | |
gl.bindBuffer(gl.ARRAY_BUFFER, vbo) | |
gl.vertexAttribPointer(aVertexPosition, 3, gl.FLOAT, false, 0, 0) | |
const aVertexColor = gl.getAttribLocation(program, 'aVertexColor') | |
gl.enableVertexAttribArray(aVertexColor) | |
gl.bindBuffer(gl.ARRAY_BUFFER, cbo) | |
gl.vertexAttribPointer(aVertexColor, 3, gl.FLOAT, false, 0, 0) | |
gl.uniformMatrix4fv(uMVMatrix, false, mvMatrix) | |
gl.uniformMatrix4fv(uPMatrix, false, pMatrix) | |
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo) | |
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0) | |
angle += 0.01 | |
requestAnimationFrame(animLoop) | |
} | |
animLoop() | |
} |
This file contains hidden or 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
varying highp vec4 vColor; | |
void main(void) { | |
gl_FragColor = vColor; | |
} |
This file contains hidden or 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
attribute vec3 aVertexPosition; | |
attribute vec3 aVertexColor; | |
uniform mat4 uMVMatrix; | |
uniform mat4 uPMatrix; | |
varying highp vec4 vColor; | |
void main(void) { | |
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); | |
vColor = vec4(aVertexColor, 1.0); | |
gl_PointSize = 10.0; | |
} |
This file contains hidden or 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
body { | |
background-color: blue; | |
} | |
canvas { | |
background-color: black; | |
position: absolute; | |
left: 10px; | |
top: 10px; | |
} |
This file contains hidden or 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
{ | |
"allowJs": false, | |
"declaration": true, | |
"emitDecoratorMetadata": true, | |
"experimentalDecorators": true, | |
"jsx": "react", | |
"module": "system", | |
"noImplicitAny": true, | |
"noImplicitReturns": true, | |
"noImplicitThis": true, | |
"noUnusedLocals": true, | |
"noUnusedParameters": true, | |
"preserveConstEnums": true, | |
"removeComments": false, | |
"sourceMap": true, | |
"strictNullChecks": true, | |
"suppressImplicitAnyIndexErrors": true, | |
"target": "es5", | |
"traceResolution": true | |
} |
This file contains hidden or 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
{ | |
"rules": { | |
"array-type": [ | |
true, | |
"array" | |
], | |
"curly": false, | |
"comment-format": [ | |
true, | |
"check-space" | |
], | |
"eofline": true, | |
"forin": true, | |
"jsdoc-format": true, | |
"no-conditional-assignment": false, | |
"no-consecutive-blank-lines": true, | |
"no-construct": true, | |
"no-for-in-array": true, | |
"no-magic-numbers": false, | |
"no-shadowed-variable": true, | |
"no-string-throw": true, | |
"no-trailing-whitespace": [ | |
true, | |
"ignore-jsdoc" | |
], | |
"no-var-keyword": true, | |
"one-variable-per-declaration": [ | |
true, | |
"ignore-for-loop" | |
], | |
"prefer-const": true, | |
"prefer-for-of": true, | |
"prefer-function-over-method": false, | |
"radix": true, | |
"semicolon": [ | |
true, | |
"never" | |
], | |
"trailing-comma": [ | |
true, | |
{ | |
"multiline": "never", | |
"singleline": "never" | |
} | |
], | |
"triple-equals": true, | |
"use-isnan": true | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
hjvrsbwevhwabe