API Docs for: 0.2.0
Show:

File: src\renderers\WebGLRenderer.js

/**
 * The WebGLRenderer class renders the Scene using a WebGL canvas context and a camera
 *
 * @class WebGLRenderer
 * @constructor
 * @param {Object} parameters Parameters is an object that contains the WebGLRenderers properties
 * @param {DOMElement} parameters.canvas
 * @param {LE.Scene} [parameters.scene=new LE.Scene()]
 * @param {LE.OrthographicCamera} [parameters.camera=new LE.OrthographicCamera(0, 0)]
 */
LE.WebGLRenderer = function(parameters) {
    if(parameters == null) {
        console.error("To create a WebGLRenderer a canvas needs to be provided.")
    }
    // Variable declarations
    /**
     * Stores the WebGL canvas context
     *
     * @private
     * @property gl
     * @type Object
     */
    this.gl,
    /**
     * Stores the canvas element
     *
     * @private
     * @property canvas
     * @type Object
     */
    this.canvas = parameters.canvas,
    /**
     * Stores the Scene. This is interchangeable with any Scene during runtime
     *
     * @property scene
     * @type Scene
     * @default new LE.Scene()
     */
    this._scene = parameters.scene || new LE.Scene(),
    /**
     * Stores the Camera. This is interchangeable with any Camera during runtime
     *
     * @property camera
     * @type Camera
     * @default new LE.OrthographicCamera(0, 0)
     */
    this._camera = parameters.camera || new LE.OrthographicCamera(0, 0),
    /**
     * Stores the shaders
     *
     * @private
     * @property shaders
     * @type Shaders
     * @default new LE.Shaders()
     */
    this.shaders = new LE.Shaders();

    // Constructor
    this.initGL();
    this.initShaders();
    this.prepareGL();
};

LE.WebGLRenderer.prototype = {
    get scene() {
        return this._scene;
    },
    set scene(scene) {
        if(scene instanceof LE.Scene) {
            this._scene = scene;
            if(this.gl != null) {
                this._scene.init(this.gl);
            }
        } else {
            console.warn("Object is not of type LE.Scene!");
        }
    },
    get camera() {
        return this._camera;
    },

    set camera(camera) {
        if(camera instanceof LE.OrthographicCamera) {
            this._camera = camera;
            if(this.gl != null) {
                this._camera.ortho(-this.gl.viewportRatio, this.gl.viewportRatio, -1.0, 1.0, 0.1, 100.0);
                this._camera.translate(-this.gl.viewportRatio, -1.0, -1.0);
            }
        } else {
            console.warn("Object is not of type LE.OrthographicCamera!");
        }
    }
};

/**
 * Initialises the WebGL context
 *
 * @method initGL
 * @private
 */
LE.WebGLRenderer.prototype.initGL = function() {
    try {
        // Experimental webgl so it can run in internet explorer and edge
        this.gl = this.canvas.getContext("experimental-webgl", {stencil:true});
        this.gl.viewportWidth = canvas.width;
        this.gl.viewportHeight = canvas.height;
        this.gl.viewportRatio = canvas.width / canvas.height;

        if(this.scene != null) {
            this.scene.init(this.gl);
        }
    } catch(e) {
    }
    if (!this.gl) {
        alert("Could not initialise WebGL, sorry :-( ");
    }
};

/**
 * Initialises the shaders
 *
 * @method initShaders
 * @private
 */
