Refact.
6 var canvas = document.getElementById("machine");
7 var context = new Context(canvas);
10 var object = new Cube(1, context);
11 gl.clearColor(0.0, 0.0, 0.0, 1.0);
12 gl.enable(gl.DEPTH_TEST);
13 machine = new Machine(object);
14 renderer = new Renderer(context);
20 requestAnimFrame(update);
21 machine.scene.rotation.x += (random(0, 2) - 2) * 0.001;
22 machine.scene.rotation.y += (random(0, 3) - 1) * 0.001;
23 machine.scene.rotation.z += (random(0, 2) - 1) * 0.001;
24 machine.update(new Date().getTime());
25 renderer.update(machine.scene);
28 function random(min, max)
30 return (min + Math.random() * (max - min));
33 function Renderer(context)
35 this.context = context;
37 this.matrixStack = [];
39 Renderer.prototype.update = function(scene)
41 var gl = this.context.gl;
42 var viewport = this.context.viewport;
43 var shader = this.context.shader;
44 var mvMatrix = this.context.mvMatrix;
45 var pMatrix = this.context.pMatrix;
47 gl.viewport(0, 0, viewport.width, viewport.height);
48 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
49 mat4.perspective(45, viewport.width / viewport.height, 0.1, 100.0, pMatrix);
51 mat4.identity(mvMatrix);
52 mat4.translate(mvMatrix, [0.0, 0.0, -7.0]);
54 this.pushMatrix(mvMatrix);
56 mat4.rotate(mvMatrix, scene.rotation.x, [1, 0, 0]);
57 mat4.rotate(mvMatrix, scene.rotation.y, [0, 1, 0]);
58 mat4.rotate(mvMatrix, scene.rotation.z, [0, 0, 1]);
60 gl.bindBuffer(gl.ARRAY_BUFFER, scene.positionBuffer);
61 gl.vertexAttribPointer(shader.vertexPosition, scene.positionBuffer.itemSize, gl.FLOAT, false, 0, 0);
63 gl.bindBuffer(gl.ARRAY_BUFFER, scene.colourBuffer);
64 gl.vertexAttribPointer(shader.vertexColour, scene.colourBuffer.itemSize, gl.FLOAT, false, 0, 0);
66 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, scene.indexBuffer);
67 this.context.updateMatrixUniforms();
68 gl.drawElements(gl.TRIANGLES, scene.indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
69 //gl.drawArrays(gl.TRIANGLE_STRIP, 0, scene.positionBuffer.numItems);
71 mvMatrix = this.popMatrix();
73 if (this.next) this.next.draw(scene);
75 Renderer.prototype.pushMatrix = function(matrix)
77 var copy = mat4.create();
78 mat4.set(matrix, copy);
79 this.matrixStack.push(copy);
81 Renderer.prototype.popMatrix = function()
83 if (this.matrixStack.length > 0) return this.matrixStack.pop();
86 function Machine(scene)
91 Machine.prototype.update = function(time)
93 if (this.lastUpdate != 0)
95 var diff = time - this.lastUpdate;
98 this.lastUpdate = time;
101 function Context(canvas)
103 this.canvas = canvas;
106 this.gl = canvas.getContext("experimental-webgl");
107 this.viewport = {'width': canvas.width,
108 'height': canvas.height};
114 if (!this.gl) alert("Failed: WebGL init.");
115 this.mvMatrix = mat4.create();
116 this.pMatrix = mat4.create();
117 this.shader = new Shader(this);
118 window.onresize = this.expand();
120 Context.prototype.updateMatrixUniforms = function()
123 var program = this.shader;
124 var pMatrix = this.pMatrix;
125 var mvMatrix = this.mvMatrix;
126 gl.uniformMatrix4fv(program.pMatrixUniform, false, pMatrix);
127 gl.uniformMatrix4fv(program.mvMatrixUniform, false, mvMatrix);
130 Context.prototype.expand = function()
132 var width = window.innerWidth;
133 var height = window.innerHeight;
134 this.canvas.width = width;
135 this.canvas.height = height;
136 this.viewport.width = width;
137 this.viewport.height = height;
140 function Shader(context)
143 var fragment = loadShader(gl, "fragment-shader");
144 var vertex = loadShader(gl, "vertex-shader");
145 this.program = gl.createProgram();
146 gl.attachShader(this.program, vertex);
147 gl.attachShader(this.program, fragment);
148 gl.linkProgram(this.program);
150 if (!gl.getProgramParameter(this.program, gl.LINK_STATUS))
152 alert("Failed: Shader init.");
155 gl.useProgram(this.program);
156 this.vertexPosition = gl.getAttribLocation(this.program, "aVertexPosition");
157 gl.enableVertexAttribArray(this.vertexPosition);
159 this.vertexColour = gl.getAttribLocation(this.program, "aVertexColour");
160 gl.enableVertexAttribArray(this.vertexColour);
162 this.pMatrixUniform = gl.getUniformLocation(this.program, "uPMatrix");
163 this.mvMatrixUniform = gl.getUniformLocation(this.program, "uMVMatrix");
165 function loadShader(gl, id)
167 var script = document.getElementById(id);
168 if (!script) return null;
171 var child = script.firstChild;
174 if (child.nodeType == 3) str += child.textContent;
175 child = child.nextSibling;
179 var common = "x-shader/x-";
180 if (script.type == common + "fragment") shader = gl.createShader(gl.FRAGMENT_SHADER);
181 else if (script.type == common + "vertex") shader = gl.createShader(gl.VERTEX_SHADER);
184 gl.shaderSource(shader, str);
185 gl.compileShader(shader);
187 if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
189 alert(gl.getShaderInfoLog(shader));
198 function Cube(size, context)
201 this.size = size || 1;
202 this.rotation = {'x': 0.0, 'y': 0.0, 'z': 0.0};
204 this.positionBuffer = gl.createBuffer();
205 gl.bindBuffer(gl.ARRAY_BUFFER, this.positionBuffer);
242 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
243 this.positionBuffer.itemSize = 3;
244 this.positionBuffer.numItems = 24;
246 this.colourBuffer = gl.createBuffer();
247 gl.bindBuffer(gl.ARRAY_BUFFER, this.colourBuffer);
249 var colours = [[1.0, 0.0, 0.0, alpha],
250 [0.0, 1.0, 0.0, alpha],
251 [0.0, 0.0, 1.0, alpha],
252 [1.0, 0.0, 1.0, alpha],
253 [1.0, 1.0, 0.0, alpha],
254 [0.0, 1.0, 1.0, alpha]];
255 var unpackedColours = [];
256 for (var i in colours)
258 var colour = colours[i];
259 for (var j = 0; j < 4; j++)
261 unpackedColours = unpackedColours.concat(colour);
263 //colours = colours.concat([0.5, 0.5, 1.0, 1.0]);
265 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(unpackedColours), gl.STATIC_DRAW);
266 this.colourBuffer.itemSize = 4;
267 this.colourBuffer.numItems = 24;
269 this.indexBuffer = gl.createBuffer();
270 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
271 var indices = [0, 1, 2, 0, 2, 3,
274 12, 13, 14, 12, 14, 15,
275 16, 17, 18, 16, 18, 19,
276 20, 21, 22, 20, 22, 23];
277 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
278 this.indexBuffer.itemSize = 1;
279 this.indexBuffer.numItems = 36;