A starting point for learning Geometry using the WebGL API.
Last active
July 7, 2020 20:35
-
-
Save mathdoodle/47e0cf9bffd69d8ee6a8fc6188b98955 to your computer and use it in GitHub Desktop.
Geometry using WebGL from Ground Zero
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
/** | |
* Displays an exception by writing it to a <pre> element. | |
*/ | |
export function displayError(e: any) { | |
const stderr = <HTMLPreElement> document.getElementById('my-output') | |
stderr.style.color = "#FF0000" | |
stderr.innerHTML = `${e}` | |
} |
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
/** | |
* Returns the canvas element identified by elementId. | |
* If the element is not found, or if it is not a canvas element, | |
* an Error is thrown. | |
*/ | |
export function getCanvasElementById(elementId: string): HTMLCanvasElement { | |
const element = document.getElementById(elementId) | |
if (element) { | |
// Further checks here that we have the script element we need? | |
if (element.nodeName.toLowerCase() === 'canvas') { | |
return element as HTMLCanvasElement | |
} | |
else { | |
throw new Error(`elementId: ${element.nodeName} ${elementId} does not identify a canvas element.`) | |
} | |
} | |
else { | |
throw new Error(`elementId ${elementId} does not identify an element.`) | |
} | |
} | |
/** | |
* Returns the script element identified by elementId. | |
* If the element is not found, or if it is not a script element, | |
* an Error is thrown. | |
*/ | |
export function getScriptElementById(elementId: string): HTMLScriptElement { | |
const element = document.getElementById(elementId) | |
if (element) { | |
// Further checks here that we have the script element we need? | |
if (element.nodeName.toLowerCase() === 'script') { | |
return element as HTMLScriptElement | |
} | |
else { | |
throw new Error(`elementId ${elementId} does not identify a script element.`) | |
} | |
} | |
else { | |
throw new Error(`elementId ${elementId} does not identify an element.`) | |
} | |
} |
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 getWebGLContext(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
<!DOCTYPE html> | |
<html> | |
<head> | |
<script src="https://jspm.io/system.js"></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> | |
<pre id='my-output'></pre> | |
<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
import { displayError } from './displayError' | |
/** | |
* Creates a WebGLProgram with compiled and linked shaders. | |
*/ | |
function makeProgramInternal(gl: WebGLRenderingContext, vertexShader: string, fragmentShader: string): WebGLProgram { | |
const vs = gl.createShader(gl.VERTEX_SHADER) | |
gl.shaderSource(vs, vertexShader) | |
gl.compileShader(vs) | |
if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) { | |
throw new Error(`VERTEX_SHADER: ${gl.getShaderInfoLog(vs)}`) | |
} | |
const fs = gl.createShader(gl.FRAGMENT_SHADER) | |
gl.shaderSource(fs, fragmentShader) | |
gl.compileShader(fs) | |
if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) { | |
throw new Error(`FRAGMENT_SHADER: ${gl.getShaderInfoLog(fs)}`) | |
} | |
const program = gl.createProgram() | |
if (program) { | |
gl.attachShader(program, vs) | |
gl.attachShader(program, fs) | |
gl.linkProgram(program) | |
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { | |
const msg = gl.getProgramInfoLog(program) | |
if (typeof msg === 'string') { | |
throw new Error(msg) | |
} | |
} | |
return program | |
} | |
else { | |
throw new Error("Out of memory") | |
} | |
} | |
export function makeProgram(gl: WebGLRenderingContext, vertexShader: string, fragmentShader: string): WebGLProgram { | |
try { | |
return makeProgramInternal(gl, vertexShader, fragmentShader) | |
} | |
catch (e) { | |
displayError(e) | |
throw e | |
} | |
} |
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": "copy-of-webgl-from-ground-zero", | |
"version": "0.1.0", | |
"description": "Geometry using WebGL from Ground Zero", | |
"dependencies": { | |
"DomReady": "1.0.0", | |
"gl-matrix": "2.3.2" | |
}, | |
"operatorOverloading": true, | |
"keywords": [ | |
"WebGL", | |
"shaders", | |
"low level", | |
"GLSL", | |
"Graphics", | |
"Geometry", | |
"mathdoodle" | |
], | |
"author": "David Geo Holmes", | |
"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 { displayError } from './displayError' | |
/** | |
* Catches exceptions thrown in the animation callback and displays them. | |
*/ | |
export function requestFrame(callback: FrameRequestCallback): number { | |
const wrapper: FrameRequestCallback = function(time: number) { | |
try { | |
callback(time) | |
} | |
catch (e) { | |
displayError(e) | |
} | |
} | |
return window.requestAnimationFrame(wrapper) | |
} |
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 { displayError } from './displayError' | |
import { getWebGLContext } from './getWebGLContext' | |
import { makeProgram } from './makeProgram' | |
import { requestFrame } from './requestFrame' | |
import { getCanvasElementById, getScriptElementById } from './domUtils' | |
const canvas = getCanvasElementById('my-canvas') | |
const gl = getWebGLContext(canvas) | |
const vertexShader = getScriptElementById('shader-vs').innerText | |
const fragmentShader = getScriptElementById('shader-fs').innerText | |
const program = makeProgram(gl, vertexShader, fragmentShader) | |
gl.useProgram(program) | |
const vbo = gl.createBuffer() | |
const data = new Float32Array(2) | |
try { | |
data[0] = 0.0 | |
data[1] = 0.0 | |
gl.bindBuffer(gl.ARRAY_BUFFER, vbo) | |
gl.bufferData(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW) | |
} | |
catch (e) { | |
displayError(e) | |
} | |
function animate() { | |
const aVertexPosition = gl.getAttribLocation(program, 'aPosition') | |
gl.enableVertexAttribArray(aVertexPosition) | |
gl.bindBuffer(gl.ARRAY_BUFFER, vbo) | |
gl.vertexAttribPointer(aVertexPosition, 2, gl.FLOAT, false, 0, 0) | |
gl.drawArrays(gl.POINTS, 0, 1) | |
} | |
requestFrame(animate) |
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
void main(void) { | |
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.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
attribute vec2 aPosition; | |
void main(void) { | |
gl_Position = vec4(aPosition, 0.0, 1.0); | |
gl_PointSize = 6.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: white; } | |
canvas { | |
background-color: black; | |
position: absolute; | |
left: 15px; | |
top: 15px; | |
z-index: 0; | |
} | |
pre { | |
position: relative; | |
color: rgb(255, 255, 255); | |
left: 15px; | |
z-index: 1; | |
font-size: 18px; | |
} | |
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
Show hidden characters
{ | |
"allowJs": true, | |
"checkJs": true, | |
"declaration": true, | |
"emitDecoratorMetadata": true, | |
"experimentalDecorators": true, | |
"jsx": "react", | |
"module": "system", | |
"noImplicitAny": true, | |
"noImplicitReturns": true, | |
"noImplicitThis": true, | |
"noUnusedLocals": true, | |
"noUnusedParameters": true, | |
"preserveConstEnums": true, | |
"removeComments": false, | |
"skipLibCheck": true, | |
"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, | |
"new-parens": true, | |
"no-conditional-assignment": false, | |
"no-consecutive-blank-lines": true, | |
"no-construct": true, | |
"no-for-in-array": true, | |
"no-inferrable-types": [ | |
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, | |
"prefer-method-signature": true, | |
"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