LE.WebGLRenderer.prototype.initShaders = function() {
    // Shader Parts
    var pointLightfragmentShader = this.shaders.getShaderFromVar(this.gl, LE.ShaderLib.POINT_LIGHT_FRAG, "Frag");
    var pointLightfragmentShader2 = this.shaders.getShaderFromVar(this.gl, LE.ShaderLib.POINT_LIGHT_FRAG2, "Frag");
    var vertexShader = this.shaders.getShaderFromVar(this.gl, LE.ShaderLib.MAIN_VERT, "Vert");
    var radialPointLightfragmentShader = this.shaders.getShaderFromVar(this.gl, LE.ShaderLib.RADIAL_LIGHT_FRAG, "Frag");
    var colourFragmentShader = this.shaders.getShaderFromVar(this.gl, LE.ShaderLib.COLOUR_FRAG, "Frag");
    var textureFragmentShader = this.shaders.getShaderFromVar(this.gl, LE.ShaderLib.TEXTURE_FRAG, "Frag");
    var textureVertexShader = this.shaders.getShaderFromVar(this.gl, LE.ShaderLib.TEXTURE_VERT, "Vert");
    // Create Shader Programs
    this.shaders.list.push(new LE.Shader('PrimaryPointLightShader', this.shaders.createShader(this.gl, false, vertexShader, pointLightfragmentShader)));
    this.shaders.list.push(new LE.Shader('SecondaryPointLightShader', this.shaders.createShader(this.gl, false, vertexShader, pointLightfragmentShader2)));
    this.shaders.list.push(new LE.Shader('RadialPointLightShader', this.shaders.createShader(this.gl, false, vertexShader, radialPointLightfragmentShader)));
    this.shaders.list.push(new LE.Shader('PolygonShader', this.shaders.createShader(this.gl, false, vertexShader, colourFragmentShader)));
    this.shaders.list.push(new LE.Shader('TextureShader', this.shaders.createShader(this.gl, true, textureVertexShader, textureFragmentShader)));
    this.shaders.setCurrentShader(this.gl, this.shaders.list[0].program);
};

/**
 * Prepares WebGL for rendering
 *
 * @method prepareGL
 * @private
 */
LE.WebGLRenderer.prototype.prepareGL = function() {
    this.gl.clearColor(0.0, 0.0, 0.0, 1.0);
    this.gl.viewport(0, 0, this.gl.viewportWidth, this.gl.viewportHeight);
    this.camera.ortho(-this.gl.viewportRatio, this.gl.viewportRatio, -1.0, 1.0, 0.1, 100.0);
    this.camera.identity(this.camera.mvMatrix);
    this.camera.translate(-this.gl.viewportRatio, -1.0, -1.0);
    this.gl.enable(this.gl.DEPTH_TEST);
    // Makes drawing clockwise
    this.gl.frontFace(this.gl.CW);
    this.gl.enable(this.gl.STENCIL_TEST);
};

/**
 * Sets projection and model view matrix uniforms
 *
 * @method setMatrixUniforms
 * @param {Object} shaderProgram
 * @private
 */
LE.WebGLRenderer.prototype.setMatrixUniforms = function(shaderProgram) {
    this.gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, this.camera.pMatrix);
    this.gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, this.camera.mvMatrix);
};

/**
 * Sets the clear colour of the canvas
 *
 * @method setClearColour
 * @param {Number} r Red
 * @param {Number} g Green
 * @param {Number} b Blue
 * @param {Number} a Alpha
 */
LE.WebGLRenderer.prototype.setClearColour = function(r, g, b, a) {
    this.gl.clearColor(r / 255, g / 255, b / 255, a / 255);
};

/**
 * Clears the canvas element
 *
 * @method clear
 */
LE.WebGLRenderer.prototype.clear = function() {
    this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
};

/**
 * Wraps on top of the camera translation function
 *
 * @method translate
 * @param {Number} x
 * @param {Number} y
 * @param {Number} rotation
 * @private
 */
LE.WebGLRenderer.prototype.translate = function(x, y, rotation) {
    this.camera.translate(LE.Utilities.toMatrix(this.gl, x, true), LE.Utilities.toMatrix(this.gl, y, false), 0.0);
};

/**
 * Resizes the canvas element and the WebGL viewport
 *
 * @method resize
 * @param {Number} width Resize width
 * @param {Number} height Resize height
 */
LE.WebGLRenderer.prototype.resize = function(width, height) {
    if(width != canvas.width || height != canvas.height) {
        canvas.width = width;
        canvas.height = height;
        this.camera.translate(+this.gl.viewportRatio, +1.0 , +1.0)
        this.gl.viewportWidth = width;
        this.gl.viewportHeight = height;
        this.gl.viewportRatio = width / height;
        this.gl.viewport(0, 0, this.gl.viewportWidth, this.gl.viewportHeight);
        this.camera.ortho(-this.gl.viewportRatio, this.gl.viewportRatio, -1.0, 1.0, 0.1, 100.0);
        this.camera.translate(-this.gl.viewportRatio , -1.0 , -1.0);
        this.scene.initBuffers();
    }
};

