Skip to content

Instantly share code, notes, and snippets.

@mathdoodle
Last active August 29, 2015 14:22
Show Gist options
  • Save mathdoodle/f8cbd86b803bd4cebd50 to your computer and use it in GitHub Desktop.
Save mathdoodle/f8cbd86b803bd4cebd50 to your computer and use it in GitHub Desktop.
WebGL Experiment
{
"uuid": "bbfa42ad-3a1d-41a2-a752-7d700d0f9b13",
"description": "WebGL Experiment",
"dependencies": {
"DomReady": "latest",
"gl-matrix": "2.2.1"
}
}
<!doctype html>
<html>
<head>
<style>
/* STYLE-MARKER */
</style>
<script id='shader-vs' type='x-shader/x-vertex'>
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;
}
</script>
<script id='shader-fs' type='x-shader/x-fragment'>
varying highp vec4 vColor;
void main(void) {
gl_FragColor = vColor;
}
</script>
<!-- SCRIPTS-MARKER -->
<script>
// CODE-MARKER
</script>
</head>
<body>
<canvas id='my-canvas' width='400' height='300'>
Your browser does not support the HTML5 canvas element.
</canvas>
</body>
</html>
DomReady.ready(main);
interface Drawable {
getIndexArray(): Uint16Array;
getIndexLength(): number;
getVertexArray(): Float32Array;
}
function main() {
var canvas = <HTMLCanvasElement>document.getElementById('my-canvas');
var gl: WebGLRenderingContext = initWebGL(canvas);
// Compile and link the shaders into a program.
var vs_source = document.getElementById('shader-vs').innerText;
var fs_source = document.getElementById('shader-fs').innerText;
var program = makeProgram(gl, vs_source, fs_source);
gl.useProgram(program);
var 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
];
var cbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cbo);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
var prism = makePrism();
var vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, prism.getVertexArray(), gl.STATIC_DRAW);
var ibo = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, prism.getIndexArray(), gl.STATIC_DRAW);
var mvMatrix = <Float32Array>mat4.create();
var pMatrix = <Float32Array>mat4.create();
var uMVMatrix = gl.getUniformLocation(program, 'uMVMatrix');
var uPMatrix = gl.getUniformLocation(program, 'uPMatrix');
var 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]);
var aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition');
gl.enableVertexAttribArray(aVertexPosition);
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.vertexAttribPointer(aVertexPosition, 3, gl.FLOAT, false, 0, 0);
var 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, prism.getIndexLength(), gl.UNSIGNED_SHORT, 0);
angle += 0.01;
requestAnimationFrame(animLoop);
}
animLoop();
}
function initWebGL(canvas: HTMLCanvasElement): WebGLRenderingContext {
var context: WebGLRenderingContext = null;
try {
// Try to grab the standard context. If it fails, fallback to experimental.
context = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
}
catch(e) {
}
if (context) {
return context;
}
else {
throw new Error("Unable to initialize WebGL. Your browser may not support it.");
}
}
/**
* Creates a WebGLProgram with compiled and linked shaders.
*/
function makeProgram(gl: WebGLRenderingContext, vertexShader: string, fragmentShader: string): WebGLProgram {
// TODO: Proper cleanup if we throw an error at any point.
var vs = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vs, vertexShader);
gl.compileShader(vs);
if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) {
throw new Error(gl.getShaderInfoLog(vs));
}
var fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fs, fragmentShader);
gl.compileShader(fs);
if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {
throw new Error(gl.getShaderInfoLog(fs));
}
var program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
throw new Error(gl.getProgramInfoLog(program));
}
return program;
}
class Prism implements Drawable {
private indices: number[];
private vertices: number[];
constructor(indices: number[], vertices: number[]) {
this.indices = indices;
this.vertices = vertices;
}
getIndexArray(): Uint16Array {
return new Uint16Array(this.indices);
}
getIndexLength(): number {
return this.indices.length;
}
getVertexArray(): Float32Array {
return new Float32Array(this.vertices);
}
}
function makePrism(): Drawable {
var 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
];
var 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
];
return new Prism(indices, vertices);
}
body { background-color: white; }
canvas {
background-color: black;
position: absolute;
left: 200px;
top: 100px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment