sawine@24: function Context(canvas) sawine@24: { sawine@24: this.canvas = canvas; sawine@24: try sawine@24: { sawine@24: this.gl = canvas.getContext("experimental-webgl"); sawine@24: this.viewport = {'width': canvas.width, sawine@24: 'height': canvas.height}; sawine@24: } sawine@24: catch(e) sawine@24: { sawine@24: alert(e); sawine@24: } sawine@24: if (!this.gl) alert("Failed: WebGL init."); sawine@24: this.mvMatrix = mat4.create(); sawine@24: this.pMatrix = mat4.create(); sawine@24: this.shader = new Shader(this); sawine@24: } sawine@24: Context.prototype.updateMatrixUniforms = function() sawine@24: { sawine@24: var gl = this.gl; sawine@24: var program = this.shader; sawine@24: var pMatrix = this.pMatrix; sawine@24: var mvMatrix = this.mvMatrix; sawine@25: sawine@24: gl.uniformMatrix4fv(program.pMatrixUniform, false, pMatrix); sawine@24: gl.uniformMatrix4fv(program.mvMatrixUniform, false, mvMatrix); sawine@24: var normalMatrix = mat3.create(); sawine@24: mat4.toInverseMat3(mvMatrix, normalMatrix); sawine@24: mat3.transpose(normalMatrix); sawine@24: gl.uniformMatrix3fv(program.nMatrixUniform, false, normalMatrix); sawine@24: } sawine@24: Context.prototype.expand = function() sawine@24: { sawine@24: var width = window.innerWidth; sawine@24: var height = window.innerHeight; sawine@24: this.canvas.width = width; sawine@24: this.canvas.height = height; sawine@24: this.viewport.width = width; sawine@24: this.viewport.height = height; sawine@24: } sawine@24: sawine@24: function Shader(context) sawine@24: { sawine@24: var gl = context.gl; sawine@24: var fragment = loadShader(gl, "fragment-shader"); sawine@24: var vertex = loadShader(gl, "vertex-shader"); sawine@24: this.program = gl.createProgram(); sawine@24: gl.attachShader(this.program, vertex); sawine@24: gl.attachShader(this.program, fragment); sawine@24: gl.linkProgram(this.program); sawine@24: sawine@24: if (!gl.getProgramParameter(this.program, gl.LINK_STATUS)) sawine@24: { sawine@24: alert("Failed: Shader init."); sawine@24: } sawine@24: sawine@24: gl.useProgram(this.program); sawine@24: this.vertexPosition = gl.getAttribLocation(this.program, "aVertexPosition"); sawine@24: gl.enableVertexAttribArray(this.vertexPosition); sawine@24: sawine@24: this.vertexNormal = gl.getAttribLocation(this.program, "aVertexNormal"); sawine@24: gl.enableVertexAttribArray(this.vertexNormal); sawine@25: sawine@25: this.vertexColour = gl.getAttribLocation(this.program, "aVertexColour"); sawine@25: gl.enableVertexAttribArray(this.vertexColour); sawine@24: sawine@36: this.textureCoord = gl.getAttribLocation(this.program, "aTextureCoord"); sawine@36: gl.enableVertexAttribArray(this.textureCoord); sawine@36: sawine@24: this.pMatrixUniform = gl.getUniformLocation(this.program, "uPMatrix"); sawine@24: this.mvMatrixUniform = gl.getUniformLocation(this.program, "uMVMatrix"); sawine@24: this.nMatrixUniform = gl.getUniformLocation(this.program, "uNMatrix"); sawine@36: this.samplerUniform = gl.getUniformLocation(this.program, "uSampler"); sawine@33: this.materialShininessUniform = gl.getUniformLocation(this.program, "uMaterialShininess"); sawine@24: this.useLightingUniform = gl.getUniformLocation(this.program, "uUseLighting"); sawine@36: this.useTexture = gl.getUniformLocation(this.program, "uUseTexture"); sawine@24: this.ambientColourUniform = gl.getUniformLocation(this.program, "uAmbientColour"); sawine@24: this.lightingDirectionUniform = gl.getUniformLocation(this.program, "uLightingDirection"); sawine@24: this.directionalColourUniform = gl.getUniformLocation(this.program, "uDirectionalColour"); sawine@30: this.pointLightingLocationUniform = gl.getUniformLocation(this.program, "uPointLightingLocation"); sawine@33: this.pointLightingSpecularColourUniform = gl.getUniformLocation(this.program, "uPointLightingSpecularColour"); sawine@33: this.pointLightingDiffuseColourUniform = gl.getUniformLocation(this.program, "uPointLightingDiffuseColour"); sawine@24: sawine@24: function loadShader(gl, id) sawine@24: { sawine@24: var script = document.getElementById(id); sawine@24: if (!script) return null; sawine@24: sawine@24: var str = ""; sawine@24: var child = script.firstChild; sawine@24: while (child) sawine@24: { sawine@24: if (child.nodeType == 3) str += child.textContent; sawine@24: child = child.nextSibling; sawine@24: } sawine@24: sawine@24: var shader; sawine@24: var common = "x-shader/x-"; sawine@24: if (script.type == common + "fragment") shader = gl.createShader(gl.FRAGMENT_SHADER); sawine@24: else if (script.type == common + "vertex") shader = gl.createShader(gl.VERTEX_SHADER); sawine@24: else return null; sawine@24: sawine@24: gl.shaderSource(shader, str); sawine@24: gl.compileShader(shader); sawine@24: sawine@24: if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) sawine@24: { sawine@24: alert(gl.getShaderInfoLog(shader)); sawine@24: return null; sawine@24: } sawine@24: sawine@24: return shader; sawine@24: } sawine@24: } sawine@24: sawine@24: function Renderer(camera, context) sawine@24: { sawine@24: this.camera = camera; sawine@24: this.context = context; sawine@24: this.gl = context.gl; sawine@24: this.matrixStack = []; sawine@24: } sawine@24: Renderer.prototype.update = function(scene) sawine@24: { sawine@31: var gl = this.context.gl; sawine@31: var shader = this.context.shader; sawine@24: var viewport = this.context.viewport; sawine@24: var mvMatrix = this.context.mvMatrix; sawine@24: var pMatrix = this.context.pMatrix; sawine@24: var camera = this.camera; sawine@24: sawine@24: gl.viewport(0, 0, viewport.width, viewport.height); sawine@24: gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); sawine@34: mat4.perspective(45, viewport.width / viewport.height, 0.1, 1000.0, pMatrix); sawine@24: sawine@31: var lighting = true; sawine@31: gl.uniform1i(shader.useLightingUniform, lighting); sawine@35: gl.uniform1f(shader.materialShininessUniform, 20.0); sawine@31: sawine@31: if (lighting) sawine@31: { sawine@31: var uni = 0.0; sawine@31: gl.uniform3f(shader.ambientColourUniform, uni, uni, uni); sawine@31: sawine@31: var pos = [0, 0, 0]; sawine@31: gl.uniform3f(shader.pointLightingLocationUniform, pos[0], pos[1], pos[2]); sawine@35: uni = 1.0; sawine@33: gl.uniform3f(shader.pointLightingSpecularColourUniform, uni, uni, uni); sawine@38: uni = .07; sawine@33: gl.uniform3f(shader.pointLightingDiffuseColourUniform, uni, uni, uni); sawine@31: sawine@31: // var lightingDir = vec3.create(); sawine@31: // vec3.add(lightingDir, [0.5, -0.5, 0.0]); sawine@31: // vec3.normalize(lightingDir); sawine@31: // vec3.scale(lightingDir, -1); sawine@31: // gl.uniform3fv(shader.lightingDirectionUniform, lightingDir); sawine@31: sawine@31: // uni = 0.9; sawine@31: // var directional = {"r": uni, "g": uni, "b": uni}; sawine@31: // gl.uniform3f(shader.directionalColourUniform, directional.r, directional.g, directional.b); sawine@31: } sawine@31: sawine@24: mat4.identity(mvMatrix); sawine@27: mat4.multiply(mvMatrix, camera.matrix); sawine@28: sawine@28: this.draw(scene); sawine@28: if (this.next) this.next.update(scene); sawine@28: } sawine@28: Renderer.prototype.draw = function(node) sawine@28: { sawine@28: var gl = this.context.gl; sawine@28: var shader = this.context.shader; sawine@28: var mvMatrix = this.context.mvMatrix; sawine@28: var pMatrix = this.context.pMatrix; sawine@28: sawine@28: if (node) sawine@28: { sawine@28: this.pushMatrix(mvMatrix); sawine@28: mat4.translate(mvMatrix, node.pos); sawine@28: //mat4.rotate(mvMatrix, node.rot); sawine@28: //mat4.multiply(mvMatrix, node.matrix); sawine@35: var geometry = node.geometry; sawine@35: if (geometry) sawine@28: { sawine@35: var object = geometry.vbo; sawine@28: gl.bindBuffer(gl.ARRAY_BUFFER, object.positionBuffer); sawine@28: gl.vertexAttribPointer(shader.vertexPosition, object.positionBuffer.itemSize, gl.FLOAT, false, 0, 0); sawine@28: sawine@28: gl.bindBuffer(gl.ARRAY_BUFFER, object.normalBuffer); sawine@28: gl.vertexAttribPointer(shader.vertexNormal, object.normalBuffer.itemSize, gl.FLOAT, false, 0, 0); sawine@24: sawine@36: gl.bindBuffer(gl.ARRAY_BUFFER, object.textureCoordBuffer); sawine@36: gl.vertexAttribPointer(shader.textureCoord, object.textureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0); sawine@36: gl.activeTexture(gl.TEXTURE0); sawine@36: if (object.texture && object.useTexture) sawine@36: { sawine@36: gl.uniform1i(shader.useTexture, true); sawine@36: sawine@36: gl.bindTexture(gl.TEXTURE_2D, object.texture.hnd); sawine@36: gl.uniform1i(shader.samplerUniform, 0); sawine@36: } sawine@36: else sawine@36: { sawine@36: gl.uniform1i(shader.useTexture, false); sawine@36: sawine@36: } sawine@28: gl.bindBuffer(gl.ARRAY_BUFFER, object.colourBuffer); sawine@28: gl.vertexAttribPointer(shader.vertexColour, object.colourBuffer.itemSize, gl.FLOAT, false, 0, 0); sawine@28: sawine@28: gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, object.indexBuffer); sawine@28: this.context.updateMatrixUniforms(); sawine@28: gl.drawElements(gl.TRIANGLES, object.indexBuffer.numItems, gl.UNSIGNED_SHORT, 0); sawine@28: //gl.drawArrays(gl.TRIANGLE_STRIP, 0, scene.positionBuffer.numItems); sawine@28: } sawine@24: sawine@28: for (var id in node.children) sawine@28: { sawine@28: this.mvMatrix = mvMatrix; sawine@28: this.draw(node.children[id]); sawine@28: } sawine@29: this.context.mvMatrix = this.popMatrix(); sawine@24: } sawine@24: } sawine@24: Renderer.prototype.pushMatrix = function(matrix) sawine@24: { sawine@24: var copy = mat4.create(); sawine@24: mat4.set(matrix, copy); sawine@24: this.matrixStack.push(copy); sawine@24: } sawine@24: Renderer.prototype.popMatrix = function() sawine@24: { sawine@24: if (this.matrixStack.length > 0) return this.matrixStack.pop(); sawine@24: }