/**
 * Renders the objects and lights in the scene to the canvas element
 *
 * @method render
 */
LE.WebGLRenderer.prototype.render = function() {
    this.renderObjects();
    this.renderShadowObjects();
    this.renderLightsAndShadows();
};

/**
 * Renders the objects in the scene to the canvas element. This should not be called if the render function is being called. 
 * This is simply here so each part of the scene can be rendered separately if needed
 *
 * @method renderObjects
 */
LE.WebGLRenderer.prototype.renderObjects = function() {
    this.translate(-this.camera.x, -this.camera.y);
    this.gl.bindTexture(this.gl.TEXTURE_2D, null);
    for(var o = 0; o < this.scene.objects.length; o++) {
        var size = LE.Utilities.sizeFromVerts(this.scene.objects[o].vertices);
        if(LE.Utilities.checkScreenBounds(this.camera.x, this.camera.y, this.gl.viewportWidth, this.gl.viewportHeight,
            size.width, size.height, this.scene.objects[o].x, this.scene.objects[o].y)) {
            if(this.scene.objects[o] instanceof LE.Texture) {
                this.renderTextureObject(this.scene.objects, o); 
            } else {
                this.renderObject(this.scene.objects, o); 
            }
        }
    }
    this.translate(this.camera.x, this.camera.y);
};

/**
 * Renders the shadow objects in the scene to the canvas element. This should not be called if the render function is being called. 
 * This is simply here so each part of the scene can be rendered separately if needed
 *
 * @method renderShadowObjects
 */
LE.WebGLRenderer.prototype.renderShadowObjects = function() {
    this.translate(-this.camera.x, -this.camera.y);
    this.gl.bindTexture(this.gl.TEXTURE_2D, null);
    for(var so = 0; so < this.scene.shadowObjects.length; so++) {
        var size = LE.Utilities.sizeFromVerts(this.scene.shadowObjects[so].vertices);
        if(LE.Utilities.checkScreenBounds(this.camera.x, this.camera.y, this.gl.viewportWidth, this.gl.viewportHeight,
            size.width, size.height, this.scene.shadowObjects[so].x, this.scene.shadowObjects[so].y)) {
            if(this.scene.shadowObjects[so] instanceof LE.Texture) {
                this.renderTextureObject(this.scene.shadowObjects, so); 
            } else {
                this.renderObject(this.scene.shadowObjects, so); 
            }
        }
    }
    this.translate(this.camera.x, this.camera.y);
};
  
/**
 * Renders the lights and shadows in the scene to the canvas element. This should not be called if the render function is being called. 
 * This is simply here so each part of the scene can be rendered separately if needed
 *
 * @method renderLightsAndShadows
 */  
LE.WebGLRenderer.prototype.renderLightsAndShadows = function() {
    this.translate(-this.camera.x, -this.camera.y);
    this.gl.bindTexture(this.gl.TEXTURE_2D, null);
    if(this.pointLightShaderSelected == true) {
        this.shaders.setCurrentShader(this.gl, this.shaders.list[0].program);
    } else {
        this.shaders.setCurrentShader(this.gl, this.shaders.list[1].program);
    }
    this.gl.enable(this.gl.STENCIL_TEST);
    this.gl.depthMask(false);
    for(var l = 0; l < this.scene.lights.length; l++) {  
        var theVertices = [];       
        this.gl.stencilOp(this.gl.KEEP, this.gl.KEEP, this.gl.REPLACE);
        this.gl.stencilFunc(this.gl.ALWAYS, 1, 1);
        this.gl.colorMask(false, false, false, false);
        var foreStart = 0;
        if(this.scene.lights[l].polygonIndex != null) {
            foreStart = this.scene.lights[l].polygonIndex;
        }
        if(LE.Utilities.checkScreenBounds(this.camera.x, this.camera.y, this.gl.viewportWidth, this.gl.viewportHeight, 500, 500, this.scene.lights[l].x, this.scene.lights[l].y)) {
            for(var so = foreStart; so < this.scene.shadowObjects.length; so++) {
                if(so > foreStart && this.scene.lights[l].polygonIndex != null) {
                    break;
                }
                var r1, r2, bb, cc, d;
                if(this.scene.lights[l].type === LE.Lights.RADIAL_POINT_LIGHT) {
                    var size = LE.Utilities.sizeFromVerts(this.scene.shadowObjects[so].vertices);
                    r1 = this.scene.lights[l].radius + size.width + size.height;
                    r2 = 1;
                    bb = (this.scene.lights[l].x) - (this.scene.shadowObjects[so].x + size.width / 2);
                    bb = bb * bb;
                    cc = (this.scene.lights[l].y) - (this.scene.shadowObjects[so].y + size.height / 2);
                    cc = cc * cc;
                    d = Math.sqrt(bb + cc);
                } else {
                    r1 = 1;
                    r2 = 1;
                    d = 1;
                }

                if(r1 + r2 > d) {
                    // This could be a performance hit but means the engine doesnt need to check for changed positions
                    // and rotations.
                    var vertices = [];
                    for(var i = 0; i < this.scene.shadowObjects[so].vertices.length; i++) {
                        vertices.push({x: this.scene.shadowObjects[so].vertices[i].x + this.scene.shadowObjects[so].x,
                                       y: this.scene.shadowObjects[so].vertices[i].y + this.scene.shadowObjects[so].y});
                    }
                    // Performance hit end
                    for(var v = 0; v < vertices.length; v++) {
                        var currentVertex = vertices[v];
                        var nextVertex = vertices[(v + 1) % vertices.length]; 
                        var edge = LE.Vector2.sub(nextVertex, currentVertex);
                        var normal = {
                            // Inverting these can allow/stop block blending
                            x: edge.y,
                            y: -edge.x
                        }
                        var lightLocation = {x: this.scene.lights[l].x, y: this.scene.lights[l].y};
                        var lightToCurrent = LE.Vector2.sub(currentVertex, lightLocation);
                        if(LE.Vector2.dot(normal, lightToCurrent) > 0) {
                            var point1 = LE.Vector2.add(currentVertex, LE.Vector2.scale(500, LE.Vector2.sub(currentVertex, lightLocation)));
                            var point2 = LE.Vector2.add(nextVertex, LE.Vector2.scale(500, LE.Vector2.sub(nextVertex, lightLocation)));
                            // Manual vertToMatrix conversion. Because this is called thousands of times a function call slows it down.
                            theVertices.push(
                                // Triangle 1
                                point1.x / this.gl.viewportWidth * this.gl.viewportRatio * 2, point1.y / this.gl.viewportHeight * 2,  0.0,
                                currentVertex.x / this.gl.viewportWidth * this.gl.viewportRatio * 2, currentVertex.y / this.gl.viewportHeight * 2, 0.0,
                                point2.x / this.gl.viewportWidth * this.gl.viewportRatio * 2, point2.y / this.gl.viewportHeight * 2,  0.0,
                                // Triangle 2
                                currentVertex.x / this.gl.viewportWidth * this.gl.viewportRatio * 2, currentVertex.y / this.gl.viewportHeight * 2, 0.0,
                                point2.x / this.gl.viewportWidth * this.gl.viewportRatio * 2, point2.y / this.gl.viewportHeight * 2,  0.0,
                                nextVertex.x / this.gl.viewportWidth * this.gl.viewportRatio * 2, nextVertex.y / this.gl.viewportHeight * 2,  0.0   );
                        }
                    } 
                }
            }

            this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.scene.shadowBuffers[0]);

            this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(theVertices), this.gl.DYNAMIC_DRAW);
            this.scene.shadowBuffers[0].itemSize = 3;
            this.scene.shadowBuffers[0].numItems = theVertices.length / 3;
            this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.scene.shadowBuffers[0]);
            this.gl.vertexAttribPointer(this.shaders.selected.vertexPositionAttribute, this.scene.shadowBuffers[0].itemSize, this.gl.FLOAT, false, 0, 0);
            this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.scene.shadowColourBuffers[0]);
            this.gl.vertexAttribPointer(this.shaders.selected.vertexColorAttribute, this.scene.shadowColourBuffers[0].itemSize, this.gl.FLOAT, false, 0, 0);
            this.setMatrixUniforms(this.shaders.selected); 
            this.gl.drawArrays(this.gl.TRIANGLES, 0, this.scene.shadowBuffers[0].numItems);
        }
        // Lights get rendered here
        this.gl.colorMask(true, true, true, true);
        if(LE.Utilities.checkScreenBounds(this.camera.x, this.camera.y, this.gl.viewportWidth, this.gl.viewportHeight, 500, 500, this.scene.lights[l].x, this.scene.lights[l].y)) {

            this.gl.stencilOp(this.gl.KEEP, this.gl.KEEP, this.gl.KEEP);
            this.gl.stencilFunc(this.gl.EQUAL, 0, 1);

            this.shaders.setCurrentShader(this.gl, this.shaders.list[this.scene.lights[l].shader].program);

            this.gl.enable(this.gl.BLEND);
            this.gl.blendFunc(this.gl.ONE, this.gl.ONE); 
            this.gl.uniform2f(this.gl.getUniformLocation(this.shaders.selected, "lightLocation"), this.scene.lights[l].x - this.camera.x, this.scene.lights[l].y - this.camera.y);
            this.gl.uniform3f(this.gl.getUniformLocation(this.shaders.selected, "lightColor"), this.scene.lights[l].colour.r * this.scene.lights[l].intensity, this.scene.lights[l].colour.g * this.scene.lights[l].intensity, this.scene.lights[l].colour.b * this.scene.lights[l].intensity);
            if(this.scene.lights[l].radius != null) {
                this.gl.uniform1f(this.gl.getUniformLocation(this.shaders.selected, "radius"), this.scene.lights[l].radius);
            }

            this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.scene.lightBuffers[this.scene.lights[l].bufferIndex]);      
            this.gl.vertexAttribPointer(this.shaders.selected.vertexColorAttribute, 3, this.gl.FLOAT, false, 0, 0);
            this.gl.vertexAttribPointer(this.shaders.selected.vertexPositionAttribute, this.scene.lightBuffers[this.scene.lights[l].bufferIndex].itemSize, this.gl.FLOAT, false, 0, 0);
            var matrixPos = LE.Utilities.vertToMatrix(this.gl, this.scene.lights[l].x, this.scene.lights[l].y);
            //mat4.translate(this.mvMatrix, this.mvMatrix, [matrixPos.x, matrixPos.y, 0.0]);
            this.camera.translate(matrixPos.x, matrixPos.y, 0.0);
            this.camera.mvPushMatrix();
            if(this.scene.lights[l].rotation != null) {
                this.camera.rotate(LE.Utilities.degToRad(this.scene.lights[l].rotation), 0, 0, 1);
                //mat4.rotate(this.mvMatrix, this.mvMatrix, LE.Utilities.degToRad(this.scene.lights[l].rotation), [0, 0, 1]); 
            }
            this.setMatrixUniforms(this.shaders.selected);
            this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, this.scene.lightBuffers[this.scene.lights[l].bufferIndex].numItems);
            this.camera.mvPopMatrix();
            this.camera.translate(-matrixPos.x, -matrixPos.y, 0.0);
            //mat4.translate(this.mvMatrix, this.mvMatrix, [-matrixPos.x, -matrixPos.y, 0.0]);
            this.gl.disable(this.gl.BLEND);
            this.gl.clear(this.gl.STENCIL_BUFFER_BIT); 
        }
    }
    this.translate(this.camera.x, this.camera.y);
};

/**
 * Renders a single texture object
 *
 * @method renderTextureObject
 * @param {Array} array
 * @param {Number} i Index in the given array
 * @private
 */
LE.WebGLRenderer.prototype.renderTextureObject = function(array, i) {
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.scene.objectBuffers[array[i].bufferIndex]);
    this.gl.vertexAttribPointer(this.shaders.selected.vertexPositionAttribute, this.scene.objectBuffers[array[i].bufferIndex].itemSize, this.gl.FLOAT, false, 0, 0);

    // Support transparent textures
    this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
    this.gl.enable(this.gl.BLEND);
    this.shaders.setCurrentShader(this.gl, this.shaders.list[4].program);
    // Need to handle ambient light code
    this.gl.uniform4f(this.gl.getUniformLocation(this.shaders.selected, "ambientLight"), this.scene.ambientLight.colour.r / 255, this.scene.ambientLight.colour.g / 255, this.scene.ambientLight.colour.b / 255, this.scene.ambientLight.colour.a / 255);
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.scene.objectTextureBuffers[array[i].bufferIndex]);
    this.gl.vertexAttribPointer(this.shaders.selected.textureCoordAttribute, this.scene.objectTextureBuffers[array[i].bufferIndex].itemSize, this.gl.FLOAT, false, 0, 0);
    this.gl.activeTexture(this.gl.TEXTURE0);
    this.gl.bindTexture(this.gl.TEXTURE_2D, this.scene.textures[array[i].textureIndex]);
    this.gl.uniform1i(this.shaders.selected.samplerUniform, 0); 
    var matrixPos = LE.Utilities.vertToMatrix(this.gl, array[i].x, array[i].y);
    var cp = LE.Utilities.vertToMatrix(this.gl, array[i].centerPoint.x, array[i].centerPoint.y);
    this.camera.translate(matrixPos.x, matrixPos.y, 0.0);
    this.camera.mvPushMatrix();
    // Move matrix to center of shape
    this.camera.translate(cp.x, cp.y, 0.0);
    this.camera.rotate(LE.Utilities.degToRad(array[i].rotation), 0, 0, 1);
    this.camera.translate(-cp.x, -cp.y, 0.0);
    this.setMatrixUniforms(this.shaders.selected); 

    this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, this.scene.objectBuffers[array[i].bufferIndex].numItems);
    this.camera.mvPopMatrix();
    this.camera.translate(-matrixPos.x, -matrixPos.y, 0.0);
    this.gl.disable(this.gl.BLEND);
}

/**
 * Renders a single object
 *
 * @method renderObject
 * @param {Array} array
 * @param {Number} i Index in the given array
 * @private
 */
LE.WebGLRenderer.prototype.renderObject = function(array, i) {
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.scene.objectBuffers[array[i].bufferIndex]);
    this.gl.vertexAttribPointer(this.shaders.selected.vertexPositionAttribute, this.scene.objectBuffers[array[i].bufferIndex].itemSize, this.gl.FLOAT, false, 0, 0);

    this.shaders.setCurrentShader(this.gl, this.shaders.list[3].program);
    // Need to handle ambient light code
    this.gl.uniform4f(this.gl.getUniformLocation(this.shaders.selected, "ambientLight"), this.scene.ambientLight.colour.r / 250, this.scene.ambientLight.colour.g / 255, this.scene.ambientLight.colour.b / 255, this.scene.ambientLight.colour.a / 255);
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.scene.objectColourBuffers[array[i].bufferIndex]);
    this.gl.vertexAttribPointer(this.shaders.selected.vertexColorAttribute, this.scene.objectColourBuffers[array[i].bufferIndex].itemSize, this.gl.FLOAT, false, 0, 0);
    var matrixPos = LE.Utilities.vertToMatrix(this.gl, array[i].x, array[i].y);
    var cp = LE.Utilities.vertToMatrix(this.gl, array[i].centerPoint.x, array[i].centerPoint.y);
    this.camera.translate(matrixPos.x, matrixPos.y, 0.0);
    this.camera.mvPushMatrix();
    // Move matrix to center of shape
    this.camera.translate(cp.x, cp.y, 0.0);
    this.camera.rotate(LE.Utilities.degToRad(array[i].rotation), 0, 0, 1);
    this.camera.translate(-cp.x, -cp.y, 0.0);

    this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.scene.objectIndexBuffers[array[i].bufferIndex]);
    this.setMatrixUniforms(this.shaders.selected);  
    this.gl.drawElements(this.gl.TRIANGLES, this.scene.objectIndexBuffers[array[i].bufferIndex].numItems, this.gl.UNSIGNED_SHORT, 0);

    this.camera.mvPopMatrix();
    this.camera.translate(-matrixPos.x, -matrixPos.y, 0.0);
    this.gl.disable(this.gl.BLEND);
};