text: (function(dependencies, chunks, undefined, global) {
      
      var cache = [],
          cacheCallbacks = {};
      
  
      function Module() {
          this.id = null;
          this.filename = null;
          this.dirname = null;
          this.exports = {};
          this.loaded = false;
      }
  
      Module.prototype.require = require;
  
      function require(index) {
          var module = cache[index],
              callback, exports;
  
          if (module !== undefined) {
              return module.exports;
          } else {
              callback = dependencies[index];
  
              cache[index] = module = new Module();
              exports = module.exports;
  
              callback.call(exports, require, exports, module, undefined, global);
              module.loaded = true;
  
              return module.exports;
          }
      }
  
      require.resolve = function(path) {
          return path;
      };
  
      
      require.async = function async(index, callback) {
          var module = cache[index],
              callbacks, node;
  
          if (module) {
              callback(module.exports);
          } else if ((callbacks = cacheCallbacks[index])) {
              callbacks[callbacks.length] = callback;
          } else {
              node = document.createElement("script");
              callbacks = cacheCallbacks[index] = [callback];
  
              node.type = "text/javascript";
              node.charset = "utf-8";
              node.async = true;
  
              function onLoad() {
                  var i = -1,
                      il = callbacks.length - 1;
  
                  while (i++ < il) {
                      callbacks[i](require(index));
                  }
                  delete cacheCallbacks[index];
              }
  
              if (node.attachEvent && !(node.attachEvent.toString && node.attachEvent.toString().indexOf("[native code") < 0)) {
                  node.attachEvent("onreadystatechange", onLoad);
              } else {
                  node.addEventListener("load", onLoad, false);
              }
  
              node.src = chunks[index];
  
              document.head.appendChild(node);
          }
      };
  
      global["dsZ16ecA-6hog-4Kwj-axUV-7taLnmRJ8Pa0R"] = function(asyncDependencies) {
          var i = -1,
              il = asyncDependencies.length - 1,
              dependency, index;
  
          while (i++ < il) {
              dependency = asyncDependencies[i];
              index = dependency[0];
  
              if (dependencies[index] === null) {
                  dependencies[index] = dependency[1];
              }
          }
      };
  
      
  
      if (typeof(define) === "function" && define.amd) {
          define([], function() {
              return require(0);
          });
      } else if (typeof(module) !== "undefined" && module.exports) {
          module.exports = require(0);
      } else {
          
          require(0);
          
      }
  }([
  function(require, exports, module, undefined, global) {
  /*@=-/var/www/html/node/_engine/js-webgl_context/example/index.js-=@*/
  var mat4 = require(1),
      requestAnimationFrame = require(2),
      WebGLContext = require(3)
      filterMode = require(4);
  
  
  var canvas = document.getElementById("canvas"),
      context = new WebGLContext(),
      gl;
  
  global.WebGLContext = WebGLContext;
  
  function loadImage(src, callback) {
      var image = new Image(),
          texture = {
              __id: src,
              generateMipmap: false,
              filter: filterMode.NONE,
              anisotropy: 0,
              data: image,
              on: function() {}
          };
  
      image.onload = function() {
          texture.width = image.width;
          texture.height = image.height;
          callback();
      };
  
      image.src = src;
  
      return texture;
  }
  
  var count = 2;
  
  function check() {
      if (--count === 0) {
          render(0);
      }
  }
  var textureA = loadImage("a.jpg", check);
  var textureB = loadImage("b.jpg", check);
  
  var framebuffer = {
      on: function() {},
      depthBuffer: false,
      stencilBuffer: false,
      texture: {
          __id: "framebuffer-texture",
          data: null,
          generateMipmap: false,
          filter: filterMode.NONE,
          anisotropy: 0,
          width: canvas.width * 0.1,
          height: canvas.height * 0.1,
          on: function() {}
      }
  };
  
  global.context = context;
  context.setAttributes({
      antialias: false
  });
  context.setCanvas(canvas);
  gl = context.gl;
  context.setViewport(0, 0, canvas.width, canvas.height);
  
  var programA = context.createProgram();
  programA.compile(
      [
          "uniform mat4 projection;",
          "uniform mat4 modelView;",
  
          "uniform vec2 offset;",
  
          "attribute vec3 position;",
          "attribute vec2 uv;",
  
          "varying vec2 vUv;",
  
          "void main(void) {",
          "    vUv = offset + uv;",
          "    gl_Position = projection * modelView * vec4(position, 1.0);",
          "}"
      ].join("\n"), [
          "uniform sampler2D texture;",
  
          "varying vec2 vUv;",
  
          "void main(void) {",
          "    gl_FragColor = texture2D(texture, vec2(vUv.s, vUv.t));",
          "}"
      ].join("\n")
  );
  
  var programB = context.createProgram();
  programB.compile(
      [
          "uniform mat4 projection;",
          "uniform mat4 modelView;",
  
          "attribute vec3 position;",
          "attribute vec2 uv;",
  
          "varying vec2 vUv;",
  
          "void main(void) {",
          "    vUv = uv;",
          "    gl_Position = projection * modelView * vec4(position, 1.0);",
          "}"
      ].join("\n"), [
          "uniform sampler2D texture;",
          "uniform sampler2D texture1;",
  
          "varying vec2 vUv;",
  
          "void main(void) {",
          "    gl_FragColor = texture2D(texture, vec2(vUv.s, vUv.t)) * texture2D(texture1, vec2(vUv.s, vUv.t));",
          "}"
      ].join("\n")
  );
  
  var programFrameBuffer = context.createProgram();
  programFrameBuffer.compile(
      [
          "attribute vec3 position;",
          "attribute vec2 uv;",
  
          "varying vec2 vUv;",
  
          "void main(void) {",
          "    vUv = uv;",
          "    gl_Position = vec4(position, 1.0);",
          "}"
      ].join("\n"), [
          "uniform sampler2D texture;",
  
          "varying vec2 vUv;",
  
          "void main(void) {",
          "    gl_FragColor = texture2D(texture, vec2(vUv.s, vUv.t));",
          "}"
      ].join("\n")
  );
  
  var buffer = context.createBuffer();
  buffer.compile(gl.ARRAY_BUFFER, new Float32Array([
      1, 1, 0, 0, 0, -1, 1, 0, 1, 0,
      1, -1, 0, 0, 1, -1, -1, 0, 1, 1
  ]), 20, gl.STATIC_DRAW);
  
  var triangleBuffer = context.createBuffer();
  triangleBuffer.compile(gl.ARRAY_BUFFER, new Float32Array([
      0, 1, 0, 0.5, 1.5, -1, -1, 0, -0.5, 0,
      1, -1, 0, 1.5, 0
  ]), 20, gl.STATIC_DRAW);
  
  var perspectiveMatrix = mat4.perspective(mat4.create(), 45, canvas.width / canvas.height, 0.1, 1024),
      modelView = mat4.create(),
      camera = [0, 0, -5],
      offset = [0, 0];
  
  function renderBox(ms) {
      camera[0] = Math.sin(ms * 0.001) * 2;
      camera[1] = 0;
  
      offset[0] = Math.sin(ms * 0.001) * 0.5;
      offset[1] = Math.cos(ms * 0.001) * 0.5;
  
      context.setProgram(programA);
  
      mat4.setPosition(modelView, camera);
  
      programA.attributes.get("position").set(buffer, 0);
      programA.attributes.get("uv").set(buffer, 12);
  
      programA.uniforms.get("offset").set(offset);
      programA.uniforms.get("projection").set(perspectiveMatrix);
      programA.uniforms.get("modelView").set(modelView);
      programA.uniforms.get("texture").set(textureA);
  
      gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
  }
  
  function renderTriangle(ms) {
      camera[0] = 0;
      camera[1] = Math.sin(ms * 0.001) * 2;
  
      context.setProgram(programB);
  
      mat4.setPosition(modelView, camera);
  
      programB.attributes.get("position").set(triangleBuffer, 0);
      programB.attributes.get("uv").set(triangleBuffer, 12);
  
      programB.uniforms.get("projection").set(perspectiveMatrix);
      programB.uniforms.get("modelView").set(modelView);
      programB.uniforms.get("texture").set(textureB);
      programB.uniforms.get("texture1").set(textureA);
  
      gl.drawArrays(gl.TRIANGLE_STRIP, 0, 3);
  }
  
  var color = [0, 0, 0];
  
  function render(ms) {
  
      color[0] = Math.sin(ms * 0.00001);
      color[1] = Math.cos(ms * 0.0001);
      color[2] = Math.sin(ms * 0.001);
  
      context.setFrameBuffer(framebuffer);
  
      context.setClearColor(color);
      context.clearCanvas();
  
      renderBox(ms);
      renderTriangle(ms);
  
      context.clearFrameBuffer();
  
      context.setProgram(programFrameBuffer);
      programFrameBuffer.attributes.get("position").set(buffer, 0);
      programFrameBuffer.attributes.get("uv").set(buffer, 12);
      programFrameBuffer.uniforms.get("texture").set(framebuffer.texture);
      gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
  
      requestAnimationFrame(render, canvas);
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/mat4@0.0.5/src/index.js-=@*/
  var mathf = require(5),
      vec3 = require(6),
      isNumber = require(7);
  
  
  var mat4 = exports;
  
  
  mat4.ArrayType = typeof(Float32Array) !== "undefined" ? Float32Array : mathf.ArrayType;
  
  
  mat4.create = function(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44) {
      var out = new mat4.ArrayType(16);
  
      out[0] = isNumber(m11) ? m11 : 1;
      out[4] = isNumber(m12) ? m12 : 0;
      out[8] = isNumber(m13) ? m13 : 0;
      out[12] = isNumber(m14) ? m14 : 0;
      out[1] = isNumber(m21) ? m21 : 0;
      out[5] = isNumber(m22) ? m22 : 1;
      out[9] = isNumber(m23) ? m23 : 0;
      out[13] = isNumber(m24) ? m24 : 0;
      out[2] = isNumber(m31) ? m31 : 0;
      out[6] = isNumber(m32) ? m32 : 0;
      out[10] = isNumber(m33) ? m33 : 1;
      out[14] = isNumber(m34) ? m34 : 0;
      out[3] = isNumber(m41) ? m41 : 0;
      out[7] = isNumber(m42) ? m42 : 0;
      out[11] = isNumber(m43) ? m43 : 0;
      out[15] = isNumber(m44) ? m44 : 1;
  
      return out;
  };
  
  mat4.copy = function(out, a) {
  
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
      out[4] = a[4];
      out[5] = a[5];
      out[6] = a[6];
      out[7] = a[7];
      out[8] = a[8];
      out[9] = a[9];
      out[10] = a[10];
      out[11] = a[11];
      out[12] = a[12];
      out[13] = a[13];
      out[14] = a[14];
      out[15] = a[15];
  
      return out;
  };
  
  mat4.clone = function(a) {
      var out = new mat4.ArrayType(16);
  
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
      out[4] = a[4];
      out[5] = a[5];
      out[6] = a[6];
      out[7] = a[7];
      out[8] = a[8];
      out[9] = a[9];
      out[10] = a[10];
      out[11] = a[11];
      out[12] = a[12];
      out[13] = a[13];
      out[14] = a[14];
      out[15] = a[15];
  
      return out;
  };
  
  mat4.set = function(out, m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44) {
  
      out[0] = isNumber(m11) ? m11 : 1;
      out[4] = isNumber(m12) ? m12 : 0;
      out[8] = isNumber(m13) ? m13 : 0;
      out[12] = isNumber(m14) ? m14 : 0;
      out[1] = isNumber(m21) ? m21 : 0;
      out[5] = isNumber(m22) ? m22 : 1;
      out[9] = isNumber(m23) ? m23 : 0;
      out[13] = isNumber(m24) ? m24 : 0;
      out[2] = isNumber(m31) ? m31 : 0;
      out[6] = isNumber(m32) ? m32 : 0;
      out[10] = isNumber(m33) ? m33 : 1;
      out[14] = isNumber(m34) ? m34 : 0;
      out[3] = isNumber(m41) ? m41 : 0;
      out[7] = isNumber(m42) ? m42 : 0;
      out[11] = isNumber(m43) ? m43 : 0;
      out[15] = isNumber(m44) ? m44 : 1;
  
      return out;
  };
  
  mat4.identity = function(out) {
  
      out[0] = 1;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 0;
      out[5] = 1;
      out[6] = 0;
      out[7] = 0;
      out[8] = 0;
      out[9] = 0;
      out[10] = 1;
      out[11] = 0;
      out[12] = 0;
      out[13] = 0;
      out[14] = 0;
      out[15] = 1;
  
      return out;
  };
  
  mat4.zero = function(out) {
  
      out[0] = 0;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 0;
      out[5] = 0;
      out[6] = 0;
      out[7] = 0;
      out[8] = 0;
      out[9] = 0;
      out[10] = 0;
      out[11] = 0;
      out[12] = 0;
      out[13] = 0;
      out[14] = 0;
      out[15] = 0;
  
      return out;
  };
  
  mat4.mul = function(out, a, b) {
      var a00 = a[0],
          a01 = a[1],
          a02 = a[2],
          a03 = a[3],
          a10 = a[4],
          a11 = a[5],
          a12 = a[6],
          a13 = a[7],
          a20 = a[8],
          a21 = a[9],
          a22 = a[10],
          a23 = a[11],
          a30 = a[12],
          a31 = a[13],
          a32 = a[14],
          a33 = a[15],
          b0, b1, b2, b3;
  
      b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
      out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
      out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
      out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
      out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  
      b0 = b[4];
      b1 = b[5];
      b2 = b[6];
      b3 = b[7];
      out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
      out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
      out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
      out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  
      b0 = b[8];
      b1 = b[9];
      b2 = b[10];
      b3 = b[11];
      out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
      out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
      out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
      out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  
      b0 = b[12];
      b1 = b[13];
      b2 = b[14];
      b3 = b[15];
      out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
      out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
      out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
      out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  
      return out;
  };
  
  mat4.smul = function(out, a, s) {
  
      out[0] = a[0] * s;
      out[1] = a[1] * s;
      out[2] = a[2] * s;
      out[3] = a[3] * s;
      out[4] = a[4] * s;
      out[5] = a[5] * s;
      out[6] = a[6] * s;
      out[7] = a[7] * s;
      out[8] = a[8] * s;
      out[9] = a[9] * s;
      out[10] = a[10] * s;
      out[11] = a[11] * s;
      out[12] = a[12] * s;
      out[13] = a[13] * s;
      out[14] = a[14] * s;
      out[15] = a[15] * s;
  
      return out;
  };
  
  mat4.sdiv = function(out, a, s) {
      s = s !== 0 ? 1 / s : s;
  
      out[0] = a[0] * s;
      out[1] = a[1] * s;
      out[2] = a[2] * s;
      out[3] = a[3] * s;
      out[4] = a[4] * s;
      out[5] = a[5] * s;
      out[6] = a[6] * s;
      out[7] = a[7] * s;
      out[8] = a[8] * s;
      out[9] = a[9] * s;
      out[10] = a[10] * s;
      out[11] = a[11] * s;
      out[12] = a[12] * s;
      out[13] = a[13] * s;
      out[14] = a[14] * s;
      out[15] = a[15] * s;
  
      return out;
  };
  
  mat4.determinant = function(a) {
      var a00 = a[0],
          a01 = a[1],
          a02 = a[2],
          a03 = a[3],
          a10 = a[4],
          a11 = a[5],
          a12 = a[6],
          a13 = a[7],
          a20 = a[8],
          a21 = a[9],
          a22 = a[10],
          a23 = a[11],
          a30 = a[12],
          a31 = a[13],
          a32 = a[14],
          a33 = a[15],
  
          b00 = a00 * a11 - a01 * a10,
          b01 = a00 * a12 - a02 * a10,
          b02 = a00 * a13 - a03 * a10,
          b03 = a01 * a12 - a02 * a11,
          b04 = a01 * a13 - a03 * a11,
          b05 = a02 * a13 - a03 * a12,
          b06 = a20 * a31 - a21 * a30,
          b07 = a20 * a32 - a22 * a30,
          b08 = a20 * a33 - a23 * a30,
          b09 = a21 * a32 - a22 * a31,
          b10 = a21 * a33 - a23 * a31,
          b11 = a22 * a33 - a23 * a32;
  
      return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
  };
  
  mat4.inverse = function(out, a) {
      var a00 = a[0],
          a01 = a[1],
          a02 = a[2],
          a03 = a[3],
          a10 = a[4],
          a11 = a[5],
          a12 = a[6],
          a13 = a[7],
          a20 = a[8],
          a21 = a[9],
          a22 = a[10],
          a23 = a[11],
          a30 = a[12],
          a31 = a[13],
          a32 = a[14],
          a33 = a[15],
  
          b00 = a00 * a11 - a01 * a10,
          b01 = a00 * a12 - a02 * a10,
          b02 = a00 * a13 - a03 * a10,
          b03 = a01 * a12 - a02 * a11,
          b04 = a01 * a13 - a03 * a11,
          b05 = a02 * a13 - a03 * a12,
          b06 = a20 * a31 - a21 * a30,
          b07 = a20 * a32 - a22 * a30,
          b08 = a20 * a33 - a23 * a30,
          b09 = a21 * a32 - a22 * a31,
          b10 = a21 * a33 - a23 * a31,
          b11 = a22 * a33 - a23 * a32,
  
          det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
  
      if (!det) {
          return mat4.identity(out);
      } else {
          det = 1.0 / det;
  
          out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
          out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
          out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
          out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
          out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
          out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
          out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
          out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
          out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
          out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
          out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
          out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
          out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
          out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
          out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
          out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
  
          return out;
      }
  };
  
  mat4.transpose = function(out, a) {
      var a01, a02, a03, a12, a13, a23;
  
      if (out === a) {
          a01 = a[1];
          a02 = a[2];
          a03 = a[3];
          a12 = a[6];
          a13 = a[7];
          a23 = a[11];
  
          out[1] = a[4];
          out[2] = a[8];
          out[3] = a[12];
          out[4] = a01;
          out[6] = a[9];
          out[7] = a[13];
          out[8] = a02;
          out[9] = a12;
          out[11] = a[14];
          out[12] = a03;
          out[13] = a13;
          out[14] = a23;
      } else {
          out[0] = a[0];
          out[1] = a[4];
          out[2] = a[8];
          out[3] = a[12];
          out[4] = a[1];
          out[5] = a[5];
          out[6] = a[9];
          out[7] = a[13];
          out[8] = a[2];
          out[9] = a[6];
          out[10] = a[10];
          out[11] = a[14];
          out[12] = a[3];
          out[13] = a[7];
          out[14] = a[11];
          out[15] = a[15];
      }
  
      return out;
  };
  
  mat4.lookAt = function(out, eye, target, up) {
      var x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
          eyex = eye[0],
          eyey = eye[1],
          eyez = eye[2],
          upx = up[0],
          upy = up[1],
          upz = up[2],
          targetx = target[0],
          targety = target[1],
          targetz = target[2];
  
      if (mathf.abs(eyex - targetx) < mathf.EPSILON &&
          mathf.abs(eyey - targety) < mathf.EPSILON &&
          mathf.abs(eyez - targetz) < mathf.EPSILON
      ) {
          return mat4.identity(out);
      } else {
          z0 = eyex - targetx;
          z1 = eyey - targety;
          z2 = eyez - targetz;
  
          len = 1 / mathf.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
          z0 *= len;
          z1 *= len;
          z2 *= len;
  
          x0 = upy * z2 - upz * z1;
          x1 = upz * z0 - upx * z2;
          x2 = upx * z1 - upy * z0;
          len = mathf.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
          if (!len) {
              x0 = 0;
              x1 = 0;
              x2 = 0;
          } else {
              len = 1 / len;
              x0 *= len;
              x1 *= len;
              x2 *= len;
          }
  
          y0 = z1 * x2 - z2 * x1;
          y1 = z2 * x0 - z0 * x2;
          y2 = z0 * x1 - z1 * x0;
  
          len = mathf.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
          if (!len) {
              y0 = 0;
              y1 = 0;
              y2 = 0;
          } else {
              len = 1 / len;
              y0 *= len;
              y1 *= len;
              y2 *= len;
          }
  
          out[0] = x0;
          out[1] = x1;
          out[2] = x2;
          out[3] = 0;
          out[4] = y0;
          out[5] = y1;
          out[6] = y2;
          out[7] = 0;
          out[8] = z0;
          out[9] = z1;
          out[10] = z2;
          out[11] = 0;
          out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
          out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
          out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
          out[15] = 1;
  
          return out;
      }
  };
  
  mat4.compose = function(out, position, scale, rotation) {
      var x = rotation[0],
          y = rotation[1],
          z = rotation[2],
          w = rotation[3],
          x2 = x + x,
          y2 = y + y,
          z2 = z + z,
          xx = x * x2,
          xy = x * y2,
          xz = x * z2,
          yy = y * y2,
          yz = y * z2,
          zz = z * z2,
          wx = w * x2,
          wy = w * y2,
          wz = w * z2,
  
          sx = scale[0],
          sy = scale[1],
          sz = scale[2];
  
      out[0] = (1 - (yy + zz)) * sx;
      out[4] = (xy - wz) * sy;
      out[8] = (xz + wy) * sz;
  
      out[1] = (xy + wz) * sx;
      out[5] = (1 - (xx + zz)) * sy;
      out[9] = (yz - wx) * sz;
  
      out[2] = (xz - wy) * sx;
      out[6] = (yz + wx) * sy;
      out[10] = (1 - (xx + yy)) * sz;
  
      out[3] = 0;
      out[7] = 0;
      out[11] = 0;
  
      out[12] = position[0];
      out[13] = position[1];
      out[14] = position[2];
      out[15] = 1;
  
      return out;
  };
  
  mat4.decompose = function(out, position, scale, rotation) {
      var m11 = out[0],
          m12 = out[4],
          m13 = out[8],
          m21 = out[1],
          m22 = out[5],
          m23 = out[9],
          m31 = out[2],
          m32 = out[6],
          m33 = out[10],
          x = 0,
          y = 0,
          z = 0,
          w = 1,
  
          sx = vec3.lengthValues(m11, m21, m31),
          sy = vec3.lengthValues(m12, m22, m32),
          sz = vec3.lengthValues(m13, m23, m33),
  
          invSx = 1 / sx,
          invSy = 1 / sy,
          invSz = 1 / sz,
  
          s, trace;
  
      scale[0] = sx;
      scale[1] = sy;
      scale[2] = sz;
  
      position[0] = out[12];
      position[1] = out[13];
      position[2] = out[14];
  
      m11 *= invSx;
      m12 *= invSy;
      m13 *= invSz;
      m21 *= invSx;
      m22 *= invSy;
      m23 *= invSz;
      m31 *= invSx;
      m32 *= invSy;
      m33 *= invSz;
  
      trace = m11 + m22 + m33;
  
      if (trace > 0) {
          s = 0.5 / mathf.sqrt(trace + 1);
  
          w = 0.25 / s;
          x = (m32 - m23) * s;
          y = (m13 - m31) * s;
          z = (m21 - m12) * s;
      } else if (m11 > m22 && m11 > m33) {
          s = 2 * mathf.sqrt(1 + m11 - m22 - m33);
  
          w = (m32 - m23) / s;
          x = 0.25 * s;
          y = (m12 + m21) / s;
          z = (m13 + m31) / s;
      } else if (m22 > m33) {
          s = 2 * mathf.sqrt(1 + m22 - m11 - m33);
  
          w = (m13 - m31) / s;
          x = (m12 + m21) / s;
          y = 0.25 * s;
          z = (m23 + m32) / s;
      } else {
          s = 2 * mathf.sqrt(1 + m33 - m11 - m22);
  
          w = (m21 - m12) / s;
          x = (m13 + m31) / s;
          y = (m23 + m32) / s;
          z = 0.25 * s;
      }
  
      rotation[0] = x;
      rotation[1] = y;
      rotation[2] = w;
      rotation[3] = z;
  
      return out;
  };
  
  mat4.setPosition = function(out, v) {
      var z = v[2];
  
      out[12] = v[0];
      out[13] = v[1];
      out[14] = isNumber(z) ? z : 0;
  
      return out;
  };
  
  mat4.extractPosition = function(out, a) {
  
      out[12] = a[12];
      out[13] = a[13];
      out[14] = a[14];
  
      return out;
  };
  
  mat4.extractRotation = function(out, a) {
      var lx = vec3.lengthSqValues(a[0], a[1], a[2]),
          ly = vec3.lengthSqValues(a[4], a[5], a[6]),
          lz = vec3.lengthSqValues(a[8], a[9], a[10]),
  
          scaleX = lx !== 0 ? 1 / mathf.sqrt(lx) : lx,
          scaleY = ly !== 0 ? 1 / mathf.sqrt(ly) : ly,
          scaleZ = lz !== 0 ? 1 / mathf.sqrt(lz) : lz;
  
      out[0] = a[0] * scaleX;
      out[1] = a[1] * scaleX;
      out[2] = a[2] * scaleX;
  
      out[4] = a[4] * scaleY;
      out[5] = a[5] * scaleY;
      out[6] = a[6] * scaleY;
  
      out[8] = a[8] * scaleZ;
      out[9] = a[9] * scaleZ;
      out[10] = a[10] * scaleZ;
  
      return out;
  };
  
  mat4.extractRotationScale = function(out, a) {
  
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
  
      out[4] = a[4];
      out[5] = a[5];
      out[6] = a[6];
  
      out[8] = a[8];
      out[9] = a[9];
      out[10] = a[10];
  
      return out;
  };
  
  mat4.translate = function(out, a, v) {
      var x = v[0],
          y = v[1],
          z = v[2],
          a00, a01, a02, a03,
          a10, a11, a12, a13,
          a20, a21, a22, a23;
  
      if (a === out) {
          out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
          out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
          out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
          out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
      } else {
          a00 = a[0];
          a01 = a[1];
          a02 = a[2];
          a03 = a[3];
          a10 = a[4];
          a11 = a[5];
          a12 = a[6];
          a13 = a[7];
          a20 = a[8];
          a21 = a[9];
          a22 = a[10];
          a23 = a[11];
  
          out[0] = a00;
          out[1] = a01;
          out[2] = a02;
          out[3] = a03;
          out[4] = a10;
          out[5] = a11;
          out[6] = a12;
          out[7] = a13;
          out[8] = a20;
          out[9] = a21;
          out[10] = a22;
          out[11] = a23;
  
          out[12] = a00 * x + a10 * y + a20 * z + a[12];
          out[13] = a01 * x + a11 * y + a21 * z + a[13];
          out[14] = a02 * x + a12 * y + a22 * z + a[14];
          out[15] = a03 * x + a13 * y + a23 * z + a[15];
      }
  
      return out;
  };
  
  mat4.scale = function(out, a, v) {
      var x = v[0],
          y = v[1],
          z = v[2];
  
      out[0] = a[0] * x;
      out[1] = a[1] * x;
      out[2] = a[2] * x;
      out[3] = a[3] * x;
      out[4] = a[4] * y;
      out[5] = a[5] * y;
      out[6] = a[6] * y;
      out[7] = a[7] * y;
      out[8] = a[8] * z;
      out[9] = a[9] * z;
      out[10] = a[10] * z;
      out[11] = a[11] * z;
      out[12] = a[12];
      out[13] = a[13];
      out[14] = a[14];
      out[15] = a[15];
  
      return out;
  };
  
  mat4.rotateX = function(out, a, angle) {
      var s = Math.sin(angle),
          c = Math.cos(angle),
          a10 = a[4],
          a11 = a[5],
          a12 = a[6],
          a13 = a[7],
          a20 = a[8],
          a21 = a[9],
          a22 = a[10],
          a23 = a[11];
  
      if (a !== out) {
          out[0] = a[0];
          out[1] = a[1];
          out[2] = a[2];
          out[3] = a[3];
          out[12] = a[12];
          out[13] = a[13];
          out[14] = a[14];
          out[15] = a[15];
      }
  
      out[4] = a10 * c + a20 * s;
      out[5] = a11 * c + a21 * s;
      out[6] = a12 * c + a22 * s;
      out[7] = a13 * c + a23 * s;
      out[8] = a20 * c - a10 * s;
      out[9] = a21 * c - a11 * s;
      out[10] = a22 * c - a12 * s;
      out[11] = a23 * c - a13 * s;
  
      return out;
  };
  
  mat4.rotateY = function(out, a, angle) {
      var s = mathf.sin(angle),
          c = mathf.cos(angle),
          a00 = a[0],
          a01 = a[1],
          a02 = a[2],
          a03 = a[3],
          a20 = a[8],
          a21 = a[9],
          a22 = a[10],
          a23 = a[11];
  
      if (a !== out) {
          out[4] = a[4];
          out[5] = a[5];
          out[6] = a[6];
          out[7] = a[7];
          out[12] = a[12];
          out[13] = a[13];
          out[14] = a[14];
          out[15] = a[15];
      }
  
      out[0] = a00 * c - a20 * s;
      out[1] = a01 * c - a21 * s;
      out[2] = a02 * c - a22 * s;
      out[3] = a03 * c - a23 * s;
      out[8] = a00 * s + a20 * c;
      out[9] = a01 * s + a21 * c;
      out[10] = a02 * s + a22 * c;
      out[11] = a03 * s + a23 * c;
  
      return out;
  };
  
  mat4.rotateZ = function(out, a, angle) {
      var s = mathf.sin(angle),
          c = mathf.cos(angle),
          a00 = a[0],
          a01 = a[1],
          a02 = a[2],
          a03 = a[3],
          a10 = a[4],
          a11 = a[5],
          a12 = a[6],
          a13 = a[7];
  
      if (a !== out) {
          out[8] = a[8];
          out[9] = a[9];
          out[10] = a[10];
          out[11] = a[11];
          out[12] = a[12];
          out[13] = a[13];
          out[14] = a[14];
          out[15] = a[15];
      }
  
      out[0] = a00 * c + a10 * s;
      out[1] = a01 * c + a11 * s;
      out[2] = a02 * c + a12 * s;
      out[3] = a03 * c + a13 * s;
      out[4] = a10 * c - a00 * s;
      out[5] = a11 * c - a01 * s;
      out[6] = a12 * c - a02 * s;
      out[7] = a13 * c - a03 * s;
  
      return out;
  };
  
  mat4.setTranslation = function(out, v) {
  
      return mat4.set(
          out,
          1, 0, 0, v[0],
          0, 1, 0, v[1],
          0, 0, 1, v[2],
          0, 0, 0, 1
      );
  };
  
  mat4.setScale = function(out, v) {
      var z = v[3];
  
      return mat4.set(
          out,
          v[0], 0, 0, 0,
          0, v[1], 0, 0,
          0, 0, v[2], 0,
          0, 0, 0, isNumber(z) ? z : 1
      );
  };
  
  mat4.seteRotationX = function(out, angle) {
      var c = mathf.cos(angle),
          s = mathf.sin(angle);
  
      return mat4.set(
          out,
          1, 0, 0, 0,
          0, c, -s, 0,
          0, s, c, 0,
          0, 0, 0, 1
      );
  };
  
  mat4.setRotationY = function(out, angle) {
      var c = mathf.cos(angle),
          s = mathf.sin(angle);
  
      return mat4.set(
          out,
          c, 0, s, 0,
          0, 1, 0, 0, -s, 0, c, 0,
          0, 0, 0, 1
      );
  };
  
  mat4.setRotationZ = function(out, angle) {
      var c = mathf.cos(angle),
          s = mathf.sin(angle);
  
      return mat4.set(
          out,
          c, -s, 0, 0,
          s, c, 0, 0,
          0, 0, 1, 0,
          0, 0, 0, 1
      );
  };
  
  mat4.fromMat2 = function(out, m) {
  
      out[0] = m[0];
      out[1] = m[1];
      out[2] = 0;
      out[3] = 0;
  
      out[4] = m[2];
      out[5] = m[3];
      out[6] = 0;
      out[7] = 0;
  
      out[8] = 0;
      out[9] = 0;
      out[10] = 1;
      out[11] = 0;
  
      out[12] = 0;
      out[13] = 0;
      out[14] = 0;
      out[15] = 1;
  
      return out;
  };
  
  mat4.fromMat32 = function(out, m) {
  
      out[0] = m[0];
      out[1] = m[1];
      out[2] = 0;
      out[3] = 0;
  
      out[4] = m[2];
      out[5] = m[3];
      out[6] = 0;
      out[7] = 0;
  
      out[8] = 0;
      out[9] = 0;
      out[10] = 1;
      out[11] = 0;
  
      out[12] = m[4];
      out[13] = m[5];
      out[14] = 0;
      out[15] = 1;
  
      return out;
  };
  
  mat4.fromMat3 = function(out, m) {
  
      out[0] = m[0];
      out[1] = m[1];
      out[2] = m[2];
      out[3] = 0;
  
      out[4] = m[3];
      out[5] = m[4];
      out[6] = m[5];
      out[7] = 0;
  
      out[8] = m[6];
      out[9] = m[7];
      out[10] = m[8];
      out[11] = 0;
  
      out[12] = 0;
      out[13] = 0;
      out[14] = 0;
      out[15] = 1;
  
      return out;
  };
  
  mat4.fromQuat = function(out, q) {
      var x = q[0],
          y = q[1],
          z = q[2],
          w = q[3],
          x2 = x + x,
          y2 = y + y,
          z2 = z + z,
          xx = x * x2,
          xy = x * y2,
          xz = x * z2,
          yy = y * y2,
          yz = y * z2,
          zz = z * z2,
          wx = w * x2,
          wy = w * y2,
          wz = w * z2;
  
      out[0] = 1 - (yy + zz);
      out[4] = xy - wz;
      out[8] = xz + wy;
  
      out[1] = xy + wz;
      out[5] = 1 - (xx + zz);
      out[9] = yz - wx;
  
      out[2] = xz - wy;
      out[6] = yz + wx;
      out[10] = 1 - (xx + yy);
  
      out[3] = 0;
      out[7] = 0;
      out[11] = 0;
  
      out[12] = 0;
      out[13] = 0;
      out[14] = 0;
      out[15] = 1;
  
      return out;
  };
  
  mat4.frustum = function(out, top, right, bottom, left, near, far) {
      var x = 2 * near / (right - left),
          y = 2 * near / (top - bottom),
  
          a = (right + left) / (right - left),
          b = (top + bottom) / (top - bottom),
          c = -(far + near) / (far - near),
          d = -2 * far * near / (far - near);
  
      out[0] = x;
      out[4] = 0;
      out[8] = a;
      out[12] = 0;
      out[1] = 0;
      out[5] = y;
      out[9] = b;
      out[13] = 0;
      out[2] = 0;
      out[6] = 0;
      out[10] = c;
      out[14] = d;
      out[3] = 0;
      out[7] = 0;
      out[11] = -1;
      out[15] = 0;
  
      return out;
  };
  
  mat4.perspective = function(out, fov, aspect, near, far) {
      var ymax = near * mathf.tan(fov * 0.5),
          ymin = -ymax,
          xmin = ymin * aspect,
          xmax = ymax * aspect;
  
      return mat4.frustum(out, ymax, xmax, ymin, xmin, near, far);
  };
  
  mat4.orthographic = function(out, top, right, bottom, left, near, far) {
      var w = right - left,
          h = top - bottom,
          p = far - near,
  
          x = (right + left) / w,
          y = (top + bottom) / h,
          z = (far + near) / p;
  
      out[0] = 2 / w;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 0;
      out[5] = 2 / h;
      out[6] = 0;
      out[7] = 0;
      out[8] = 0;
      out[9] = 0;
      out[10] = -2 / p;
      out[11] = 0;
      out[12] = -x;
      out[13] = -y;
      out[14] = -z;
      out[15] = 1;
  
      return out;
  };
  
  mat4.equals = function(a, b, e) {
      return !mat4.notEquals(a, b, e);
  };
  
  mat4.notEquals = function(a, b, e) {
      return (!mathf.equals(a[0], b[0], e) ||
          !mathf.equals(a[1], b[1], e) ||
          !mathf.equals(a[2], b[2], e) ||
          !mathf.equals(a[3], b[3], e) ||
          !mathf.equals(a[4], b[4], e) ||
          !mathf.equals(a[5], b[5], e) ||
          !mathf.equals(a[6], b[6], e) ||
          !mathf.equals(a[7], b[7], e) ||
          !mathf.equals(a[8], b[8], e) ||
          !mathf.equals(a[9], b[9], e) ||
          !mathf.equals(a[10], b[10], e) ||
          !mathf.equals(a[11], b[11], e) ||
          !mathf.equals(a[12], b[12], e) ||
          !mathf.equals(a[13], b[13], e) ||
          !mathf.equals(a[14], b[14], e) ||
          !mathf.equals(a[15], b[15], e)
      );
  };
  
  mat4.str = function(out) {
      return (
          "Mat4[" + out[0] + ", " + out[4] + ", " + out[8] + ", " + out[12] + ",\n" +
          "     " + out[1] + ", " + out[5] + ", " + out[9] + ", " + out[13] + ",\n" +
          "     " + out[2] + ", " + out[6] + ", " + out[10] + ", " + out[14] + ",\n" +
          "     " + out[3] + ", " + out[7] + ", " + out[11] + ", " + out[15] + "]"
      );
  };
  
  mat4.string = mat4.toString = mat4.str;
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/request_animation_frame@0.0.4/src/index.js-=@*/
  var environment = require(22),
      emptyFunction = require(23),
      now = require(24);
  
  
  var window = environment.window,
      requestAnimationFrame, lastTime;
  
  
  window.requestAnimationFrame = (
      window.requestAnimationFrame ||
      window.webkitRequestAnimationFrame ||
      window.mozRequestAnimationFrame ||
      window.oRequestAnimationFrame ||
      window.msRequestAnimationFrame
  );
  
  window.cancelRequestAnimationFrame = (
      window.cancelAnimationFrame ||
      window.cancelRequestAnimationFrame ||
  
      window.webkitCancelAnimationFrame ||
      window.webkitCancelRequestAnimationFrame ||
  
      window.mozCancelAnimationFrame ||
      window.mozCancelRequestAnimationFrame ||
  
      window.oCancelAnimationFrame ||
      window.oCancelRequestAnimationFrame ||
  
      window.msCancelAnimationFrame ||
      window.msCancelRequestAnimationFrame
  );
  
  
  if (window.requestAnimationFrame) {
      requestAnimationFrame = function requestAnimationFrame(callback, element) {
          return window.requestAnimationFrame(callback, element);
      };
  } else {
      lastTime = 0;
  
      requestAnimationFrame = function requestAnimationFrame(callback) {
          var current = now.stamp(),
              timeToCall = Math.max(0, 16 - (current - lastTime)),
              id = global.setTimeout(
                  function runCallback() {
                      callback(current + timeToCall);
                  },
                  timeToCall
              );
  
          lastTime = current + timeToCall;
          return id;
      };
  }
  
  
  if (window.cancelRequestAnimationFrame && window.requestAnimationFrame) {
      requestAnimationFrame.cancel = function(id) {
          return window.cancelRequestAnimationFrame(id);
      };
  } else {
      requestAnimationFrame.cancel = function(id) {
          return global.clearTimeout(id);
      };
  }
  
  
  requestAnimationFrame(emptyFunction);
  
  
  module.exports = requestAnimationFrame;
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/index.js-=@*/
  var mathf = require(5),
  
      isNull = require(18),
      isNullOrUndefined = require(13),
  
      environment = require(22),
      EventEmitter = require(30),
      eventListener = require(31),
      color = require(32),
  
      enums = require(33),
      WebGLBuffer = require(34),
      WebGLTexture = require(35),
      WebGLFrameBuffer = require(36),
      WebGLProgram = require(37);
  
  
  var NativeUint8Array = typeof(Uint8Array) !== "undefined" ? Uint8Array : Array,
      cullFace = enums.cullFace,
      blending = enums.blending,
      depth = enums.depth,
      WebGLContextPrototype;
  
  
  module.exports = WebGLContext;
  
  
  WebGLContext.enums = enums;
  WebGLContext.WebGLTexture = WebGLTexture;
  WebGLContext.WebGLProgram = WebGLProgram;
  
  
  function WebGLContext() {
  
      EventEmitter.call(this);
  
      this.gl = null;
      this.canvas = null;
  
      this.__attributes = {
          alpha: true,
          antialias: true,
          depth: true,
          premultipliedAlpha: true,
          preserveDrawingBuffer: false,
          stencil: true
      };
  
      this.__textures = {};
      this.__framebuffers = {};
  
      this.__precision = null;
      this.__extensions = {};
  
      this.__maxAnisotropy = null;
      this.__maxTextures = null;
      this.__maxVertexTextures = null;
      this.__maxTextureSize = null;
      this.__maxCubeTextureSize = null;
      this.__maxRenderBufferSize = null;
  
      this.__maxUniforms = null;
      this.__maxVaryings = null;
      this.__maxAttributes = null;
  
      this.__enabledAttributes = null;
  
      this.__viewportX = null;
      this.__viewportY = null;
      this.__viewportWidth = null;
      this.__viewportHeight = null;
  
      this.__clearColor = color.create();
      this.__clearAlpha = null;
  
      this.__blending = null;
      this.__blendingDisabled = null;
      this.__cullFace = null;
      this.__cullFaceDisabled = null;
      this.__depthFunc = null;
      this.__depthTestDisabled = null;
      this.__depthWrite = null;
      this.__lineWidth = null;
  
      this.__program = null;
      this.__programForce = null;
  
      this.__textureIndex = null;
      this.__activeIndex = null;
      this.__activeTexture = null;
  
      this.__arrayBuffer = null;
      this.__elementArrayBuffer = null;
  
      this.__framebuffer = null;
  
      this.__handlerContextLost = null;
      this.__handlerContextRestored = null;
  }
  EventEmitter.extend(WebGLContext);
  WebGLContextPrototype = WebGLContext.prototype;
  
  WebGLContextPrototype.setAttributes = function(attributes) {
  
      getAttributes(this.__attributes, attributes);
  
      if (this.gl) {
          WebGLContext_getGLContext(this);
      }
  
      return this;
  };
  
  WebGLContextPrototype.setCanvas = function(canvas, attributes) {
      var _this = this,
          thisCanvas = this.canvas;
  
      if (thisCanvas) {
          if (thisCanvas !== canvas) {
              eventListener.off(thisCanvas, "webglcontextlost", this.__handlerContextLost);
              eventListener.off(thisCanvas, "webglcontextrestored", this.__handlerContextRestored);
          } else {
              return this;
          }
      }
  
      getAttributes(this.__attributes, attributes);
      this.canvas = canvas;
  
      this.__handlerContextLost = this.__handlerContextLost || function handlerContextLost(e) {
          handleWebGLContextContextLost(_this, e);
      };
      this.__handlerContextRestored = this.__handlerContextRestored || function handlerContextRestored(e) {
          handleWebGLContextContextRestored(_this, e);
      };
  
      eventListener.on(canvas, "webglcontextlost", this.__handlerContextLost);
      eventListener.on(canvas, "webglcontextrestored", this.__handlerContextRestored);
  
      WebGLContext_getGLContext(this);
  
      return this;
  };
  
  WebGLContextPrototype.clearGL = function() {
  
      this.gl = null;
  
      this.__textures = {};
  
      this.__precision = null;
      this.__extensions = {};
  
      this.__maxAnisotropy = null;
      this.__maxTextures = null;
      this.__maxVertexTextures = null;
      this.__maxTextureSize = null;
      this.__maxCubeTextureSize = null;
      this.__maxRenderBufferSize = null;
  
      this.__maxUniforms = null;
      this.__maxVaryings = null;
      this.__maxAttributes = null;
  
      this.__enabledAttributes = null;
  
      this.__viewportX = null;
      this.__viewportY = null;
      this.__viewportWidth = null;
      this.__viewportHeight = null;
  
      color.set(this.__clearColor, 0, 0, 0);
      this.__clearAlpha = null;
  
      this.__blending = null;
      this.__blendingDisabled = true;
      this.__cullFace = null;
      this.__cullFaceDisabled = true;
      this.__depthFunc = null;
      this.__depthTestDisabled = true;
      this.__depthWrite = null;
      this.__lineWidth = null;
  
      this.__program = null;
      this.__programForce = null;
  
      this.__textureIndex = null;
      this.__activeIndex = null;
      this.__activeTexture = null;
  
      this.__arrayBuffer = null;
      this.__elementArrayBuffer = null;
  
      this.__framebuffer = null;
  
      return this;
  };
  
  WebGLContextPrototype.resetGL = function() {
  
      this.__textures = {};
  
      this.__viewportX = null;
      this.__viewportY = null;
      this.__viewportWidth = null;
      this.__viewportHeight = null;
  
      this.__clearAlpha = null;
  
      this.__blending = null;
      this.__blendingDisabled = true;
      this.__cullFace = null;
      this.__cullFaceDisabled = true;
      this.__depthFunc = null;
      this.__depthTestDisabled = true;
      this.__depthWrite = null;
      this.__lineWidth = null;
  
      this.__program = null;
      this.__programForce = null;
  
      this.__textureIndex = null;
      this.__activeIndex = null;
      this.__activeTexture = null;
  
      this.__arrayBuffer = null;
      this.__elementArrayBuffer = null;
  
      this.__framebuffer = null;
  
      this.disableAttributes();
      this.setViewport(0, 0, 1, 1);
      this.setDepthWrite(true);
      this.setLineWidth(1);
      this.setDepthFunc(depth.LESS);
      this.setCullFace(cullFace.BACK);
      this.setBlending(blending.DEFAULT);
      this.setClearColor(color.set(this.__clearColor, 0, 0, 0), 1);
      this.setProgram(null);
      this.clearCanvas();
  
      return this;
  };
  
  WebGLContextPrototype.clampMaxSize = function(image, isCubeMap) {
      var maxSize = isCubeMap ? this.__maxCubeTextureSize : this.__maxTextureSize,
          maxDim, newWidth, newHeight, canvas, ctx;
  
      if (!image || (image.height <= maxSize && image.width <= maxSize)) {
          return image;
      } else {
          maxDim = 1 / mathf.max(image.width, image.height);
          newWidth = (image.width * maxSize * maxDim) | 0;
          newHeight = (image.height * maxSize * maxDim) | 0;
          canvas = document.createElement("canvas");
          ctx = canvas.getContext("2d");
  
          canvas.width = newWidth;
          canvas.height = newHeight;
          ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, newWidth, newHeight);
  
          return canvas;
      }
  };
  
  WebGLContextPrototype.setProgram = function(program, force) {
      if (this.__program !== program || force) {
          this.__program = program;
          this.__programForce = true;
  
          if (program) {
              this.gl.useProgram(program.glProgram);
          } else {
              this.gl.useProgram(null);
          }
      } else {
          if (this.__textureIndex !== 0 || this.__activeIndex !== -1) {
              this.__programForce = true;
          } else {
              this.__programForce = false;
          }
      }
  
      this.__textureIndex = 0;
      this.__activeIndex = -1;
  
      return this;
  };
  
  WebGLContextPrototype.setTexture = function(location, texture, force) {
      var gl = this.gl,
          webglTexture = this.createTexture(texture),
          index = this.__textureIndex++,
          needsUpdate = this.__activeIndex !== index;
  
      this.__activeIndex = index;
  
      if (this.__activeTexture !== webglTexture || force) {
          this.__activeTexture = webglTexture;
  
          if (needsUpdate || this.__programForce || force) {
              gl.activeTexture(gl.TEXTURE0 + index);
              gl.uniform1i(location, index);
          }
  
          if (webglTexture.isCubeMap) {
              gl.bindTexture(gl.TEXTURE_CUBE_MAP, webglTexture.getGLTexture());
          } else {
              gl.bindTexture(gl.TEXTURE_2D, webglTexture.getGLTexture());
          }
  
          return true;
      } else {
          return false;
      }
  };
  
  WebGLContextPrototype.setFrameBuffer = function(framebuffer, force) {
      var gl = this.gl,
          webglFrameBuffer = this.createFrameBuffer(framebuffer),
          glFrameBuffer, webglTexture;
  
      if (this.__framebuffer !== webglFrameBuffer || force) {
          this.__framebuffer = webglFrameBuffer;
  
          webglTexture = this.createTexture(framebuffer.texture);
          glFrameBuffer = webglFrameBuffer.getGLFrameBuffer();
  
          gl.bindFramebuffer(gl.FRAMEBUFFER, glFrameBuffer);
          gl.viewport(0, 0, webglTexture.getWidth(), webglTexture.getHeight());
  
          if (webglFrameBuffer.isCubeMap) {
              gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + framebuffer.activeCubeFace, webglTexture.getGLTexture(), 0);
          }
  
          return true;
      } else {
          return false;
      }
  };
  
  WebGLContextPrototype.clearFrameBuffer = function() {
      var gl = this.gl,
          webglFrameBuffer = this.__framebuffer;
  
      if (!isNull(webglFrameBuffer)) {
          this.__framebuffer = null;
  
          gl.bindFramebuffer(gl.FRAMEBUFFER, null);
          gl.viewport(this.__viewportX, this.__viewportY, this.__viewportWidth, this.__viewportHeight);
  
          return true;
      } else {
          return false;
      }
  };
  
  WebGLContextPrototype.setArrayBuffer = function(buffer, force) {
      var gl = this.gl;
  
      if (this.__arrayBuffer !== buffer || force) {
          this.disableAttributes();
          gl.bindBuffer(gl.ARRAY_BUFFER, buffer.glBuffer);
          this.__arrayBuffer = buffer;
          return true;
      } else {
          return false;
      }
  };
  
  WebGLContextPrototype.setElementArrayBuffer = function(buffer, force) {
      var gl = this.gl;
  
      if (this.__elementArrayBuffer !== buffer || force) {
          gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer.glBuffer);
          this.__elementArrayBuffer = buffer;
          return true;
      } else {
          return false;
      }
  };
  
  WebGLContextPrototype.setAttribPointer = function(location, itemSize, type, stride, offset, force) {
      var gl = this.gl;
  
      if (this.enableAttribute(location) || force) {
          gl.vertexAttribPointer(location, itemSize, type, gl.FALSE, stride, offset);
          return true;
      } else {
          return false;
      }
  };
  
  WebGLContextPrototype.createProgram = function() {
      return new WebGLProgram(this);
  };
  
  WebGLContextPrototype.createTexture = function(texture) {
      var textures = this.__textures;
      return textures[texture.__id] || (textures[texture.__id] = new WebGLTexture(this, texture));
  };
  
  WebGLContextPrototype.getTexture = function(texture) {
      return this.__textures[texture.__id];
  };
  
  WebGLContextPrototype.createFrameBuffer = function(framebuffer) {
      var framebuffers = this.__framebuffers;
      return framebuffers[framebuffer.__id] || (framebuffers[framebuffer.__id] = new WebGLFrameBuffer(this, framebuffer));
  };
  
  WebGLContextPrototype.getFrameBuffer = function(framebuffer) {
      return this.__framebuffers[framebuffer.__id];
  };
  
  WebGLContextPrototype.createBuffer = function() {
      return new WebGLBuffer(this);
  };
  
  WebGLContextPrototype.deleteProgram = function(program) {
      if (program) {
          program.destroy();
      }
      return this;
  };
  
  WebGLContextPrototype.deleteTexture = function(texture) {
      var webglTexture = this.getTexture(texture);
  
      if (webglTexture) {
          webglTexture.destroy();
      }
  
      return this;
  };
  
  WebGLContextPrototype.deleteBuffer = function(buffer) {
      if (buffer) {
          buffer.destroy();
      }
      return this;
  };
  
  WebGLContextPrototype.deleteFrameBuffer = function(frameBuffer) {
      var webglFrameBuffer = this.getFrameBuffer(frameBuffer);
  
      if (webglFrameBuffer) {
          webglFrameBuffer.destroy();
      }
  
      return this;
  };
  
  WebGLContextPrototype.setViewport = function(x, y, width, height) {
      x = x || 0;
      y = y || 0;
      width = width || 1;
      height = height || 1;
  
      if (
          this.__viewportX !== x ||
          this.__viewportY !== y ||
          this.__viewportWidth !== width ||
          this.__viewportHeight !== height
      ) {
          this.__viewportX = x;
          this.__viewportY = y;
          this.__viewportWidth = width;
          this.__viewportHeight = height;
  
          this.gl.viewport(x, y, width, height);
      }
  
      return this;
  };
  
  WebGLContextPrototype.setDepthWrite = function(depthWrite) {
  
      if (this.__depthWrite !== depthWrite) {
          this.__depthWrite = depthWrite;
          this.gl.depthMask(depthWrite);
      }
  
      return this;
  };
  
  WebGLContextPrototype.setLineWidth = function(width) {
  
      if (this.__lineWidth !== width) {
          this.__lineWidth = width;
          this.gl.lineWidth(width);
      }
  
      return this;
  };
  
  WebGLContextPrototype.setDepthFunc = function(depthFunc) {
      var gl = this.gl;
  
      if (this.__depthFunc !== depthFunc) {
          switch (depthFunc) {
              case depth.NEVER:
                  if (this.__depthTestDisabled) {
                      gl.enable(gl.DEPTH_TEST);
                  }
                  gl.depthFunc(gl.NEVER);
                  break;
              case depth.LESS:
                  if (this.__depthTestDisabled) {
                      gl.enable(gl.DEPTH_TEST);
                  }
                  gl.depthFunc(gl.LESS);
                  break;
              case depth.EQUAL:
                  if (this.__depthTestDisabled) {
                      gl.enable(gl.DEPTH_TEST);
                  }
                  gl.depthFunc(gl.EQUAL);
                  break;
              case depth.LEQUAL:
                  if (this.__depthTestDisabled) {
                      gl.enable(gl.DEPTH_TEST);
                  }
                  gl.depthFunc(gl.LEQUAL);
                  break;
              case depth.GREATER:
                  if (this.__depthTestDisabled) {
                      gl.enable(gl.DEPTH_TEST);
                  }
                  gl.depthFunc(gl.GREATER);
                  break;
              case depth.NOTEQUAL:
                  if (this.__depthTestDisabled) {
                      gl.enable(gl.DEPTH_TEST);
                  }
                  gl.depthFunc(gl.NOTEQUAL);
                  break;
              case depth.GEQUAL:
                  if (this.__depthTestDisabled) {
                      gl.enable(gl.DEPTH_TEST);
                  }
                  gl.depthFunc(gl.GEQUAL);
                  break;
              case depth.ALWAYS:
                  if (this.__depthTestDisabled) {
                      gl.enable(gl.DEPTH_TEST);
                  }
                  gl.depthFunc(gl.ALWAYS);
                  break;
              default:
                  this.__depthTestDisabled = true;
                  this.__depthFunc = depth.NONE;
                  gl.disable(gl.DEPTH_TEST);
                  return this;
          }
  
          this.__depthTestDisabled = false;
          this.__depthFunc = depthFunc;
      }
  
      return this;
  };
  
  WebGLContextPrototype.setCullFace = function(value) {
      var gl = this.gl;
  
      if (this.__cullFace !== value) {
          switch (value) {
              case cullFace.BACK:
                  if (this.__cullFaceDisabled) {
                      gl.enable(gl.CULL_FACE);
                  }
                  gl.cullFace(gl.BACK);
                  break;
              case cullFace.FRONT:
                  if (this.__cullFaceDisabled) {
                      gl.enable(gl.CULL_FACE);
                  }
                  gl.cullFace(gl.FRONT);
                  break;
              case cullFace.FRONT_AND_BACK:
                  if (this.__cullFaceDisabled) {
                      gl.enable(gl.CULL_FACE);
                  }
                  gl.cullFace(gl.FRONT_AND_BACK);
                  break;
              default:
                  this.__cullFaceDisabled = true;
                  this.__cullFace = cullFace.NONE;
                  gl.disable(gl.CULL_FACE);
                  return this;
          }
  
          this.__cullFaceDisabled = false;
          this.__cullFace = value;
      }
  
      return this;
  };
  
  WebGLContextPrototype.setBlending = function(value) {
      var gl = this.gl;
  
      if (this.__blending !== value) {
          switch (value) {
              case blending.ADDITIVE:
                  if (this.__blendingDisabled) {
                      gl.enable(gl.BLEND);
                  }
                  gl.blendEquation(gl.FUNC_ADD);
                  gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
                  break;
              case blending.SUBTRACTIVE:
                  if (this.__blendingDisabled) {
                      gl.enable(gl.BLEND);
                  }
                  gl.blendEquation(gl.FUNC_ADD);
                  gl.blendFunc(gl.ZERO, gl.ONE_MINUS_SRC_COLOR);
                  break;
              case blending.MULTIPLY:
                  if (this.__blendingDisabled) {
                      gl.enable(gl.BLEND);
                  }
                  gl.blendEquation(gl.FUNC_ADD);
                  gl.blendFunc(gl.ZERO, gl.SRC_COLOR);
                  break;
              case blending.DEFAULT:
                  if (this.__blendingDisabled) {
                      gl.enable(gl.BLEND);
                  }
                  gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
                  gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
                  break;
              default:
                  gl.disable(gl.BLEND);
                  this.__blendingDisabled = true;
                  this.__blending = blending.NONE;
                  return this;
          }
  
          this.__blendingDisabled = false;
          this.__blending = value;
      }
  
      return this;
  };
  
  WebGLContextPrototype.setClearColor = function(clearColor, alpha) {
      alpha = alpha || 1;
  
      if (color.notEquals(this.__clearColor, clearColor) || alpha !== this.__clearAlpha) {
  
          color.copy(this.__clearColor, clearColor);
          this.__clearAlpha = alpha;
  
          this.gl.clearColor(clearColor[0], clearColor[1], clearColor[2], alpha);
      }
  
      return this;
  };
  
  WebGLContextPrototype.scissor = function(x, y, width, height) {
      this.gl.scissor(x, y, width, height);
      return this;
  };
  
  WebGLContextPrototype.clearCanvas = function(color, depth, stencil) {
      var gl = this.gl,
          bits = 0;
  
      if (color !== false) {
          bits |= gl.COLOR_BUFFER_BIT;
      }
      if (depth !== false) {
          bits |= gl.DEPTH_BUFFER_BIT;
      }
      if (stencil !== false) {
          bits |= gl.STENCIL_BUFFER_BIT;
      }
  
      gl.clear(bits);
  
      return this;
  };
  
  WebGLContextPrototype.clearColor = function() {
      var gl = this.gl;
  
      gl.clear(gl.COLOR_BUFFER_BIT);
      return this;
  };
  
  WebGLContextPrototype.clearDepth = function() {
      var gl = this.gl;
  
      gl.clear(gl.DEPTH_BUFFER_BIT);
      return this;
  };
  
  WebGLContextPrototype.clearStencil = function() {
      var gl = this.gl;
  
      gl.clear(gl.STENCIL_BUFFER_BIT);
      return this;
  };
  
  WebGLContextPrototype.enableAttribute = function(attribute) {
      var enabledAttributes = this.__enabledAttributes;
  
      if (enabledAttributes[attribute] === 0) {
          this.gl.enableVertexAttribArray(attribute);
          enabledAttributes[attribute] = 1;
          return true;
      } else {
          return false;
      }
  };
  
  WebGLContextPrototype.disableAttribute = function(attribute) {
      var enabledAttributes = this.__enabledAttributes;
  
      if (enabledAttributes[attribute] === 1) {
          this.gl.disableVertexAttribArray(attribute);
          enabledAttributes[attribute] = 0;
          return true;
      } else {
          return false;
      }
  };
  
  WebGLContextPrototype.disableAttributes = function() {
      var gl = this.gl,
          i = this.__maxAttributes,
          enabledAttributes = this.__enabledAttributes;
  
      while (i--) {
          if (enabledAttributes[i] === 1) {
              gl.disableVertexAttribArray(i);
              enabledAttributes[i] = 0;
          }
      }
  
      return this;
  };
  
  var getExtension_lowerPrefixes = ["webkit", "moz", "o", "ms"],
      getExtension_upperPrefixes = ["WEBKIT", "MOZ", "O", "MS"];
  
  WebGLContextPrototype.getExtension = function(name, throwError) {
      var gl = this.gl,
          extensions = this.__extensions || (this.__extensions = {}),
          extension = extensions[name] || (extensions[name] = gl.getExtension(name)),
          i;
  
      if (isNullOrUndefined(extension)) {
          i = getExtension_upperPrefixes.length;
  
          while (i--) {
              if (!isNullOrUndefined(extension = gl.getExtension(getExtension_upperPrefixes[i] + "_" + name))) {
                  extensions[name] = extension;
                  break;
              }
          }
      }
      if (isNullOrUndefined(extension)) {
          i = getExtension_lowerPrefixes.length;
  
          while (i--) {
              if (!isNullOrUndefined(extension = gl.getExtension(getExtension_lowerPrefixes[i] + name))) {
                  extensions[name] = extension;
                  break;
              }
          }
      }
  
      if (isNullOrUndefined(extension)) {
          if (throwError) {
              throw new Error("WebGLContext.getExtension: could not get Extension " + name);
          } else {
              return null;
          }
      } else {
          return extension;
      }
  };
  
  
  function getAttributes(attributes, options) {
      options = options || {};
  
      attributes.alpha = !isNullOrUndefined(options.alpha) ? !!options.alpha : attributes.alpha;
      attributes.antialias = !isNullOrUndefined(options.antialias) ? !!options.antialias : attributes.antialias;
      attributes.depth = !isNullOrUndefined(options.depth) ? !!options.depth : attributes.depth;
      attributes.premultipliedAlpha = !isNullOrUndefined(options.premultipliedAlpha) ? !!options.premultipliedAlpha : attributes.premultipliedAlpha;
      attributes.preserveDrawingBuffer = !isNullOrUndefined(options.preserveDrawingBuffer) ? !!options.preserveDrawingBuffer : attributes.preserveDrawingBuffer;
      attributes.stencil = !isNullOrUndefined(options.stencil) ? !!options.stencil : attributes.stencil;
  
      return attributes;
  }
  
  function handleWebGLContextContextLost(_this, e) {
      e.preventDefault();
      _this.clearGL();
      _this.emit("webglcontextlost", e);
  }
  
  function handleWebGLContextContextRestored(_this, e) {
      e.preventDefault();
      WebGLContext_getGLContext(_this);
      _this.emit("webglcontextrestored", e);
  }
  
  function WebGLContext_getGLContext(_this) {
      var gl;
  
      if (!isNullOrUndefined(_this.gl)) {
          _this.clearGL();
      }
  
      gl = getWebGLContext(_this.canvas, _this.__attributes);
  
      if (isNullOrUndefined(gl)) {
          _this.emit("webglcontextcreationfailed");
      } else {
          _this.emit("webglcontextcreation");
  
          if (!gl.getShaderPrecisionFormat) {
              gl.getShaderPrecisionFormat = getShaderPrecisionFormat;
          }
  
          _this.gl = gl;
          getGPUInfo(_this);
          _this.resetGL();
      }
  }
  
  function getShaderPrecisionFormat() {
      return {
          rangeMin: 1,
          rangeMax: 1,
          precision: 1
      };
  }
  
  function getGPUInfo(_this) {
      var gl = _this.gl,
  
          VERTEX_SHADER = gl.VERTEX_SHADER,
          FRAGMENT_SHADER = gl.FRAGMENT_SHADER,
          HIGH_FLOAT = gl.HIGH_FLOAT,
          MEDIUM_FLOAT = gl.MEDIUM_FLOAT,
  
          EXT_tfa = _this.getExtension("EXT_texture_filter_anisotropic"),
  
          vsHighpFloat = gl.getShaderPrecisionFormat(VERTEX_SHADER, HIGH_FLOAT),
          vsMediumpFloat = gl.getShaderPrecisionFormat(VERTEX_SHADER, MEDIUM_FLOAT),
  
          fsHighpFloat = gl.getShaderPrecisionFormat(FRAGMENT_SHADER, HIGH_FLOAT),
          fsMediumpFloat = gl.getShaderPrecisionFormat(FRAGMENT_SHADER, MEDIUM_FLOAT),
  
          highpAvailable = vsHighpFloat.precision > 0 && fsHighpFloat.precision > 0,
          mediumpAvailable = vsMediumpFloat.precision > 0 && fsMediumpFloat.precision > 0,
  
          precision = "highp";
  
      if (!highpAvailable || environment.mobile) {
          if (mediumpAvailable) {
              precision = "mediump";
          } else {
              precision = "lowp";
          }
      }
  
      _this.__precision = precision;
      _this.__maxAnisotropy = EXT_tfa ? gl.getParameter(EXT_tfa.MAX_TEXTURE_MAX_ANISOTROPY_EXT) : 1;
      _this.__maxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
      _this.__maxVertexTextures = gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS);
      _this.__maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
      _this.__maxCubeTextureSize = gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE);
      _this.__maxRenderBufferSize = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE);
  
      _this.__maxUniforms = mathf.max(
          gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS), gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS)
      ) * 4;
      _this.__maxVaryings = gl.getParameter(gl.MAX_VARYING_VECTORS) * 4;
      _this.__maxAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
  
      _this.__enabledAttributes = new NativeUint8Array(_this.__maxAttributes);
  }
  
  var getWebGLContext_webglNames = ["3d", "moz-webgl", "experimental-webgl", "webkit-3d", "webgl"],
      getWebGLContext_webglAttributes = {
          alpha: true,
          antialias: true,
          depth: true,
          premultipliedAlpha: true,
          preserveDrawingBuffer: false,
          stencil: true
      };
  
  function getWebGLContext(canvas, attributes) {
      var webglNames = getWebGLContext_webglNames,
          webglAttributes = getWebGLContext_webglAttributes,
          i = webglNames.length,
          gl, key;
  
      attributes = attributes || {};
  
      for (key in webglAttributes) {
          if (isNullOrUndefined(attributes[key])) {
              attributes[key] = webglAttributes[key];
          }
      }
  
      while (i--) {
          try {
              gl = canvas.getContext(webglNames[i], attributes);
              if (gl) {
                  return gl;
              }
          } catch (e) {}
      }
  
      if (!gl) {
          throw new Error("WebGLContext: could not get a WebGL Context");
      }
  
      return gl;
  }
  },
  function(require, exports, module, undefined, global) {
  /*@=-/var/www/html/node/_engine/js-webgl_context/src/enums/filterMode.js-=@*/
  var enums = require(60);
  
  
  module.exports = enums({
      NONE: 1,
      LINEAR: 2
  });
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/mathf@0.0.3/src/index.js-=@*/
  var keys = require(8),
      clamp = require(9),
      isNaNPolyfill = require(10);
  
  
  var mathf = exports,
  
      NativeMath = global.Math,
  
      hasFloat32Array = typeof(Float32Array) !== "undefined",
      NativeFloat32Array = hasFloat32Array ? Float32Array : Array;
  
  
  mathf.ArrayType = NativeFloat32Array;
  
  mathf.PI = NativeMath.PI;
  mathf.TAU = mathf.PI * 2;
  mathf.TWO_PI = mathf.TAU;
  mathf.HALF_PI = mathf.PI * 0.5;
  mathf.FOURTH_PI = mathf.PI * 0.25;
  
  mathf.EPSILON = Number.EPSILON || NativeMath.pow(2, -52);
  
  mathf.TO_RADS = mathf.PI / 180;
  mathf.TO_DEGS = 180 / mathf.PI;
  
  mathf.E = NativeMath.E;
  mathf.LN2 = NativeMath.LN2;
  mathf.LN10 = NativeMath.LN10;
  mathf.LOG2E = NativeMath.LOG2E;
  mathf.LOG10E = NativeMath.LOG10E;
  mathf.SQRT1_2 = NativeMath.SQRT1_2;
  mathf.SQRT2 = NativeMath.SQRT2;
  
  mathf.abs = NativeMath.abs;
  
  mathf.acos = NativeMath.acos;
  mathf.acosh = NativeMath.acosh || function acosh(x) {
      return mathf.log(x + mathf.sqrt(x * x - 1));
  };
  mathf.asin = NativeMath.asin;
  mathf.asinh = NativeMath.asinh || function asinh(x) {
      if (x === -Infinity) {
          return x;
      } else {
          return mathf.log(x + mathf.sqrt(x * x + 1));
      }
  };
  mathf.atan = NativeMath.atan;
  mathf.atan2 = NativeMath.atan2;
  mathf.atanh = NativeMath.atanh || function atanh(x) {
      return mathf.log((1 + x) / (1 - x)) / 2;
  };
  
  mathf.cbrt = NativeMath.cbrt || function cbrt(x) {
      var y = mathf.pow(mathf.abs(x), 1 / 3);
      return x < 0 ? -y : y;
  };
  
  mathf.ceil = NativeMath.ceil;
  
  mathf.clz32 = NativeMath.clz32 || function clz32(value) {
      value = +value >>> 0;
      return value ? 32 - value.toString(2).length : 32;
  };
  
  mathf.cos = NativeMath.cos;
  mathf.cosh = NativeMath.cosh || function cosh(x) {
      return (mathf.exp(x) + mathf.exp(-x)) / 2;
  };
  
  mathf.exp = NativeMath.exp;
  
  mathf.expm1 = NativeMath.expm1 || function expm1(x) {
      return mathf.exp(x) - 1;
  };
  
  mathf.floor = NativeMath.floor;
  mathf.fround = NativeMath.fround || (hasFloat32Array ?
      function fround(x) {
          return new NativeFloat32Array([x])[0];
      } :
      function fround(x) {
          return x;
      }
  );
  
  mathf.hypot = NativeMath.hypot || function hypot() {
      var y = 0,
          i = -1,
          il = arguments.length - 1,
          value;
  
      while (i++ < il) {
          value = arguments[i];
  
          if (value === Infinity || value === -Infinity) {
              return Infinity;
          } else {
              y += value * value;
          }
      }
  
      return mathf.sqrt(y);
  };
  
  mathf.imul = NativeMath.imul || function imul(a, b) {
      var ah = (a >>> 16) & 0xffff,
          al = a & 0xffff,
          bh = (b >>> 16) & 0xffff,
          bl = b & 0xffff;
  
      return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0) | 0);
  };
  
  mathf.log = NativeMath.log;
  
  mathf.log1p = NativeMath.log1p || function log1p(x) {
      return mathf.log(1 + x);
  };
  
  mathf.log10 = NativeMath.log10 || function log10(x) {
      return mathf.log(x) / mathf.LN10;
  };
  
  mathf.log2 = NativeMath.log2 || function log2(x) {
      return mathf.log(x) / mathf.LN2;
  };
  
  mathf.fac = function fac(n) {
      if (n < 2) {
          return 1;
      } else {
          return n * fac(n - 1);
      }
  };
  
  mathf.max = NativeMath.max;
  mathf.min = NativeMath.min;
  
  mathf.pow = NativeMath.pow;
  
  mathf.random = NativeMath.random;
  mathf.round = NativeMath.round;
  
  mathf.sign = NativeMath.sign || function sign(x) {
      x = +x;
      if (x === 0 || isNaNPolyfill(x)) {
          return x;
      } else {
          return x > 0 ? 1 : -1;
      }
  };
  
  mathf.sin = NativeMath.sin;
  mathf.sinh = NativeMath.sinh || function sinh(x) {
      return (mathf.exp(x) - mathf.exp(-x)) / 2;
  };
  
  mathf.sqrt = NativeMath.sqrt;
  
  mathf.tan = NativeMath.tan;
  mathf.tanh = NativeMath.tanh || function tanh(x) {
      if (x === Infinity) {
          return 1;
      } else if (x === -Infinity) {
          return -1;
      } else {
          return (mathf.exp(x) - mathf.exp(-x)) / (mathf.exp(x) + mathf.exp(-x));
      }
  };
  
  mathf.trunc = NativeMath.trunc || function trunc(x) {
      return x < 0 ? mathf.ceil(x) : mathf.floor(x);
  };
  
  mathf.equals = function(a, b, e) {
      return mathf.abs(a - b) < (e !== void(0) ? e : mathf.EPSILON);
  };
  
  mathf.modulo = function(a, b) {
      var r = a % b;
      return (r * b < 0) ? r + b : r;
  };
  
  mathf.standardRadian = function(x) {
      return mathf.modulo(x, mathf.TWO_PI);
  };
  
  mathf.standardAngle = function(x) {
      return mathf.modulo(x, 360);
  };
  
  mathf.snap = function(x, y) {
      var m = x % y;
      return m < (y * 0.5) ? x - m : x + y - m;
  };
  
  mathf.clamp = clamp;
  
  mathf.clampBottom = function(x, min) {
      return x < min ? min : x;
  };
  
  mathf.clampTop = function(x, max) {
      return x > max ? max : x;
  };
  
  mathf.clamp01 = function(x) {
      if (x < 0) {
          return 0;
      } else if (x > 1) {
          return 1;
      } else {
          return x;
      }
  };
  
  mathf.truncate = function(x, n) {
      var p = mathf.pow(10, n),
          num = x * p;
  
      return (num < 0 ? mathf.ceil(num) : mathf.floor(num)) / p;
  };
  
  mathf.lerp = function(a, b, x) {
      return a + (b - a) * x;
  };
  
  mathf.lerpRadian = function(a, b, x) {
      return mathf.standardRadian(a + (b - a) * x);
  };
  
  mathf.lerpAngle = function(a, b, x) {
      return mathf.standardAngle(a + (b - a) * x);
  };
  
  mathf.lerpCos = function(a, b, x) {
      var ft = x * mathf.PI,
          f = (1 - mathf.cos(ft)) * 0.5;
  
      return a * (1 - f) + b * f;
  };
  
  mathf.lerpCubic = function(v0, v1, v2, v3, x) {
      var P, Q, R, S, Px, Qx, Rx;
  
      v0 = v0 || v1;
      v3 = v3 || v2;
  
      P = (v3 - v2) - (v0 - v1);
      Q = (v0 - v1) - P;
      R = v2 - v0;
      S = v1;
  
      Px = P * x;
      Qx = Q * x;
      Rx = R * x;
  
      return (Px * Px * Px) + (Qx * Qx) + Rx + S;
  };
  
  mathf.smoothStep = function(x, min, max) {
      if (x <= min) {
          return 0;
      } else {
          if (x >= max) {
              return 1;
          } else {
              x = (x - min) / (max - min);
              return x * x * (3 - 2 * x);
          }
      }
  };
  
  mathf.smootherStep = function(x, min, max) {
      if (x <= min) {
          return 0;
      } else {
          if (x >= max) {
              return 1;
          } else {
              x = (x - min) / (max - min);
              return x * x * x * (x * (x * 6 - 15) + 10);
          }
      }
  };
  
  mathf.pingPong = function(x, length) {
      length = +length || 1;
      return length - mathf.abs(x % (2 * length) - length);
  };
  
  mathf.degsToRads = function(x) {
      return mathf.standardRadian(x * mathf.TO_RADS);
  };
  
  mathf.radsToDegs = function(x) {
      return mathf.standardAngle(x * mathf.TO_DEGS);
  };
  
  mathf.randInt = function(min, max) {
      return mathf.round(min + (mathf.random() * (max - min)));
  };
  
  mathf.randFloat = function(min, max) {
      return min + (mathf.random() * (max - min));
  };
  
  mathf.randSign = function() {
      return mathf.random() < 0.5 ? 1 : -1;
  };
  
  mathf.shuffle = function(array) {
      var i = array.length,
          j, x;
  
      while (i) {
          j = (mathf.random() * i--) | 0;
          x = array[i];
          array[i] = array[j];
          array[j] = x;
      }
  
      return array;
  };
  
  mathf.randArg = function() {
      return arguments[(mathf.random() * arguments.length) | 0];
  };
  
  mathf.randChoice = function(array) {
      return array[(mathf.random() * array.length) | 0];
  };
  
  mathf.randChoiceObject = function(object) {
      var objectKeys = keys(object);
      return object[objectKeys[(mathf.random() * objectKeys.length) | 0]];
  };
  
  mathf.isPowerOfTwo = function(x) {
      return (x & -x) === x;
  };
  
  mathf.floorPowerOfTwo = function(x) {
      var i = 2,
          prev;
  
      while (i < x) {
          prev = i;
          i *= 2;
      }
  
      return prev;
  };
  
  mathf.ceilPowerOfTwo = function(x) {
      var i = 2;
  
      while (i < x) {
          i *= 2;
      }
  
      return i;
  };
  
  var n225 = 0.39269908169872414,
      n675 = 1.1780972450961724,
      n1125 = 1.9634954084936207,
      n1575 = 2.748893571891069,
      n2025 = 3.5342917352885173,
      n2475 = 4.319689898685966,
      n2925 = 5.105088062083414,
      n3375 = 5.8904862254808625,
  
      RIGHT = "right",
      UP_RIGHT = "up_right",
      UP = "up",
      UP_LEFT = "up_left",
      LEFT = "left",
      DOWN_LEFT = "down_left",
      DOWN = "down",
      DOWN_RIGHT = "down_right";
  
  mathf.directionAngle = function(a) {
      a = mathf.standardRadian(a);
  
      return (
          (a >= n225 && a < n675) ? UP_RIGHT :
          (a >= n675 && a < n1125) ? UP :
          (a >= n1125 && a < n1575) ? UP_LEFT :
          (a >= n1575 && a < n2025) ? LEFT :
          (a >= n2025 && a < n2475) ? DOWN_LEFT :
          (a >= n2475 && a < n2925) ? DOWN :
          (a >= n2925 && a < n3375) ? DOWN_RIGHT :
          RIGHT
      );
  };
  
  mathf.direction = function(x, y) {
      var a = mathf.standardRadian(mathf.atan2(y, x));
  
      return (
          (a >= n225 && a < n675) ? UP_RIGHT :
          (a >= n675 && a < n1125) ? UP :
          (a >= n1125 && a < n1575) ? UP_LEFT :
          (a >= n1575 && a < n2025) ? LEFT :
          (a >= n2025 && a < n2475) ? DOWN_LEFT :
          (a >= n2475 && a < n2925) ? DOWN :
          (a >= n2925 && a < n3375) ? DOWN_RIGHT :
          RIGHT
      );
  };
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/vec3@0.0.3/src/index.js-=@*/
  var mathf = require(5),
      isNumber = require(7);
  
  
  var vec3 = exports;
  
  
  vec3.ArrayType = typeof(Float32Array) !== "undefined" ? Float32Array : mathf.ArrayType;
  
  
  vec3.create = function(x, y, z) {
      var out = new vec3.ArrayType(3);
  
      out[0] = isNumber(x) ? x : 0;
      out[1] = isNumber(y) ? y : 0;
      out[2] = isNumber(z) ? z : 0;
  
      return out;
  };
  
  vec3.up = vec3.create(0.0, 0.0, 1.0);
  vec3.down = vec3.create(0.0, 0.0, -1.0);
  
  vec3.forward = vec3.create(0.0, 1.0, 0.0);
  vec3.backward = vec3.create(0.0, -1.0, 0.0);
  
  vec3.right = vec3.create(1.0, 0.0, 0.0);
  vec3.left = vec3.create(-1.0, 0.0, 0.0);
  
  vec3.zero = vec3.create(0.0, 0.0, 0.0);
  vec3.one = vec3.create(1.0, 1.0, 1.0);
  
  vec3.copy = function(out, a) {
  
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
  
      return out;
  };
  
  vec3.clone = function(a) {
      var out = new vec3.ArrayType(3);
  
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
  
      return out;
  };
  
  vec3.set = function(out, x, y, z) {
  
      out[0] = isNumber(x) ? x : 0;
      out[1] = isNumber(y) ? y : 0;
      out[2] = isNumber(z) ? z : 0;
  
      return out;
  };
  
  vec3.add = function(out, a, b) {
  
      out[0] = a[0] + b[0];
      out[1] = a[1] + b[1];
      out[2] = a[2] + b[2];
  
      return out;
  };
  
  vec3.sub = function(out, a, b) {
  
      out[0] = a[0] - b[0];
      out[1] = a[1] - b[1];
      out[2] = a[2] - b[2];
  
      return out;
  };
  
  vec3.mul = function(out, a, b) {
  
      out[0] = a[0] * b[0];
      out[1] = a[1] * b[1];
      out[2] = a[2] * b[2];
  
      return out;
  };
  
  vec3.div = function(out, a, b) {
      var bx = b[0],
          by = b[1],
          bz = b[2];
  
      out[0] = a[0] * (bx !== 0 ? 1 / bx : bx);
      out[1] = a[1] * (by !== 0 ? 1 / by : by);
      out[2] = a[2] * (bz !== 0 ? 1 / bz : bz);
  
      return out;
  };
  
  vec3.sadd = function(out, a, s) {
  
      out[0] = a[0] + s;
      out[1] = a[1] + s;
      out[2] = a[2] + s;
  
      return out;
  };
  
  vec3.ssub = function(out, a, s) {
  
      out[0] = a[0] - s;
      out[1] = a[1] - s;
      out[2] = a[2] - s;
  
      return out;
  };
  
  vec3.smul = function(out, a, s) {
  
      out[0] = a[0] * s;
      out[1] = a[1] * s;
      out[2] = a[2] * s;
  
      return out;
  };
  
  vec3.sdiv = function(out, a, s) {
      s = s !== 0 ? 1 / s : s;
  
      out[0] = a[0] * s;
      out[1] = a[1] * s;
      out[2] = a[2] * s;
  
      return out;
  };
  
  vec3.lengthSqValues = function(x, y, z) {
  
      return x * x + y * y + z * z;
  };
  
  vec3.lengthValues = function(x, y, z) {
      var lsq = vec3.lengthSqValues(x, y, z);
  
      return lsq !== 0 ? mathf.sqrt(lsq) : lsq;
  };
  
  vec3.invLengthValues = function(x, y, z) {
      var lsq = vec3.lengthSqValues(x, y, z);
  
      return lsq !== 0 ? 1 / mathf.sqrt(lsq) : lsq;
  };
  
  vec3.cross = function(out, a, b) {
      var ax = a[0],
          ay = a[1],
          az = a[2],
          bx = b[0],
          by = b[1],
          bz = b[2];
  
      out[0] = ay * bz - az * by;
      out[1] = az * bx - ax * bz;
      out[2] = ax * by - ay * bx;
  
      return out;
  };
  
  vec3.dot = function(a, b) {
  
      return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
  };
  
  vec3.lengthSq = function(a) {
  
      return vec3.dot(a, a);
  };
  
  vec3.length = function(a) {
      var lsq = vec3.lengthSq(a);
  
      return lsq !== 0 ? mathf.sqrt(lsq) : lsq;
  };
  
  vec3.invLength = function(a) {
      var lsq = vec3.lengthSq(a);
  
      return lsq !== 0 ? 1 / mathf.sqrt(lsq) : lsq;
  };
  
  vec3.setLength = function(out, a, length) {
      var x = a[0],
          y = a[1],
          z = a[2],
          s = length * vec3.invLengthValues(x, y, z);
  
      out[0] = x * s;
      out[1] = y * s;
      out[2] = z * s;
  
      return out;
  };
  
  vec3.normalize = function(out, a) {
      var x = a[0],
          y = a[1],
          z = a[2],
          invlsq = vec3.invLengthValues(x, y, z);
  
      out[0] = x * invlsq;
      out[1] = y * invlsq;
      out[2] = z * invlsq;
  
      return out;
  };
  
  vec3.inverse = function(out, a) {
  
      out[0] = a[0] * -1;
      out[1] = a[1] * -1;
      out[2] = a[2] * -1;
  
      return out;
  };
  
  vec3.lerp = function(out, a, b, x) {
      var lerp = mathf.lerp;
  
      out[0] = lerp(a[0], b[0], x);
      out[1] = lerp(a[1], b[1], x);
      out[2] = lerp(a[2], b[2], x);
  
      return out;
  };
  
  vec3.min = function(out, a, b) {
      var ax = a[0],
          ay = a[1],
          az = a[2],
          bx = b[0],
          by = b[1],
          bz = b[2];
  
      out[0] = bx < ax ? bx : ax;
      out[1] = by < ay ? by : ay;
      out[2] = bz < az ? bz : az;
  
      return out;
  };
  
  vec3.max = function(out, a, b) {
      var ax = a[0],
          ay = a[1],
          az = a[2],
          bx = b[0],
          by = b[1],
          bz = b[2];
  
      out[0] = bx > ax ? bx : ax;
      out[1] = by > ay ? by : ay;
      out[2] = bz > az ? bz : az;
  
      return out;
  };
  
  vec3.clamp = function(out, a, min, max) {
      var x = a[0],
          y = a[1],
          z = a[2],
          minx = min[0],
          miny = min[1],
          minz = min[2],
          maxx = max[0],
          maxy = max[1],
          maxz = max[2];
  
      out[0] = x < minx ? minx : x > maxx ? maxx : x;
      out[1] = y < miny ? miny : y > maxy ? maxy : y;
      out[2] = z < minz ? minz : z > maxz ? maxz : z;
  
      return out;
  };
  
  vec3.transformMat2 = function(out, a, m) {
      var x = a[0],
          y = a[1],
          z = a[2];
  
      out[0] = x * m[0] + y * m[2];
      out[1] = x * m[1] + y * m[3];
      out[2] = z;
  
      return out;
  };
  
  vec3.transformMat32 = function(out, a, m) {
      var x = a[0],
          y = a[1],
          z = a[2];
  
      out[0] = x * m[0] + y * m[2] + z * m[4];
      out[1] = x * m[1] + y * m[3] + z * m[5];
      out[2] = z;
  
      return out;
  };
  
  vec3.transformMat32Rotation = vec3.transformMat2;
  
  vec3.transformMat3 = function(out, a, m) {
      var x = a[0],
          y = a[1],
          z = a[2];
  
      out[0] = x * m[0] + y * m[3] + z * m[6];
      out[1] = x * m[1] + y * m[4] + z * m[7];
      out[2] = x * m[2] + y * m[5] + z * m[8];
  
      return out;
  };
  
  vec3.transformMat4 = function(out, a, m) {
      var x = a[0],
          y = a[1],
          z = a[2];
  
      out[0] = x * m[0] + y * m[4] + z * m[8] + m[12];
      out[1] = x * m[1] + y * m[5] + z * m[9] + m[13];
      out[2] = x * m[2] + y * m[6] + z * m[10] + m[14];
  
      return out;
  };
  
  vec3.transformMat4Rotation = function(out, a, m) {
      var x = a[0],
          y = a[1],
          z = a[2];
  
      out[0] = x * m[0] + y * m[4] + z * m[8];
      out[1] = x * m[1] + y * m[5] + z * m[9];
      out[2] = x * m[2] + y * m[6] + z * m[10];
  
      return out;
  };
  
  vec3.transformProjection = function(out, a, m) {
      var x = a[0],
          y = a[1],
          z = a[2],
          d = x * m[3] + y * m[7] + z * m[11] + m[15];
  
      d = d !== 0 ? 1 / d : d;
  
      out[0] = (x * m[0] + y * m[4] + z * m[8] + m[12]) * d;
      out[1] = (x * m[1] + y * m[5] + z * m[9] + m[13]) * d;
      out[2] = (x * m[2] + y * m[6] + z * m[10] + m[14]) * d;
  
      return out;
  };
  
  vec3.transformProjectionNoPosition = function(out, a, m) {
      var x = a[0],
          y = a[1],
          z = a[2],
          d = x * m[3] + y * m[7] + z * m[11] + m[15];
  
      d = d !== 0 ? 1 / d : d;
  
      out[0] = (x * m[0] + y * m[4] + z * m[8]) * d;
      out[1] = (x * m[1] + y * m[5] + z * m[9]) * d;
      out[2] = (x * m[2] + y * m[6] + z * m[10]) * d;
  
      return out;
  };
  
  vec3.transformQuat = function(out, a, q) {
      var x = a[0],
          y = a[1],
          z = a[2],
          qx = q[0],
          qy = q[1],
          qz = q[2],
          qw = q[3],
  
          ix = qw * x + qy * z - qz * y,
          iy = qw * y + qz * x - qx * z,
          iz = qw * z + qx * y - qy * x,
          iw = -qx * x - qy * y - qz * z;
  
      out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
      out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
      out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
  
      return out;
  };
  
  vec3.positionFromMat4 = function(out, m) {
  
      out[0] = m[12];
      out[1] = m[13];
      out[2] = m[14];
  
      return out;
  };
  
  vec3.scaleFromMat2 = function(out, m) {
  
      out[0] = vec3.lengthValues(m[0], m[2], 0);
      out[1] = vec3.lengthValues(m[1], m[3], 0);
      out[2] = vec3.lengthValues(0, 0, 1);
  
      return out;
  };
  
  vec3.scaleFromMat32 = function(out, m) {
  
      out[0] = vec3.lengthValues(m[0], m[2], 0);
      out[1] = vec3.lengthValues(m[1], m[3], 0);
      out[2] = vec3.lengthValues(0, 0, 1);
  
      return out;
  };
  
  vec3.scaleFromMat3 = function(out, m) {
  
      out[0] = vec3.lengthValues(m[0], m[3], m[6]);
      out[1] = vec3.lengthValues(m[1], m[4], m[7]);
      out[2] = vec3.lengthValues(m[2], m[5], m[8]);
  
      return out;
  };
  
  vec3.scaleFromMat4 = function(out, m) {
  
      out[0] = vec3.lengthValues(m[0], m[4], m[8]);
      out[1] = vec3.lengthValues(m[1], m[5], m[9]);
      out[2] = vec3.lengthValues(m[2], m[6], m[10]);
  
      return out;
  };
  
  vec3.equals = function(a, b) {
      return !vec3.notEquals(a, b);
  };
  
  vec3.notEquals = function(a, b) {
      return !(
          mathf.equals(a[0], b[0]) ||
          mathf.equals(a[1], b[1]) ||
          mathf.equals(a[2], b[2])
      );
  };
  
  vec3.str = function(out) {
      return "Vec3(" + out[0] + ", " + out[1] + ", " + out[2] + ")";
  };
  
  vec3.string = vec3.toString = vec3.str;
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/is_number@0.0.1/src/index.js-=@*/
  module.exports = isNumber;
  
  
  function isNumber(value) {
      return typeof(value) === "number" || false;
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/keys@0.0.2/src/index.js-=@*/
  var has = require(11),
      isNative = require(12),
      isNullOrUndefined = require(13),
      isObject = require(14);
  
  
  var nativeKeys = Object.keys;
  
  
  module.exports = keys;
  
  
  function keys(value) {
      if (isNullOrUndefined(value)) {
          return [];
      } else {
          return nativeKeys(isObject(value) ? value : Object(value));
      }
  }
  
  if (!isNative(nativeKeys)) {
      nativeKeys = function keys(value) {
          var localHas = has,
              out = [],
              i = 0,
              key;
  
          for (key in value) {
              if (localHas(value, key)) {
                  out[i++] = key;
              }
          }
  
          return out;
      };
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/clamp@0.0.1/src/index.js-=@*/
  module.exports = clamp;
  
  
  function clamp(x, min, max) {
      if (x < min) {
          return min;
      } else if (x > max) {
          return max;
      } else {
          return x;
      }
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/is_nan@0.0.2/src/index.js-=@*/
  var isNumber = require(7);
  
  
  module.exports = Number.isNaN || function isNaN(value) {
      return isNumber(value) && value !== value;
  };
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/has@0.0.2/src/index.js-=@*/
  var isNative = require(12),
      getPrototypeOf = require(15),
      isNullOrUndefined = require(13);
  
  
  var nativeHasOwnProp = Object.prototype.hasOwnProperty,
      baseHas;
  
  
  module.exports = has;
  
  
  function has(object, key) {
      if (isNullOrUndefined(object)) {
          return false;
      } else {
          return baseHas(object, key);
      }
  }
  
  if (isNative(nativeHasOwnProp)) {
      baseHas = function baseHas(object, key) {
          if (object.hasOwnProperty) {
              return object.hasOwnProperty(key);
          } else {
              return nativeHasOwnProp.call(object, key);
          }
      };
  } else {
      baseHas = function baseHas(object, key) {
          var proto = getPrototypeOf(object);
  
          if (isNullOrUndefined(proto)) {
              return key in object;
          } else {
              return (key in object) && (!(key in proto) || proto[key] !== object[key]);
          }
      };
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/is_native@0.0.2/src/index.js-=@*/
  var isFunction = require(16),
      isNullOrUndefined = require(13),
      escapeRegExp = require(17);
  
  
  var reHostCtor = /^\[object .+?Constructor\]$/,
  
      functionToString = Function.prototype.toString,
  
      reNative = RegExp("^" +
          escapeRegExp(Object.prototype.toString)
          .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"
      ),
  
      isHostObject;
  
  
  module.exports = isNative;
  
  
  function isNative(value) {
      return !isNullOrUndefined(value) && (
          isFunction(value) ?
          reNative.test(functionToString.call(value)) : (
              typeof(value) === "object" && (
                  (isHostObject(value) ? reNative : reHostCtor).test(value) || false
              )
          )
      ) || false;
  }
  
  try {
      String({
          "toString": 0
      } + "");
  } catch (e) {
      isHostObject = function isHostObject() {
          return false;
      };
  }
  
  isHostObject = function isHostObject(value) {
      return !isFunction(value.toString) && typeof(value + "") === "string";
  };
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/is_null_or_undefined@0.0.1/src/index.js-=@*/
  var isNull = require(18),
      isUndefined = require(19);
  
  
  module.exports = isNullOrUndefined;
  
  /**
    isNullOrUndefined accepts any value and returns true
    if the value is null or undefined. For all other values
    false is returned.
    
    @param {Any}        any value to test
    @returns {Boolean}  the boolean result of testing value
  
    @example
      isNullOrUndefined(null);   // returns true
      isNullOrUndefined(undefined);   // returns true
      isNullOrUndefined("string");    // returns false
  **/
  function isNullOrUndefined(value) {
      return isNull(value) || isUndefined(value);
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/is_object@0.0.1/src/index.js-=@*/
  var isNull = require(18);
  
  
  module.exports = isObject;
  
  
  function isObject(value) {
      var type = typeof(value);
      return type === "function" || (!isNull(value) && type === "object") || false;
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/get_prototype_of@0.0.1/src/index.js-=@*/
  var isObject = require(14),
      isNative = require(12),
      isNullOrUndefined = require(13);
  
  
  var nativeGetPrototypeOf = Object.getPrototypeOf,
      baseGetPrototypeOf;
  
  
  module.exports = getPrototypeOf;
  
  
  function getPrototypeOf(value) {
      if (isNullOrUndefined(value)) {
          return null;
      } else {
          return baseGetPrototypeOf(value);
      }
  }
  
  if (isNative(nativeGetPrototypeOf)) {
      baseGetPrototypeOf = function baseGetPrototypeOf(value) {
          return nativeGetPrototypeOf(isObject(value) ? value : Object(value)) || null;
      };
  } else {
      if ("".__proto__ === String.prototype) {
          baseGetPrototypeOf = function baseGetPrototypeOf(value) {
              return value.__proto__ || null;
          };
      } else {
          baseGetPrototypeOf = function baseGetPrototypeOf(value) {
              return value.constructor ? value.constructor.prototype : null;
          };
      }
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/is_function@0.0.1/src/index.js-=@*/
  var objectToString = Object.prototype.toString,
      isFunction;
  
  
  if (objectToString.call(function() {}) === "[object Object]") {
      isFunction = function isFunction(value) {
          return value instanceof Function;
      };
  } else if (typeof(/./) === "function" || (typeof(Uint8Array) !== "undefined" && typeof(Uint8Array) !== "function")) {
      isFunction = function isFunction(value) {
          return objectToString.call(value) === "[object Function]";
      };
  } else {
      isFunction = function isFunction(value) {
          return typeof(value) === "function" || false;
      };
  }
  
  
  module.exports = isFunction;
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/escape_regexp@0.0.1/src/index.js-=@*/
  var toString = require(20);
  
  
  var reRegExpChars = /[.*+?\^${}()|\[\]\/\\]/g,
      reHasRegExpChars = new RegExp(reRegExpChars.source);
  
  
  module.exports = escapeRegExp;
  
  
  function escapeRegExp(string) {
      string = toString(string);
      return (
          (string && reHasRegExpChars.test(string)) ?
          string.replace(reRegExpChars, "\\$&") :
          string
      );
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/is_null@0.0.1/src/index.js-=@*/
  module.exports = isNull;
  
  
  function isNull(value) {
      return value === null;
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/is_undefined@0.0.1/src/index.js-=@*/
  module.exports = isUndefined;
  
  
  function isUndefined(value) {
      return value === void(0);
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/to_string@0.0.1/src/index.js-=@*/
  var isString = require(21),
      isNullOrUndefined = require(13);
  
  
  module.exports = toString;
  
  
  function toString(value) {
      if (isString(value)) {
          return value;
      } else if (isNullOrUndefined(value)) {
          return "";
      } else {
          return value + "";
      }
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/is_string@0.0.1/src/index.js-=@*/
  module.exports = isString;
  
  
  function isString(value) {
      return typeof(value) === "string" || false;
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/environment@0.0.2/src/index.js-=@*/
  var Buffer = require(25).Buffer;
  var process = require(26);
  var environment = exports,
  
      hasWindow = typeof(window) !== "undefined",
      userAgent = hasWindow ? window.navigator.userAgent : "";
  
  
  environment.worker = typeof(importScripts) !== "undefined";
  
  environment.browser = environment.worker || !!(
      hasWindow &&
      typeof(navigator) !== "undefined" &&
      window.document
  );
  
  environment.node = (!hasWindow &&
      typeof(process) !== "undefined" &&
      typeof(process.versions) !== "undefined" &&
      typeof(process.versions.node) !== "undefined" &&
      typeof(Buffer) !== "undefined"
  );
  
  environment.mobile = environment.browser && /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent.toLowerCase());
  
  environment.window = (
      hasWindow ? window :
      typeof(global) !== "undefined" ? global :
      typeof(self) !== "undefined" ? self : {}
  );
  
  environment.pixelRatio = environment.window.devicePixelRatio || 1;
  
  environment.document = typeof(document) !== "undefined" ? document : {};
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/empty_function@0.0.1/src/index.js-=@*/
  module.exports = emptyFunction;
  
  
  function emptyFunction() {}
  
  function makeEmptyFunction(value) {
      return function() {
          return value;
      };
  }
  
  emptyFunction.thatReturns = makeEmptyFunction;
  emptyFunction.thatReturnsFalse = makeEmptyFunction(false);
  emptyFunction.thatReturnsTrue = makeEmptyFunction(true);
  emptyFunction.thatReturnsNull = makeEmptyFunction(null);
  emptyFunction.thatReturnsThis = function() {
      return this;
  };
  emptyFunction.thatReturnsArgument = function(argument) {
      return argument;
  };
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/now@0.0.3/src/browser.js-=@*/
  var Date_now = Date.now || function Date_now() {
          return (new Date()).getTime();
      },
      START_TIME = Date_now(),
      performance = global.performance || {};
  
  
  function now() {
      return performance.now();
  }
  
  performance.now = (
      performance.now ||
      performance.webkitNow ||
      performance.mozNow ||
      performance.msNow ||
      performance.oNow ||
      function now() {
          return Date_now() - START_TIME;
      }
  );
  
  now.getStartTime = function getStartTime() {
      return START_TIME;
  };
  
  now.stamp = function stamp() {
      return START_TIME + now();
  };
  
  now.hrtime = function hrtime(previousTimestamp) {
      var clocktime = now() * 1e-3,
          seconds = Math.floor(clocktime),
          nanoseconds = Math.floor((clocktime % 1) * 1e9);
  
      if (previousTimestamp) {
          seconds = seconds - previousTimestamp[0];
          nanoseconds = nanoseconds - previousTimestamp[1];
  
          if (nanoseconds < 0) {
              seconds--;
              nanoseconds += 1e9;
          }
      }
  
      return [seconds, nanoseconds];
  };
  
  
  START_TIME -= now();
  
  
  module.exports = now;
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-buffer@3.6.0/index.js-=@*/
  /*!
   * The buffer module from node.js, for the browser.
   *
   * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
   * @license  MIT
   */
  /* eslint-disable no-proto */
  
  'use strict'
  
  var base64 = require(27)
  var ieee754 = require(28)
  var isArray = require(29)
  
  exports.Buffer = Buffer
  exports.SlowBuffer = SlowBuffer
  exports.INSPECT_MAX_BYTES = 50
  Buffer.poolSize = 8192 // not used by this implementation
  
  var rootParent = {}
  
  /**
   * If `Buffer.TYPED_ARRAY_SUPPORT`:
   *   === true    Use Uint8Array implementation (fastest)
   *   === false   Use Object implementation (most compatible, even IE6)
   *
   * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
   * Opera 11.6+, iOS 4.2+.
   *
   * Due to various browser bugs, sometimes the Object implementation will be used even
   * when the browser supports typed arrays.
   *
   * Note:
   *
   *   - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
   *     See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
   *
   *   - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property
   *     on objects.
   *
   *   - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
   *
   *   - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
   *     incorrect length in some situations.
  
   * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
   * get the Object implementation, which is slower but behaves correctly.
   */
  Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
    ? global.TYPED_ARRAY_SUPPORT
    : typedArraySupport()
  
  function typedArraySupport () {
    function Bar () {}
    try {
      var arr = new Uint8Array(1)
      arr.foo = function () { return 42 }
      arr.constructor = Bar
      return arr.foo() === 42 && // typed array instances can be augmented
          arr.constructor === Bar && // constructor can be set
          typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
          arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
    } catch (e) {
      return false
    }
  }
  
  function kMaxLength () {
    return Buffer.TYPED_ARRAY_SUPPORT
      ? 0x7fffffff
      : 0x3fffffff
  }
  
  /**
   * Class: Buffer
   * =============
   *
   * The Buffer constructor returns instances of `Uint8Array` that are augmented
   * with function properties for all the node `Buffer` API functions. We use
   * `Uint8Array` so that square bracket notation works as expected -- it returns
   * a single octet.
   *
   * By augmenting the instances, we can avoid modifying the `Uint8Array`
   * prototype.
   */
  function Buffer (arg) {
    if (!(this instanceof Buffer)) {
      // Avoid going through an ArgumentsAdaptorTrampoline in the common case.
      if (arguments.length > 1) return new Buffer(arg, arguments[1])
      return new Buffer(arg)
    }
  
    if (!Buffer.TYPED_ARRAY_SUPPORT) {
      this.length = 0
      this.parent = undefined
    }
  
    // Common case.
    if (typeof arg === 'number') {
      return fromNumber(this, arg)
    }
  
    // Slightly less common case.
    if (typeof arg === 'string') {
      return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8')
    }
  
    // Unusual.
    return fromObject(this, arg)
  }
  
  function fromNumber (that, length) {
    that = allocate(that, length < 0 ? 0 : checked(length) | 0)
    if (!Buffer.TYPED_ARRAY_SUPPORT) {
      for (var i = 0; i < length; i++) {
        that[i] = 0
      }
    }
    return that
  }
  
  function fromString (that, string, encoding) {
    if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8'
  
    // Assumption: byteLength() return value is always < kMaxLength.
    var length = byteLength(string, encoding) | 0
    that = allocate(that, length)
  
    that.write(string, encoding)
    return that
  }
  
  function fromObject (that, object) {
    if (Buffer.isBuffer(object)) return fromBuffer(that, object)
  
    if (isArray(object)) return fromArray(that, object)
  
    if (object == null) {
      throw new TypeError('must start with number, buffer, array or string')
    }
  
    if (typeof ArrayBuffer !== 'undefined') {
      if (object.buffer instanceof ArrayBuffer) {
        return fromTypedArray(that, object)
      }
      if (object instanceof ArrayBuffer) {
        return fromArrayBuffer(that, object)
      }
    }
  
    if (object.length) return fromArrayLike(that, object)
  
    return fromJsonObject(that, object)
  }
  
  function fromBuffer (that, buffer) {
    var length = checked(buffer.length) | 0
    that = allocate(that, length)
    buffer.copy(that, 0, 0, length)
    return that
  }
  
  function fromArray (that, array) {
    var length = checked(array.length) | 0
    that = allocate(that, length)
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  // Duplicate of fromArray() to keep fromArray() monomorphic.
  function fromTypedArray (that, array) {
    var length = checked(array.length) | 0
    that = allocate(that, length)
    // Truncating the elements is probably not what people expect from typed
    // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior
    // of the old Buffer constructor.
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  function fromArrayBuffer (that, array) {
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      // Return an augmented `Uint8Array` instance, for best performance
      array.byteLength
      that = Buffer._augment(new Uint8Array(array))
    } else {
      // Fallback: Return an object instance of the Buffer class
      that = fromTypedArray(that, new Uint8Array(array))
    }
    return that
  }
  
  function fromArrayLike (that, array) {
    var length = checked(array.length) | 0
    that = allocate(that, length)
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  // Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object.
  // Returns a zero-length buffer for inputs that don't conform to the spec.
  function fromJsonObject (that, object) {
    var array
    var length = 0
  
    if (object.type === 'Buffer' && isArray(object.data)) {
      array = object.data
      length = checked(array.length) | 0
    }
    that = allocate(that, length)
  
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    Buffer.prototype.__proto__ = Uint8Array.prototype
    Buffer.__proto__ = Uint8Array
  } else {
    // pre-set for values that may exist in the future
    Buffer.prototype.length = undefined
    Buffer.prototype.parent = undefined
  }
  
  function allocate (that, length) {
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      // Return an augmented `Uint8Array` instance, for best performance
      that = Buffer._augment(new Uint8Array(length))
      that.__proto__ = Buffer.prototype
    } else {
      // Fallback: Return an object instance of the Buffer class
      that.length = length
      that._isBuffer = true
    }
  
    var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1
    if (fromPool) that.parent = rootParent
  
    return that
  }
  
  function checked (length) {
    // Note: cannot use `length < kMaxLength` here because that fails when
    // length is NaN (which is otherwise coerced to zero.)
    if (length >= kMaxLength()) {
      throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
                           'size: 0x' + kMaxLength().toString(16) + ' bytes')
    }
    return length | 0
  }
  
  function SlowBuffer (subject, encoding) {
    if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding)
  
    var buf = new Buffer(subject, encoding)
    delete buf.parent
    return buf
  }
  
  Buffer.isBuffer = function isBuffer (b) {
    return !!(b != null && b._isBuffer)
  }
  
  Buffer.compare = function compare (a, b) {
    if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
      throw new TypeError('Arguments must be Buffers')
    }
  
    if (a === b) return 0
  
    var x = a.length
    var y = b.length
  
    var i = 0
    var len = Math.min(x, y)
    while (i < len) {
      if (a[i] !== b[i]) break
  
      ++i
    }
  
    if (i !== len) {
      x = a[i]
      y = b[i]
    }
  
    if (x < y) return -1
    if (y < x) return 1
    return 0
  }
  
  Buffer.isEncoding = function isEncoding (encoding) {
    switch (String(encoding).toLowerCase()) {
      case 'hex':
      case 'utf8':
      case 'utf-8':
      case 'ascii':
      case 'binary':
      case 'base64':
      case 'raw':
      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        return true
      default:
        return false
    }
  }
  
  Buffer.concat = function concat (list, length) {
    if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.')
  
    if (list.length === 0) {
      return new Buffer(0)
    }
  
    var i
    if (length === undefined) {
      length = 0
      for (i = 0; i < list.length; i++) {
        length += list[i].length
      }
    }
  
    var buf = new Buffer(length)
    var pos = 0
    for (i = 0; i < list.length; i++) {
      var item = list[i]
      item.copy(buf, pos)
      pos += item.length
    }
    return buf
  }
  
  function byteLength (string, encoding) {
    if (typeof string !== 'string') string = '' + string
  
    var len = string.length
    if (len === 0) return 0
  
    // Use a for loop to avoid recursion
    var loweredCase = false
    for (;;) {
      switch (encoding) {
        case 'ascii':
        case 'binary':
        // Deprecated
        case 'raw':
        case 'raws':
          return len
        case 'utf8':
        case 'utf-8':
          return utf8ToBytes(string).length
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return len * 2
        case 'hex':
          return len >>> 1
        case 'base64':
          return base64ToBytes(string).length
        default:
          if (loweredCase) return utf8ToBytes(string).length // assume utf8
          encoding = ('' + encoding).toLowerCase()
          loweredCase = true
      }
    }
  }
  Buffer.byteLength = byteLength
  
  function slowToString (encoding, start, end) {
    var loweredCase = false
  
    start = start | 0
    end = end === undefined || end === Infinity ? this.length : end | 0
  
    if (!encoding) encoding = 'utf8'
    if (start < 0) start = 0
    if (end > this.length) end = this.length
    if (end <= start) return ''
  
    while (true) {
      switch (encoding) {
        case 'hex':
          return hexSlice(this, start, end)
  
        case 'utf8':
        case 'utf-8':
          return utf8Slice(this, start, end)
  
        case 'ascii':
          return asciiSlice(this, start, end)
  
        case 'binary':
          return binarySlice(this, start, end)
  
        case 'base64':
          return base64Slice(this, start, end)
  
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return utf16leSlice(this, start, end)
  
        default:
          if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
          encoding = (encoding + '').toLowerCase()
          loweredCase = true
      }
    }
  }
  
  Buffer.prototype.toString = function toString () {
    var length = this.length | 0
    if (length === 0) return ''
    if (arguments.length === 0) return utf8Slice(this, 0, length)
    return slowToString.apply(this, arguments)
  }
  
  Buffer.prototype.equals = function equals (b) {
    if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
    if (this === b) return true
    return Buffer.compare(this, b) === 0
  }
  
  Buffer.prototype.inspect = function inspect () {
    var str = ''
    var max = exports.INSPECT_MAX_BYTES
    if (this.length > 0) {
      str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
      if (this.length > max) str += ' ... '
    }
    return '<Buffer ' + str + '>'
  }
  
  Buffer.prototype.compare = function compare (b) {
    if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
    if (this === b) return 0
    return Buffer.compare(this, b)
  }
  
  Buffer.prototype.indexOf = function indexOf (val, byteOffset) {
    if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff
    else if (byteOffset < -0x80000000) byteOffset = -0x80000000
    byteOffset >>= 0
  
    if (this.length === 0) return -1
    if (byteOffset >= this.length) return -1
  
    // Negative offsets start from the end of the buffer
    if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0)
  
    if (typeof val === 'string') {
      if (val.length === 0) return -1 // special case: looking for empty string always fails
      return String.prototype.indexOf.call(this, val, byteOffset)
    }
    if (Buffer.isBuffer(val)) {
      return arrayIndexOf(this, val, byteOffset)
    }
    if (typeof val === 'number') {
      if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') {
        return Uint8Array.prototype.indexOf.call(this, val, byteOffset)
      }
      return arrayIndexOf(this, [ val ], byteOffset)
    }
  
    function arrayIndexOf (arr, val, byteOffset) {
      var foundIndex = -1
      for (var i = 0; byteOffset + i < arr.length; i++) {
        if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) {
          if (foundIndex === -1) foundIndex = i
          if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex
        } else {
          foundIndex = -1
        }
      }
      return -1
    }
  
    throw new TypeError('val must be string, number or Buffer')
  }
  
  // `get` is deprecated
  Buffer.prototype.get = function get (offset) {
    console.log('.get() is deprecated. Access using array indexes instead.')
    return this.readUInt8(offset)
  }
  
  // `set` is deprecated
  Buffer.prototype.set = function set (v, offset) {
    console.log('.set() is deprecated. Access using array indexes instead.')
    return this.writeUInt8(v, offset)
  }
  
  function hexWrite (buf, string, offset, length) {
    offset = Number(offset) || 0
    var remaining = buf.length - offset
    if (!length) {
      length = remaining
    } else {
      length = Number(length)
      if (length > remaining) {
        length = remaining
      }
    }
  
    // must be an even number of digits
    var strLen = string.length
    if (strLen % 2 !== 0) throw new Error('Invalid hex string')
  
    if (length > strLen / 2) {
      length = strLen / 2
    }
    for (var i = 0; i < length; i++) {
      var parsed = parseInt(string.substr(i * 2, 2), 16)
      if (isNaN(parsed)) throw new Error('Invalid hex string')
      buf[offset + i] = parsed
    }
    return i
  }
  
  function utf8Write (buf, string, offset, length) {
    return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
  }
  
  function asciiWrite (buf, string, offset, length) {
    return blitBuffer(asciiToBytes(string), buf, offset, length)
  }
  
  function binaryWrite (buf, string, offset, length) {
    return asciiWrite(buf, string, offset, length)
  }
  
  function base64Write (buf, string, offset, length) {
    return blitBuffer(base64ToBytes(string), buf, offset, length)
  }
  
  function ucs2Write (buf, string, offset, length) {
    return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
  }
  
  Buffer.prototype.write = function write (string, offset, length, encoding) {
    // Buffer#write(string)
    if (offset === undefined) {
      encoding = 'utf8'
      length = this.length
      offset = 0
    // Buffer#write(string, encoding)
    } else if (length === undefined && typeof offset === 'string') {
      encoding = offset
      length = this.length
      offset = 0
    // Buffer#write(string, offset[, length][, encoding])
    } else if (isFinite(offset)) {
      offset = offset | 0
      if (isFinite(length)) {
        length = length | 0
        if (encoding === undefined) encoding = 'utf8'
      } else {
        encoding = length
        length = undefined
      }
    // legacy write(string, encoding, offset, length) - remove in v0.13
    } else {
      var swap = encoding
      encoding = offset
      offset = length | 0
      length = swap
    }
  
    var remaining = this.length - offset
    if (length === undefined || length > remaining) length = remaining
  
    if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
      throw new RangeError('attempt to write outside buffer bounds')
    }
  
    if (!encoding) encoding = 'utf8'
  
    var loweredCase = false
    for (;;) {
      switch (encoding) {
        case 'hex':
          return hexWrite(this, string, offset, length)
  
        case 'utf8':
        case 'utf-8':
          return utf8Write(this, string, offset, length)
  
        case 'ascii':
          return asciiWrite(this, string, offset, length)
  
        case 'binary':
          return binaryWrite(this, string, offset, length)
  
        case 'base64':
          // Warning: maxLength not taken into account in base64Write
          return base64Write(this, string, offset, length)
  
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return ucs2Write(this, string, offset, length)
  
        default:
          if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
          encoding = ('' + encoding).toLowerCase()
          loweredCase = true
      }
    }
  }
  
  Buffer.prototype.toJSON = function toJSON () {
    return {
      type: 'Buffer',
      data: Array.prototype.slice.call(this._arr || this, 0)
    }
  }
  
  function base64Slice (buf, start, end) {
    if (start === 0 && end === buf.length) {
      return base64.fromByteArray(buf)
    } else {
      return base64.fromByteArray(buf.slice(start, end))
    }
  }
  
  function utf8Slice (buf, start, end) {
    end = Math.min(buf.length, end)
    var res = []
  
    var i = start
    while (i < end) {
      var firstByte = buf[i]
      var codePoint = null
      var bytesPerSequence = (firstByte > 0xEF) ? 4
        : (firstByte > 0xDF) ? 3
        : (firstByte > 0xBF) ? 2
        : 1
  
      if (i + bytesPerSequence <= end) {
        var secondByte, thirdByte, fourthByte, tempCodePoint
  
        switch (bytesPerSequence) {
          case 1:
            if (firstByte < 0x80) {
              codePoint = firstByte
            }
            break
          case 2:
            secondByte = buf[i + 1]
            if ((secondByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
              if (tempCodePoint > 0x7F) {
                codePoint = tempCodePoint
              }
            }
            break
          case 3:
            secondByte = buf[i + 1]
            thirdByte = buf[i + 2]
            if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
              if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
                codePoint = tempCodePoint
              }
            }
            break
          case 4:
            secondByte = buf[i + 1]
            thirdByte = buf[i + 2]
            fourthByte = buf[i + 3]
            if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
              if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
                codePoint = tempCodePoint
              }
            }
        }
      }
  
      if (codePoint === null) {
        // we did not generate a valid codePoint so insert a
        // replacement char (U+FFFD) and advance only 1 byte
        codePoint = 0xFFFD
        bytesPerSequence = 1
      } else if (codePoint > 0xFFFF) {
        // encode to utf16 (surrogate pair dance)
        codePoint -= 0x10000
        res.push(codePoint >>> 10 & 0x3FF | 0xD800)
        codePoint = 0xDC00 | codePoint & 0x3FF
      }
  
      res.push(codePoint)
      i += bytesPerSequence
    }
  
    return decodeCodePointsArray(res)
  }
  
  // Based on http://stackoverflow.com/a/22747272/680742, the browser with
  // the lowest limit is Chrome, with 0x10000 args.
  // We go 1 magnitude less, for safety
  var MAX_ARGUMENTS_LENGTH = 0x1000
  
  function decodeCodePointsArray (codePoints) {
    var len = codePoints.length
    if (len <= MAX_ARGUMENTS_LENGTH) {
      return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
    }
  
    // Decode in chunks to avoid "call stack size exceeded".
    var res = ''
    var i = 0
    while (i < len) {
      res += String.fromCharCode.apply(
        String,
        codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
      )
    }
    return res
  }
  
  function asciiSlice (buf, start, end) {
    var ret = ''
    end = Math.min(buf.length, end)
  
    for (var i = start; i < end; i++) {
      ret += String.fromCharCode(buf[i] & 0x7F)
    }
    return ret
  }
  
  function binarySlice (buf, start, end) {
    var ret = ''
    end = Math.min(buf.length, end)
  
    for (var i = start; i < end; i++) {
      ret += String.fromCharCode(buf[i])
    }
    return ret
  }
  
  function hexSlice (buf, start, end) {
    var len = buf.length
  
    if (!start || start < 0) start = 0
    if (!end || end < 0 || end > len) end = len
  
    var out = ''
    for (var i = start; i < end; i++) {
      out += toHex(buf[i])
    }
    return out
  }
  
  function utf16leSlice (buf, start, end) {
    var bytes = buf.slice(start, end)
    var res = ''
    for (var i = 0; i < bytes.length; i += 2) {
      res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
    }
    return res
  }
  
  Buffer.prototype.slice = function slice (start, end) {
    var len = this.length
    start = ~~start
    end = end === undefined ? len : ~~end
  
    if (start < 0) {
      start += len
      if (start < 0) start = 0
    } else if (start > len) {
      start = len
    }
  
    if (end < 0) {
      end += len
      if (end < 0) end = 0
    } else if (end > len) {
      end = len
    }
  
    if (end < start) end = start
  
    var newBuf
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      newBuf = Buffer._augment(this.subarray(start, end))
    } else {
      var sliceLen = end - start
      newBuf = new Buffer(sliceLen, undefined)
      for (var i = 0; i < sliceLen; i++) {
        newBuf[i] = this[i + start]
      }
    }
  
    if (newBuf.length) newBuf.parent = this.parent || this
  
    return newBuf
  }
  
  /*
   * Need to make sure that buffer isn't trying to write out of bounds.
   */
  function checkOffset (offset, ext, length) {
    if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
    if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
  }
  
  Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var val = this[offset]
    var mul = 1
    var i = 0
    while (++i < byteLength && (mul *= 0x100)) {
      val += this[offset + i] * mul
    }
  
    return val
  }
  
  Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) {
      checkOffset(offset, byteLength, this.length)
    }
  
    var val = this[offset + --byteLength]
    var mul = 1
    while (byteLength > 0 && (mul *= 0x100)) {
      val += this[offset + --byteLength] * mul
    }
  
    return val
  }
  
  Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 1, this.length)
    return this[offset]
  }
  
  Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    return this[offset] | (this[offset + 1] << 8)
  }
  
  Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    return (this[offset] << 8) | this[offset + 1]
  }
  
  Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return ((this[offset]) |
        (this[offset + 1] << 8) |
        (this[offset + 2] << 16)) +
        (this[offset + 3] * 0x1000000)
  }
  
  Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset] * 0x1000000) +
      ((this[offset + 1] << 16) |
      (this[offset + 2] << 8) |
      this[offset + 3])
  }
  
  Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var val = this[offset]
    var mul = 1
    var i = 0
    while (++i < byteLength && (mul *= 0x100)) {
      val += this[offset + i] * mul
    }
    mul *= 0x80
  
    if (val >= mul) val -= Math.pow(2, 8 * byteLength)
  
    return val
  }
  
  Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var i = byteLength
    var mul = 1
    var val = this[offset + --i]
    while (i > 0 && (mul *= 0x100)) {
      val += this[offset + --i] * mul
    }
    mul *= 0x80
  
    if (val >= mul) val -= Math.pow(2, 8 * byteLength)
  
    return val
  }
  
  Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 1, this.length)
    if (!(this[offset] & 0x80)) return (this[offset])
    return ((0xff - this[offset] + 1) * -1)
  }
  
  Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    var val = this[offset] | (this[offset + 1] << 8)
    return (val & 0x8000) ? val | 0xFFFF0000 : val
  }
  
  Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    var val = this[offset + 1] | (this[offset] << 8)
    return (val & 0x8000) ? val | 0xFFFF0000 : val
  }
  
  Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset]) |
      (this[offset + 1] << 8) |
      (this[offset + 2] << 16) |
      (this[offset + 3] << 24)
  }
  
  Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset] << 24) |
      (this[offset + 1] << 16) |
      (this[offset + 2] << 8) |
      (this[offset + 3])
  }
  
  Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
    return ieee754.read(this, offset, true, 23, 4)
  }
  
  Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
    return ieee754.read(this, offset, false, 23, 4)
  }
  
  Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 8, this.length)
    return ieee754.read(this, offset, true, 52, 8)
  }
  
  Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 8, this.length)
    return ieee754.read(this, offset, false, 52, 8)
  }
  
  function checkInt (buf, value, offset, ext, max, min) {
    if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')
    if (value > max || value < min) throw new RangeError('value is out of bounds')
    if (offset + ext > buf.length) throw new RangeError('index out of range')
  }
  
  Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
  
    var mul = 1
    var i = 0
    this[offset] = value & 0xFF
    while (++i < byteLength && (mul *= 0x100)) {
      this[offset + i] = (value / mul) & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
  
    var i = byteLength - 1
    var mul = 1
    this[offset + i] = value & 0xFF
    while (--i >= 0 && (mul *= 0x100)) {
      this[offset + i] = (value / mul) & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
    if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
    this[offset] = (value & 0xff)
    return offset + 1
  }
  
  function objectWriteUInt16 (buf, value, offset, littleEndian) {
    if (value < 0) value = 0xffff + value + 1
    for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {
      buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
        (littleEndian ? i : 1 - i) * 8
    }
  }
  
  Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value & 0xff)
      this[offset + 1] = (value >>> 8)
    } else {
      objectWriteUInt16(this, value, offset, true)
    }
    return offset + 2
  }
  
  Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 8)
      this[offset + 1] = (value & 0xff)
    } else {
      objectWriteUInt16(this, value, offset, false)
    }
    return offset + 2
  }
  
  function objectWriteUInt32 (buf, value, offset, littleEndian) {
    if (value < 0) value = 0xffffffff + value + 1
    for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {
      buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
    }
  }
  
  Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset + 3] = (value >>> 24)
      this[offset + 2] = (value >>> 16)
      this[offset + 1] = (value >>> 8)
      this[offset] = (value & 0xff)
    } else {
      objectWriteUInt32(this, value, offset, true)
    }
    return offset + 4
  }
  
  Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 24)
      this[offset + 1] = (value >>> 16)
      this[offset + 2] = (value >>> 8)
      this[offset + 3] = (value & 0xff)
    } else {
      objectWriteUInt32(this, value, offset, false)
    }
    return offset + 4
  }
  
  Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) {
      var limit = Math.pow(2, 8 * byteLength - 1)
  
      checkInt(this, value, offset, byteLength, limit - 1, -limit)
    }
  
    var i = 0
    var mul = 1
    var sub = value < 0 ? 1 : 0
    this[offset] = value & 0xFF
    while (++i < byteLength && (mul *= 0x100)) {
      this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) {
      var limit = Math.pow(2, 8 * byteLength - 1)
  
      checkInt(this, value, offset, byteLength, limit - 1, -limit)
    }
  
    var i = byteLength - 1
    var mul = 1
    var sub = value < 0 ? 1 : 0
    this[offset + i] = value & 0xFF
    while (--i >= 0 && (mul *= 0x100)) {
      this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
    if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
    if (value < 0) value = 0xff + value + 1
    this[offset] = (value & 0xff)
    return offset + 1
  }
  
  Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value & 0xff)
      this[offset + 1] = (value >>> 8)
    } else {
      objectWriteUInt16(this, value, offset, true)
    }
    return offset + 2
  }
  
  Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 8)
      this[offset + 1] = (value & 0xff)
    } else {
      objectWriteUInt16(this, value, offset, false)
    }
    return offset + 2
  }
  
  Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value & 0xff)
      this[offset + 1] = (value >>> 8)
      this[offset + 2] = (value >>> 16)
      this[offset + 3] = (value >>> 24)
    } else {
      objectWriteUInt32(this, value, offset, true)
    }
    return offset + 4
  }
  
  Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
    if (value < 0) value = 0xffffffff + value + 1
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 24)
      this[offset + 1] = (value >>> 16)
      this[offset + 2] = (value >>> 8)
      this[offset + 3] = (value & 0xff)
    } else {
      objectWriteUInt32(this, value, offset, false)
    }
    return offset + 4
  }
  
  function checkIEEE754 (buf, value, offset, ext, max, min) {
    if (value > max || value < min) throw new RangeError('value is out of bounds')
    if (offset + ext > buf.length) throw new RangeError('index out of range')
    if (offset < 0) throw new RangeError('index out of range')
  }
  
  function writeFloat (buf, value, offset, littleEndian, noAssert) {
    if (!noAssert) {
      checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
    }
    ieee754.write(buf, value, offset, littleEndian, 23, 4)
    return offset + 4
  }
  
  Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
    return writeFloat(this, value, offset, true, noAssert)
  }
  
  Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
    return writeFloat(this, value, offset, false, noAssert)
  }
  
  function writeDouble (buf, value, offset, littleEndian, noAssert) {
    if (!noAssert) {
      checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
    }
    ieee754.write(buf, value, offset, littleEndian, 52, 8)
    return offset + 8
  }
  
  Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
    return writeDouble(this, value, offset, true, noAssert)
  }
  
  Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
    return writeDouble(this, value, offset, false, noAssert)
  }
  
  // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
  Buffer.prototype.copy = function copy (target, targetStart, start, end) {
    if (!start) start = 0
    if (!end && end !== 0) end = this.length
    if (targetStart >= target.length) targetStart = target.length
    if (!targetStart) targetStart = 0
    if (end > 0 && end < start) end = start
  
    // Copy 0 bytes; we're done
    if (end === start) return 0
    if (target.length === 0 || this.length === 0) return 0
  
    // Fatal error conditions
    if (targetStart < 0) {
      throw new RangeError('targetStart out of bounds')
    }
    if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
    if (end < 0) throw new RangeError('sourceEnd out of bounds')
  
    // Are we oob?
    if (end > this.length) end = this.length
    if (target.length - targetStart < end - start) {
      end = target.length - targetStart + start
    }
  
    var len = end - start
    var i
  
    if (this === target && start < targetStart && targetStart < end) {
      // descending copy from end
      for (i = len - 1; i >= 0; i--) {
        target[i + targetStart] = this[i + start]
      }
    } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
      // ascending copy from start
      for (i = 0; i < len; i++) {
        target[i + targetStart] = this[i + start]
      }
    } else {
      target._set(this.subarray(start, start + len), targetStart)
    }
  
    return len
  }
  
  // fill(value, start=0, end=buffer.length)
  Buffer.prototype.fill = function fill (value, start, end) {
    if (!value) value = 0
    if (!start) start = 0
    if (!end) end = this.length
  
    if (end < start) throw new RangeError('end < start')
  
    // Fill 0 bytes; we're done
    if (end === start) return
    if (this.length === 0) return
  
    if (start < 0 || start >= this.length) throw new RangeError('start out of bounds')
    if (end < 0 || end > this.length) throw new RangeError('end out of bounds')
  
    var i
    if (typeof value === 'number') {
      for (i = start; i < end; i++) {
        this[i] = value
      }
    } else {
      var bytes = utf8ToBytes(value.toString())
      var len = bytes.length
      for (i = start; i < end; i++) {
        this[i] = bytes[i % len]
      }
    }
  
    return this
  }
  
  /**
   * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
   * Added in Node 0.12. Only available in browsers that support ArrayBuffer.
   */
  Buffer.prototype.toArrayBuffer = function toArrayBuffer () {
    if (typeof Uint8Array !== 'undefined') {
      if (Buffer.TYPED_ARRAY_SUPPORT) {
        return (new Buffer(this)).buffer
      } else {
        var buf = new Uint8Array(this.length)
        for (var i = 0, len = buf.length; i < len; i += 1) {
          buf[i] = this[i]
        }
        return buf.buffer
      }
    } else {
      throw new TypeError('Buffer.toArrayBuffer not supported in this browser')
    }
  }
  
  // HELPER FUNCTIONS
  // ================
  
  var BP = Buffer.prototype
  
  /**
   * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
   */
  Buffer._augment = function _augment (arr) {
    arr.constructor = Buffer
    arr._isBuffer = true
  
    // save reference to original Uint8Array set method before overwriting
    arr._set = arr.set
  
    // deprecated
    arr.get = BP.get
    arr.set = BP.set
  
    arr.write = BP.write
    arr.toString = BP.toString
    arr.toLocaleString = BP.toString
    arr.toJSON = BP.toJSON
    arr.equals = BP.equals
    arr.compare = BP.compare
    arr.indexOf = BP.indexOf
    arr.copy = BP.copy
    arr.slice = BP.slice
    arr.readUIntLE = BP.readUIntLE
    arr.readUIntBE = BP.readUIntBE
    arr.readUInt8 = BP.readUInt8
    arr.readUInt16LE = BP.readUInt16LE
    arr.readUInt16BE = BP.readUInt16BE
    arr.readUInt32LE = BP.readUInt32LE
    arr.readUInt32BE = BP.readUInt32BE
    arr.readIntLE = BP.readIntLE
    arr.readIntBE = BP.readIntBE
    arr.readInt8 = BP.readInt8
    arr.readInt16LE = BP.readInt16LE
    arr.readInt16BE = BP.readInt16BE
    arr.readInt32LE = BP.readInt32LE
    arr.readInt32BE = BP.readInt32BE
    arr.readFloatLE = BP.readFloatLE
    arr.readFloatBE = BP.readFloatBE
    arr.readDoubleLE = BP.readDoubleLE
    arr.readDoubleBE = BP.readDoubleBE
    arr.writeUInt8 = BP.writeUInt8
    arr.writeUIntLE = BP.writeUIntLE
    arr.writeUIntBE = BP.writeUIntBE
    arr.writeUInt16LE = BP.writeUInt16LE
    arr.writeUInt16BE = BP.writeUInt16BE
    arr.writeUInt32LE = BP.writeUInt32LE
    arr.writeUInt32BE = BP.writeUInt32BE
    arr.writeIntLE = BP.writeIntLE
    arr.writeIntBE = BP.writeIntBE
    arr.writeInt8 = BP.writeInt8
    arr.writeInt16LE = BP.writeInt16LE
    arr.writeInt16BE = BP.writeInt16BE
    arr.writeInt32LE = BP.writeInt32LE
    arr.writeInt32BE = BP.writeInt32BE
    arr.writeFloatLE = BP.writeFloatLE
    arr.writeFloatBE = BP.writeFloatBE
    arr.writeDoubleLE = BP.writeDoubleLE
    arr.writeDoubleBE = BP.writeDoubleBE
    arr.fill = BP.fill
    arr.inspect = BP.inspect
    arr.toArrayBuffer = BP.toArrayBuffer
  
    return arr
  }
  
  var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g
  
  function base64clean (str) {
    // Node strips out invalid characters like \n and \t from the string, base64-js does not
    str = stringtrim(str).replace(INVALID_BASE64_RE, '')
    // Node converts strings with length < 2 to ''
    if (str.length < 2) return ''
    // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
    while (str.length % 4 !== 0) {
      str = str + '='
    }
    return str
  }
  
  function stringtrim (str) {
    if (str.trim) return str.trim()
    return str.replace(/^\s+|\s+$/g, '')
  }
  
  function toHex (n) {
    if (n < 16) return '0' + n.toString(16)
    return n.toString(16)
  }
  
  function utf8ToBytes (string, units) {
    units = units || Infinity
    var codePoint
    var length = string.length
    var leadSurrogate = null
    var bytes = []
  
    for (var i = 0; i < length; i++) {
      codePoint = string.charCodeAt(i)
  
      // is surrogate component
      if (codePoint > 0xD7FF && codePoint < 0xE000) {
        // last char was a lead
        if (!leadSurrogate) {
          // no lead yet
          if (codePoint > 0xDBFF) {
            // unexpected trail
            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
            continue
          } else if (i + 1 === length) {
            // unpaired lead
            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
            continue
          }
  
          // valid lead
          leadSurrogate = codePoint
  
          continue
        }
  
        // 2 leads in a row
        if (codePoint < 0xDC00) {
          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
          leadSurrogate = codePoint
          continue
        }
  
        // valid surrogate pair
        codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
      } else if (leadSurrogate) {
        // valid bmp char, but last char was a lead
        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
      }
  
      leadSurrogate = null
  
      // encode utf8
      if (codePoint < 0x80) {
        if ((units -= 1) < 0) break
        bytes.push(codePoint)
      } else if (codePoint < 0x800) {
        if ((units -= 2) < 0) break
        bytes.push(
          codePoint >> 0x6 | 0xC0,
          codePoint & 0x3F | 0x80
        )
      } else if (codePoint < 0x10000) {
        if ((units -= 3) < 0) break
        bytes.push(
          codePoint >> 0xC | 0xE0,
          codePoint >> 0x6 & 0x3F | 0x80,
          codePoint & 0x3F | 0x80
        )
      } else if (codePoint < 0x110000) {
        if ((units -= 4) < 0) break
        bytes.push(
          codePoint >> 0x12 | 0xF0,
          codePoint >> 0xC & 0x3F | 0x80,
          codePoint >> 0x6 & 0x3F | 0x80,
          codePoint & 0x3F | 0x80
        )
      } else {
        throw new Error('Invalid code point')
      }
    }
  
    return bytes
  }
  
  function asciiToBytes (str) {
    var byteArray = []
    for (var i = 0; i < str.length; i++) {
      // Node's code seems to be doing this and not & 0x7F..
      byteArray.push(str.charCodeAt(i) & 0xFF)
    }
    return byteArray
  }
  
  function utf16leToBytes (str, units) {
    var c, hi, lo
    var byteArray = []
    for (var i = 0; i < str.length; i++) {
      if ((units -= 2) < 0) break
  
      c = str.charCodeAt(i)
      hi = c >> 8
      lo = c % 256
      byteArray.push(lo)
      byteArray.push(hi)
    }
  
    return byteArray
  }
  
  function base64ToBytes (str) {
    return base64.toByteArray(base64clean(str))
  }
  
  function blitBuffer (src, dst, offset, length) {
    for (var i = 0; i < length; i++) {
      if ((i + offset >= dst.length) || (i >= src.length)) break
      dst[i + offset] = src[i]
    }
    return i
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-process@0.11.9/browser.js-=@*/
  // shim for using process in browser
  var process = module.exports = {};
  
  // cached from whatever global is present so that test runners that stub it
  // don't break things.  But we need to wrap it in a try catch in case it is
  // wrapped in strict mode code which doesn't define any globals.  It's inside a
  // function because try/catches deoptimize in certain engines.
  
  var cachedSetTimeout;
  var cachedClearTimeout;
  
  function defaultSetTimout() {
      throw new Error('setTimeout has not been defined');
  }
  function defaultClearTimeout () {
      throw new Error('clearTimeout has not been defined');
  }
  (function () {
      try {
          if (typeof setTimeout === 'function') {
              cachedSetTimeout = setTimeout;
          } else {
              cachedSetTimeout = defaultSetTimout;
          }
      } catch (e) {
          cachedSetTimeout = defaultSetTimout;
      }
      try {
          if (typeof clearTimeout === 'function') {
              cachedClearTimeout = clearTimeout;
          } else {
              cachedClearTimeout = defaultClearTimeout;
          }
      } catch (e) {
          cachedClearTimeout = defaultClearTimeout;
      }
  } ())
  function runTimeout(fun) {
      if (cachedSetTimeout === setTimeout) {
          //normal enviroments in sane situations
          return setTimeout(fun, 0);
      }
      // if setTimeout wasn't available but was latter defined
      if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
          cachedSetTimeout = setTimeout;
          return setTimeout(fun, 0);
      }
      try {
          // when when somebody has screwed with setTimeout but no I.E. maddness
          return cachedSetTimeout(fun, 0);
      } catch(e){
          try {
              // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
              return cachedSetTimeout.call(null, fun, 0);
          } catch(e){
              // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
              return cachedSetTimeout.call(this, fun, 0);
          }
      }
  
  
  }
  function runClearTimeout(marker) {
      if (cachedClearTimeout === clearTimeout) {
          //normal enviroments in sane situations
          return clearTimeout(marker);
      }
      // if clearTimeout wasn't available but was latter defined
      if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
          cachedClearTimeout = clearTimeout;
          return clearTimeout(marker);
      }
      try {
          // when when somebody has screwed with setTimeout but no I.E. maddness
          return cachedClearTimeout(marker);
      } catch (e){
          try {
              // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
              return cachedClearTimeout.call(null, marker);
          } catch (e){
              // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
              // Some versions of I.E. have different rules for clearTimeout vs setTimeout
              return cachedClearTimeout.call(this, marker);
          }
      }
  
  
  
  }
  var queue = [];
  var draining = false;
  var currentQueue;
  var queueIndex = -1;
  
  function cleanUpNextTick() {
      if (!draining || !currentQueue) {
          return;
      }
      draining = false;
      if (currentQueue.length) {
          queue = currentQueue.concat(queue);
      } else {
          queueIndex = -1;
      }
      if (queue.length) {
          drainQueue();
      }
  }
  
  function drainQueue() {
      if (draining) {
          return;
      }
      var timeout = runTimeout(cleanUpNextTick);
      draining = true;
  
      var len = queue.length;
      while(len) {
          currentQueue = queue;
          queue = [];
          while (++queueIndex < len) {
              if (currentQueue) {
                  currentQueue[queueIndex].run();
              }
          }
          queueIndex = -1;
          len = queue.length;
      }
      currentQueue = null;
      draining = false;
      runClearTimeout(timeout);
  }
  
  process.nextTick = function (fun) {
      var args = new Array(arguments.length - 1);
      if (arguments.length > 1) {
          for (var i = 1; i < arguments.length; i++) {
              args[i - 1] = arguments[i];
          }
      }
      queue.push(new Item(fun, args));
      if (queue.length === 1 && !draining) {
          runTimeout(drainQueue);
      }
  };
  
  // v8 likes predictible objects
  function Item(fun, array) {
      this.fun = fun;
      this.array = array;
  }
  Item.prototype.run = function () {
      this.fun.apply(null, this.array);
  };
  process.title = 'browser';
  process.browser = true;
  process.env = {};
  process.argv = [];
  process.version = ''; // empty string to avoid regexp issues
  process.versions = {};
  
  function noop() {}
  
  process.on = noop;
  process.addListener = noop;
  process.once = noop;
  process.off = noop;
  process.removeListener = noop;
  process.removeAllListeners = noop;
  process.emit = noop;
  
  process.binding = function (name) {
      throw new Error('process.binding is not supported');
  };
  
  process.cwd = function () { return '/' };
  process.chdir = function (dir) {
      throw new Error('process.chdir is not supported');
  };
  process.umask = function() { return 0; };
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-base64-js@0.0.8/lib/b64.js-=@*/
  var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  
  ;(function (exports) {
  	'use strict';
  
    var Arr = (typeof Uint8Array !== 'undefined')
      ? Uint8Array
      : Array
  
  	var PLUS   = '+'.charCodeAt(0)
  	var SLASH  = '/'.charCodeAt(0)
  	var NUMBER = '0'.charCodeAt(0)
  	var LOWER  = 'a'.charCodeAt(0)
  	var UPPER  = 'A'.charCodeAt(0)
  	var PLUS_URL_SAFE = '-'.charCodeAt(0)
  	var SLASH_URL_SAFE = '_'.charCodeAt(0)
  
  	function decode (elt) {
  		var code = elt.charCodeAt(0)
  		if (code === PLUS ||
  		    code === PLUS_URL_SAFE)
  			return 62 // '+'
  		if (code === SLASH ||
  		    code === SLASH_URL_SAFE)
  			return 63 // '/'
  		if (code < NUMBER)
  			return -1 //no match
  		if (code < NUMBER + 10)
  			return code - NUMBER + 26 + 26
  		if (code < UPPER + 26)
  			return code - UPPER
  		if (code < LOWER + 26)
  			return code - LOWER + 26
  	}
  
  	function b64ToByteArray (b64) {
  		var i, j, l, tmp, placeHolders, arr
  
  		if (b64.length % 4 > 0) {
  			throw new Error('Invalid string. Length must be a multiple of 4')
  		}
  
  		// the number of equal signs (place holders)
  		// if there are two placeholders, than the two characters before it
  		// represent one byte
  		// if there is only one, then the three characters before it represent 2 bytes
  		// this is just a cheap hack to not do indexOf twice
  		var len = b64.length
  		placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
  
  		// base64 is 4/3 + up to two characters of the original data
  		arr = new Arr(b64.length * 3 / 4 - placeHolders)
  
  		// if there are placeholders, only get up to the last complete 4 chars
  		l = placeHolders > 0 ? b64.length - 4 : b64.length
  
  		var L = 0
  
  		function push (v) {
  			arr[L++] = v
  		}
  
  		for (i = 0, j = 0; i < l; i += 4, j += 3) {
  			tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
  			push((tmp & 0xFF0000) >> 16)
  			push((tmp & 0xFF00) >> 8)
  			push(tmp & 0xFF)
  		}
  
  		if (placeHolders === 2) {
  			tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
  			push(tmp & 0xFF)
  		} else if (placeHolders === 1) {
  			tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
  			push((tmp >> 8) & 0xFF)
  			push(tmp & 0xFF)
  		}
  
  		return arr
  	}
  
  	function uint8ToBase64 (uint8) {
  		var i,
  			extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
  			output = "",
  			temp, length
  
  		function encode (num) {
  			return lookup.charAt(num)
  		}
  
  		function tripletToBase64 (num) {
  			return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
  		}
  
  		// go through the array every three bytes, we'll deal with trailing stuff later
  		for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
  			temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
  			output += tripletToBase64(temp)
  		}
  
  		// pad the end with zeros, but make sure to not forget the extra bytes
  		switch (extraBytes) {
  			case 1:
  				temp = uint8[uint8.length - 1]
  				output += encode(temp >> 2)
  				output += encode((temp << 4) & 0x3F)
  				output += '=='
  				break
  			case 2:
  				temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
  				output += encode(temp >> 10)
  				output += encode((temp >> 4) & 0x3F)
  				output += encode((temp << 2) & 0x3F)
  				output += '='
  				break
  		}
  
  		return output
  	}
  
  	exports.toByteArray = b64ToByteArray
  	exports.fromByteArray = uint8ToBase64
  }(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-ieee754@1.1.8/index.js-=@*/
  exports.read = function (buffer, offset, isLE, mLen, nBytes) {
    var e, m
    var eLen = nBytes * 8 - mLen - 1
    var eMax = (1 << eLen) - 1
    var eBias = eMax >> 1
    var nBits = -7
    var i = isLE ? (nBytes - 1) : 0
    var d = isLE ? -1 : 1
    var s = buffer[offset + i]
  
    i += d
  
    e = s & ((1 << (-nBits)) - 1)
    s >>= (-nBits)
    nBits += eLen
    for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
  
    m = e & ((1 << (-nBits)) - 1)
    e >>= (-nBits)
    nBits += mLen
    for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
  
    if (e === 0) {
      e = 1 - eBias
    } else if (e === eMax) {
      return m ? NaN : ((s ? -1 : 1) * Infinity)
    } else {
      m = m + Math.pow(2, mLen)
      e = e - eBias
    }
    return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
  }
  
  exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
    var e, m, c
    var eLen = nBytes * 8 - mLen - 1
    var eMax = (1 << eLen) - 1
    var eBias = eMax >> 1
    var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
    var i = isLE ? 0 : (nBytes - 1)
    var d = isLE ? 1 : -1
    var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
  
    value = Math.abs(value)
  
    if (isNaN(value) || value === Infinity) {
      m = isNaN(value) ? 1 : 0
      e = eMax
    } else {
      e = Math.floor(Math.log(value) / Math.LN2)
      if (value * (c = Math.pow(2, -e)) < 1) {
        e--
        c *= 2
      }
      if (e + eBias >= 1) {
        value += rt / c
      } else {
        value += rt * Math.pow(2, 1 - eBias)
      }
      if (value * c >= 2) {
        e++
        c /= 2
      }
  
      if (e + eBias >= eMax) {
        m = 0
        e = eMax
      } else if (e + eBias >= 1) {
        m = (value * c - 1) * Math.pow(2, mLen)
        e = e + eBias
      } else {
        m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
        e = 0
      }
    }
  
    for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
  
    e = (e << mLen) | m
    eLen += mLen
    for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
  
    buffer[offset + i - d] |= s * 128
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-isarray@1.0.0/index.js-=@*/
  var toString = {}.toString;
  
  module.exports = Array.isArray || function (arr) {
    return toString.call(arr) == '[object Array]';
  };
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/event_emitter@0.0.3/src/index.js-=@*/
  var isFunction = require(16),
      inherits = require(38),
      fastSlice = require(39),
      keys = require(8),
      isNumber = require(7),
      isNullOrUndefined = require(13);
  
  
  var EventEmitterPrototype;
  
  
  module.exports = EventEmitter;
  
  
  function EventEmitter(maxListeners) {
      this.__events = {};
      this.__maxListeners = isNumber(maxListeners) ? +maxListeners : EventEmitter.defaultMaxListeners;
  }
  EventEmitterPrototype = EventEmitter.prototype;
  
  EventEmitterPrototype.on = function(name, listener) {
      var events, eventList, maxListeners;
  
      if (!isFunction(listener)) {
          throw new TypeError("EventEmitter.on(name, listener) listener must be a function");
      }
  
      events = this.__events || (this.__events = {});
      eventList = (events[name] || (events[name] = []));
      maxListeners = this.__maxListeners || -1;
  
      eventList[eventList.length] = listener;
  
      if (maxListeners !== -1 && eventList.length > maxListeners) {
          console.error(
              "EventEmitter.on(type, listener) possible EventEmitter memory leak detected. " + maxListeners + " listeners added"
          );
      }
  
      return this;
  };
  
  EventEmitterPrototype.addEventListener = EventEmitterPrototype.addListener = EventEmitterPrototype.on;
  
  EventEmitterPrototype.once = function(name, listener) {
      var _this = this;
  
      function once() {
  
          _this.off(name, once);
  
          switch (arguments.length) {
              case 0:
                  return listener();
              case 1:
                  return listener(arguments[0]);
              case 2:
                  return listener(arguments[0], arguments[1]);
              case 3:
                  return listener(arguments[0], arguments[1], arguments[2]);
              case 4:
                  return listener(arguments[0], arguments[1], arguments[2], arguments[3]);
              default:
                  return listener.apply(null, arguments);
          }
      }
  
      this.on(name, once);
  
      return once;
  };
  
  EventEmitterPrototype.listenTo = function(value, name) {
      var _this = this;
  
      if (!value || !(isFunction(value.on) || isFunction(value.addListener))) {
          throw new TypeError("EventEmitter.listenTo(value, name) value must have a on function taking (name, listener[, ctx])");
      }
  
      function handler() {
          _this.emitArgs(name, arguments);
      }
  
      value.on(name, handler);
  
      return handler;
  };
  
  EventEmitterPrototype.off = function(name, listener) {
      var events = this.__events || (this.__events = {}),
          eventList, event, i;
  
      eventList = events[name];
      if (!eventList) {
          return this;
      }
  
      if (!listener) {
          i = eventList.length;
  
          while (i--) {
              this.emit("removeListener", name, eventList[i]);
          }
          eventList.length = 0;
          delete events[name];
      } else {
          i = eventList.length;
  
          while (i--) {
              event = eventList[i];
  
              if (event === listener) {
                  this.emit("removeListener", name, event);
                  eventList.splice(i, 1);
              }
          }
  
          if (eventList.length === 0) {
              delete events[name];
          }
      }
  
      return this;
  };
  
  EventEmitterPrototype.removeEventListener = EventEmitterPrototype.removeListener = EventEmitterPrototype.off;
  
  EventEmitterPrototype.removeAllListeners = function() {
      var events = this.__events || (this.__events = {}),
          objectKeys = keys(events),
          i = -1,
          il = objectKeys.length - 1,
          key, eventList, j;
  
      while (i++ < il) {
          key = objectKeys[i];
          eventList = events[key];
  
          if (eventList) {
              j = eventList.length;
  
              while (j--) {
                  this.emit("removeListener", key, eventList[j]);
                  eventList.splice(j, 1);
              }
          }
  
          delete events[key];
      }
  
      return this;
  };
  
  EventEmitterPrototype.dispatchEvent = function(event) {
      return this.emitArg(event.type, event);
  };
  
  EventEmitterPrototype.attachEvent = function(type, listener) {
      return this.on(type.slice(2), listener);
  };
  
  EventEmitterPrototype.detachEvent = function(type, listener) {
      return this.off(type.slice(2), listener);
  };
  
  EventEmitterPrototype.fireEvent = function(type, event) {
      return this.emitArg(type.slice(2), event);
  };
  
  function emit0(eventList) {
      var i = -1,
          il = eventList.length - 1,
          event;
  
      while (i++ < il) {
          if ((event = eventList[i])) {
              event();
          }
      }
  }
  
  function emit1(eventList, a0) {
      var i = -1,
          il = eventList.length - 1,
          event;
  
      while (i++ < il) {
          if ((event = eventList[i])) {
              event(a0);
          }
      }
  }
  
  function emit2(eventList, args) {
      var a0 = args[0],
          a1 = args[1],
          i = -1,
          il = eventList.length - 1,
          event;
  
      while (i++ < il) {
          if ((event = eventList[i])) {
              event(a0, a1);
          }
      }
  }
  
  function emit3(eventList, args) {
      var a0 = args[0],
          a1 = args[1],
          a2 = args[2],
          i = -1,
          il = eventList.length - 1,
          event;
  
      while (i++ < il) {
          if ((event = eventList[i])) {
              event(a0, a1, a2);
          }
      }
  }
  
  function emit4(eventList, args) {
      var a0 = args[0],
          a1 = args[1],
          a2 = args[2],
          a3 = args[3],
          i = -1,
          il = eventList.length - 1,
          event;
  
      while (i++ < il) {
          if ((event = eventList[i])) {
              event(a0, a1, a2, a3);
          }
      }
  }
  
  function emit5(eventList, args) {
      var a0 = args[0],
          a1 = args[1],
          a2 = args[2],
          a3 = args[3],
          a4 = args[4],
          i = -1,
          il = eventList.length - 1,
          event;
  
      while (i++ < il) {
          if ((event = eventList[i])) {
              event(a0, a1, a2, a3, a4);
          }
      }
  }
  
  function emitApply(eventList, args) {
      var i = -1,
          il = eventList.length - 1,
          event;
  
      while (i++ < il) {
          if ((event = eventList[i])) {
              event.apply(null, args);
          }
      }
  }
  
  function emit(eventList, args) {
      switch (args.length) {
          case 0:
              emit0(eventList);
              break;
          case 1:
              emit1(eventList, args[0]);
              break;
          case 2:
              emit2(eventList, args);
              break;
          case 3:
              emit3(eventList, args);
              break;
          case 4:
              emit4(eventList, args);
              break;
          case 5:
              emit5(eventList, args);
              break;
          default:
              emitApply(eventList, args);
              break;
      }
  }
  
  EventEmitterPrototype.emitArg = function(name, arg) {
      var eventList = (this.__events || (this.__events = {}))[name];
  
      if (!eventList || !eventList.length) {
          return this;
      } else {
          emit1(eventList, arg);
          return this;
      }
  };
  
  EventEmitterPrototype.emitArgs = function(name, args) {
      var eventList = (this.__events || (this.__events = {}))[name];
  
      if (!eventList || !eventList.length) {
          return this;
      } else {
          emit(eventList, args);
          return this;
      }
  };
  
  EventEmitterPrototype.emit = function(name) {
      return this.emitArgs(name, fastSlice(arguments, 1));
  };
  
  function createFunctionCaller(args) {
      var a0, a1, a2, a3, a4;
      switch (args.length) {
          case 0:
              return function functionCaller(fn) {
                  return fn();
              };
          case 1:
              a0 = args[0];
              return function functionCaller(fn) {
                  return fn(a0);
              };
          case 2:
              a0 = args[0];
              a1 = args[1];
              return function functionCaller(fn) {
                  return fn(a0, a1);
              };
          case 3:
              a0 = args[0];
              a1 = args[1];
              a2 = args[2];
              return function functionCaller(fn) {
                  return fn(a0, a1, a2);
              };
          case 4:
              a0 = args[0];
              a1 = args[1];
              a2 = args[2];
              a3 = args[3];
              return function functionCaller(fn) {
                  return fn(a0, a1, a2, a3);
              };
          case 5:
              a0 = args[0];
              a1 = args[1];
              a2 = args[2];
              a3 = args[3];
              a4 = args[4];
              return function functionCaller(fn) {
                  return fn(a0, a1, a2, a3, a4);
              };
          default:
              return function functionCaller(fn) {
                  return fn.apply(null, args);
              };
      }
  }
  
  function emitAsync(eventList, args, callback) {
      var length = eventList.length,
          index = 0,
          called = false,
          functionCaller;
  
      function next(error) {
          if (called !== true) {
              if (error || index === length) {
                  called = true;
                  callback(error);
              } else {
                  functionCaller(eventList[index++]);
              }
          }
      }
  
      args[args.length] = next;
      functionCaller = createFunctionCaller(args);
      next();
  }
  
  EventEmitterPrototype.emitAsync = function(name, args, callback) {
      var eventList = (this.__events || (this.__events = {}))[name];
  
      args = fastSlice(arguments, 1);
      callback = args.pop();
  
      if (!isFunction(callback)) {
          throw new TypeError("EventEmitter.emitAsync(name [, ...args], callback) callback must be a function");
      } else {
          if (!eventList || !eventList.length) {
              callback();
          } else {
              emitAsync(eventList, args, callback);
          }
          return this;
      }
  };
  
  EventEmitterPrototype.listeners = function(name) {
      var eventList = (this.__events || (this.__events = {}))[name];
      return eventList ? eventList.slice() : [];
  };
  
  EventEmitterPrototype.listenerCount = function(name) {
      var eventList = (this.__events || (this.__events = {}))[name];
      return eventList ? eventList.length : 0;
  };
  
  EventEmitterPrototype.setMaxListeners = function(value) {
      if ((value = +value) !== value) {
          throw new TypeError("EventEmitter.setMaxListeners(value) value must be a number");
      }
  
      this.__maxListeners = value < 0 ? -1 : value;
      return this;
  };
  
  inherits.defineProperty(EventEmitter, "defaultMaxListeners", 10);
  
  inherits.defineProperty(EventEmitter, "listeners", function(value, name) {
      var eventList;
  
      if (isNullOrUndefined(value)) {
          throw new TypeError("EventEmitter.listeners(value, name) value required");
      }
      eventList = value.__events && value.__events[name];
  
      return eventList ? eventList.slice() : [];
  });
  
  inherits.defineProperty(EventEmitter, "listenerCount", function(value, name) {
      var eventList;
  
      if (isNullOrUndefined(value)) {
          throw new TypeError("EventEmitter.listenerCount(value, name) value required");
      }
      eventList = value.__events && value.__events[name];
  
      return eventList ? eventList.length : 0;
  });
  
  inherits.defineProperty(EventEmitter, "setMaxListeners", function(value) {
      if ((value = +value) !== value) {
          throw new TypeError("EventEmitter.setMaxListeners(value) value must be a number");
      }
  
      EventEmitter.defaultMaxListeners = value < 0 ? -1 : value;
      return value;
  });
  
  EventEmitter.extend = function(child) {
      inherits(child, this);
      return child;
  };
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/event_listener@0.0.2/src/index.js-=@*/
  var process = require(26);
  var isObject = require(14),
      isFunction = require(16),
      environment = require(22),
      eventTable = require(47);
  
  
  var eventListener = module.exports,
  
      reSpliter = /[\s]+/,
  
      window = environment.window,
      document = environment.document,
  
      listenToEvent, captureEvent, removeEvent, dispatchEvent;
  
  
  window.Event = window.Event || function EmptyEvent() {};
  
  
  eventListener.on = function(target, eventType, callback) {
      var eventTypes = eventType.split(reSpliter),
          i = eventTypes.length;
  
      while (i--) {
          listenToEvent(target, eventTypes[i], callback);
      }
  };
  
  eventListener.capture = function(target, eventType, callback) {
      var eventTypes = eventType.split(reSpliter),
          i = eventTypes.length;
  
      while (i--) {
          captureEvent(target, eventTypes[i], callback);
      }
  };
  
  eventListener.off = function(target, eventType, callback) {
      var eventTypes = eventType.split(reSpliter),
          i = eventTypes.length;
  
      while (i--) {
          removeEvent(target, eventTypes[i], callback);
      }
  };
  
  eventListener.emit = function(target, eventType, event) {
  
      return dispatchEvent(target, eventType, isObject(event) ? event : {});
  };
  
  eventListener.getEventConstructor = function(target, eventType) {
      var getter = eventTable[eventType];
      return isFunction(getter) ? getter(target) : window.Event;
  };
  
  
  if (isFunction(document.addEventListener)) {
  
      listenToEvent = function(target, eventType, callback) {
  
          target.addEventListener(eventType, callback, false);
      };
  
      captureEvent = function(target, eventType, callback) {
  
          target.addEventListener(eventType, callback, true);
      };
  
      removeEvent = function(target, eventType, callback) {
  
          target.removeEventListener(eventType, callback, false);
      };
  
      dispatchEvent = function(target, eventType, event) {
          var getter = eventTable[eventType],
              EventType = isFunction(getter) ? getter(target) : window.Event;
  
          return !!target.dispatchEvent(new EventType(eventType, event));
      };
  } else if (isFunction(document.attachEvent)) {
  
      listenToEvent = function(target, eventType, callback) {
  
          target.attachEvent("on" + eventType, callback);
      };
  
      captureEvent = function() {
          if (process.env.NODE_ENV === "development") {
              throw new Error(
                  "Attempted to listen to events during the capture phase on a " +
                  "browser that does not support the capture phase. Your application " +
                  "will not receive some events."
              );
          }
      };
  
      removeEvent = function(target, eventType, callback) {
  
          target.detachEvent("on" + eventType, callback);
      };
  
      dispatchEvent = function(target, eventType, event) {
          var doc = target.ownerDocument || document;
  
          return !!target.fireEvent("on" + eventType, doc.createEventObject(event));
      };
  } else {
  
      listenToEvent = function(target, eventType, callback) {
  
          target["on" + eventType] = callback;
          return target;
      };
  
      captureEvent = function() {
          if (process.env.NODE_ENV === "development") {
              throw new Error(
                  "Attempted to listen to events during the capture phase on a " +
                  "browser that does not support the capture phase. Your application " +
                  "will not receive some events."
              );
          }
      };
  
      removeEvent = function(target, eventType) {
  
          target["on" + eventType] = null;
          return true;
      };
  
      dispatchEvent = function(target, eventType, event) {
          var onType = "on" + eventType;
  
          if (isFunction(target[onType])) {
              event.type = eventType;
              return !!target[onType](event);
          }
  
          return false;
      };
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/color@0.0.4/src/index.js-=@*/
  var mathf = require(5),
      vec3 = require(6),
      vec4 = require(49),
      isNumber = require(7),
      isString = require(21),
      colorNames = require(50);
  
  
  var color = exports;
  
  
  color.ArrayType = typeof(Float32Array) !== "undefined" ? Float32Array : mathf.ArrayType;
  
  
  color.create = function(r, g, b, a) {
      var out = new color.ArrayType(4);
  
      out[0] = isNumber(r) ? r : 0;
      out[1] = isNumber(g) ? g : 0;
      out[2] = isNumber(b) ? b : 0;
      out[3] = isNumber(a) ? a : 1;
  
      return out;
  };
  
  color.copy = vec4.copy;
  
  color.clone = function(a) {
      var out = new color.ArrayType(4);
  
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
  
      return out;
  };
  
  color.setRGB = vec3.set;
  color.setRGBA = vec4.set;
  
  color.add = vec4.add;
  color.sub = vec4.sub;
  
  color.mul = vec4.mul;
  color.div = vec4.div;
  
  color.sadd = vec4.sadd;
  color.ssub = vec4.ssub;
  
  color.smul = vec4.smul;
  color.sdiv = vec4.sdiv;
  
  color.lengthSqValues = vec4.lengthSqValues;
  color.lengthValues = vec4.lengthValues;
  color.invLengthValues = vec4.invLengthValues;
  
  color.dot = vec4.dot;
  
  color.lengthSq = vec4.lengthSq;
  
  color.length = vec4.length;
  
  color.invLength = vec4.invLength;
  
  color.setLength = vec4.setLength;
  
  color.normalize = vec4.normalize;
  
  color.lerp = vec4.lerp;
  
  color.min = vec4.min;
  
  color.max = vec4.max;
  
  color.clamp = vec4.clamp;
  
  color.equals = vec4.equals;
  color.notEquals = vec4.notEquals;
  
  
  var cmin = color.create(0, 0, 0, 0),
      cmax = color.create(1, 1, 1, 1);
  
  color.cnormalize = function(out, a) {
      return color.clamp(out, a, cmin, cmax);
  };
  
  color.str = function(out) {
      return "Color(" + out[0] + ", " + out[1] + ", " + out[2] + ", " + out[3] + ")";
  };
  
  color.string = color.toString = color.str;
  
  color.set = function(out, r, g, b, a) {
      if (isNumber(r)) {
          out[0] = isNumber(r) ? r : 0;
          out[1] = isNumber(g) ? g : 0;
          out[2] = isNumber(b) ? b : 0;
          out[3] = isNumber(a) ? a : 1;
      } else if (isString(r)) {
          color.fromStyle(out, r);
      } else if (r && r.length === +r.length) {
          out[0] = r[0] || 0;
          out[1] = r[1] || 0;
          out[2] = r[2] || 0;
          out[3] = r[3] || 1;
      }
  
      return out;
  };
  
  function to256(value) {
      return (value * 255) | 0;
  }
  
  color.toRGB = function(out, alpha) {
      if (isNumber(alpha)) {
          return "rgba(" + to256(out[0]) + "," + to256(out[1]) + "," + to256(out[2]) + "," + (mathf.clamp01(alpha) || 0) + ")";
      } else {
          return "rgb(" + to256(out[0]) + "," + to256(out[1]) + "," + to256(out[2]) + ")";
      }
  };
  
  color.toRGBA = function(out) {
      return "rgba(" + to256(out[0]) + "," + to256(out[1]) + "," + to256(out[2]) + "," + (mathf.clamp01(out[3]) || 0) + ")";
  };
  
  function toHEX(value) {
      value = mathf.clamp(value * 255, 0, 255) | 0;
  
      if (value < 16) {
          return "0" + value.toString(16);
      } else if (value < 255) {
          return value.toString(16);
      } else {
          return "ff";
      }
  }
  
  color.toHEX = function(out) {
      return "#" + toHEX(out[0]) + toHEX(out[1]) + toHEX(out[2]);
  };
  
  var rgb255 = /^rgb\((\d+),(?:\s+)?(\d+),(?:\s+)?(\d+)\)$/i,
      inv255 = 1 / 255;
  
  color.fromRGB = function(out, style) {
      var values = rgb255.exec(style);
      out[0] = mathf.min(255, Number(values[1])) * inv255;
      out[1] = mathf.min(255, Number(values[2])) * inv255;
      out[2] = mathf.min(255, Number(values[3])) * inv255;
      out[3] = 1;
      return out;
  };
  
  var rgba255 = /^rgba\((\d+),(?:\s+)?(\d+),(?:\s+)?(\d+),(?:\s+)?((?:\.)?\d+(?:\.\d+)?)\)$/i;
  
  color.fromRGBA = function(out, style) {
      var values = rgba255.exec(style);
      out[0] = mathf.min(255, Number(values[1])) * inv255;
      out[1] = mathf.min(255, Number(values[2])) * inv255;
      out[2] = mathf.min(255, Number(values[3])) * inv255;
      out[3] = mathf.min(1, Number(values[4]));
      return out;
  };
  
  var rgb100 = /^rgb\((\d+)\%,(?:\s+)?(\d+)\%,(?:\s+)?(\d+)\%\)$/i,
      inv100 = 1 / 100;
  
  color.fromRGB100 = function(out, style) {
      var values = rgb100.exec(style);
      out[0] = mathf.min(100, Number(values[1])) * inv100;
      out[1] = mathf.min(100, Number(values[2])) * inv100;
      out[2] = mathf.min(100, Number(values[3])) * inv100;
      out[3] = 1;
      return out;
  };
  
  color.fromHEX = function(out, style) {
      out[0] = parseInt(style.substr(1, 2), 16) * inv255;
      out[1] = parseInt(style.substr(3, 2), 16) * inv255;
      out[2] = parseInt(style.substr(5, 2), 16) * inv255;
      out[3] = 1;
      return out;
  };
  
  var hex3to6 = /#(.)(.)(.)/,
      hex3to6String = "#$1$1$2$2$3$3";
  
  color.fromHEX3 = function(out, style) {
      style = style.replace(hex3to6, hex3to6String);
      out[0] = parseInt(style.substr(1, 2), 16) * inv255;
      out[1] = parseInt(style.substr(3, 2), 16) * inv255;
      out[2] = parseInt(style.substr(5, 2), 16) * inv255;
      out[3] = 1;
      return out;
  };
  
  color.fromColorName = function(out, style) {
      return color.fromHEX(out, colorNames[style.toLowerCase()]);
  };
  
  var hex6 = /^\#([0.0-9a-f]{6})$/i,
      hex3 = /^\#([0.0-9a-f])([0.0-9a-f])([0.0-9a-f])$/i,
      colorName = /^(\w+)$/i;
  
  color.fromStyle = function(out, style) {
      if (rgb255.test(style)) {
          return color.fromRGB(out, style);
      } else if (rgba255.test(style)) {
          return color.fromRGBA(out, style);
      } else if (rgb100.test(style)) {
          return color.fromRGB100(out, style);
      } else if (hex6.test(style)) {
          return color.fromHEX(out, style);
      } else if (hex3.test(style)) {
          return color.fromHEX3(out, style);
      } else if (colorName.test(style)) {
          return color.fromColorName(out, style);
      } else {
          return out;
      }
  };
  
  color.colorNames = colorNames;
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/enums/index.js-=@*/
  var objectReverse = require(51);
  
  
  var enums = exports;
  
  
  enums.blending = require(52);
  enums.cullFace = require(53);
  enums.depth = require(54);
  enums.filterMode = require(55);
  
  enums.gl = require(56);
  enums.glValues = objectReverse(enums.gl);
  
  enums.textureFormat = require(57);
  enums.textureType = require(58);
  enums.textureWrap = require(59);
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/WebGLBuffer.js-=@*/
  var WebGLBufferPrototype;
  
  
  module.exports = WebGLBuffer;
  
  
  function WebGLBuffer(context) {
  
      this.context = context;
  
      this.stride = 0;
      this.type = null;
      this.draw = null;
      this.length = null;
      this.glBuffer = null;
      this.needsCompile = true;
  }
  WebGLBufferPrototype = WebGLBuffer.prototype;
  
  WebGLBufferPrototype.destroy = function() {
  
      if (this.glBuffer) {
          this.context.gl.deleteBuffer(this.glBuffer);
          this.glBuffer = null;
          this.needsCompile = true;
      }
  
      return this;
  };
  
  WebGLBufferPrototype.compile = function(type, array, stride, draw) {
      var gl = this.context.gl,
          glBuffer = this.glBuffer || (this.glBuffer = gl.createBuffer());
  
      gl.bindBuffer(type, glBuffer);
      gl.bufferData(type, array, draw);
  
      this.type = type;
      this.stride = stride || 0;
      this.draw = draw;
      this.length = array.length;
  
      this.needsCompile = false;
  
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/WebGLTexture.js-=@*/
  var isArray = require(64),
      isNullOrUndefined = require(13),
      mathf = require(5),
      enums = require(33);
  
  
  var WebGLTexturePrototype,
      textureType = enums.textureType,
      filterMode = enums.filterMode;
  
  
  module.exports = WebGLTexture;
  
  
  function WebGLTexture(context, texture) {
      var _this = this;
  
      this.context = context;
      this.texture = texture;
  
      this.isCubeMap = false;
      this.needsCompile = true;
      this.glTexture = null;
  
      this.__format = null;
      this.__type = null;
      this.__wrap = null;
      this.__isPOT = false;
  
      texture.on("update", function() {
          _this.needsCompile = true;
      });
  }
  WebGLTexturePrototype = WebGLTexture.prototype;
  
  WebGLTexturePrototype.destroy = function() {
  
      if (this.glTexture) {
          this.context.gl.deleteTexture(this.glTexture);
          this.glTexture = null;
          this.needsCompile = true;
      }
  
      return this;
  };
  
  WebGLTexturePrototype.getIsPOT = function() {
      var texture;
  
      if (this.needsCompile) {
          texture = this.texture;
          return (this.__isPOT = mathf.isPowerOfTwo(texture.width) && mathf.isPowerOfTwo(texture.height));
      } else {
          return this.__isPOT;
      }
  
  };
  
  WebGLTexturePrototype.getWidth = function() {
      return this.texture.width;
  };
  
  WebGLTexturePrototype.getHeight = function() {
      return this.texture.height;
  };
  
  WebGLTexturePrototype.getFormat = function() {
      if (this.needsCompile) {
          return (this.__format = getFormat(this.context.gl, this.texture.format));
      } else {
          return this.__format;
      }
  };
  
  WebGLTexturePrototype.getType = function() {
      if (this.needsCompile) {
          return (this.__type = getType(this.context, this.texture.type));
      } else {
          return this.__type;
      }
  };
  
  WebGLTexturePrototype.getWrap = function() {
      if (this.needsCompile) {
          if (this.__isPOT) {
              return (this.__wrap = getWrap(this.context.gl, this.texture.wrap));
          } else {
              return (this.__wrap = this.context.gl.CLAMP_TO_EDGE);
          }
      } else {
          return this.__wrap;
      }
  };
  
  WebGLTexturePrototype.getGLTexture = function() {
      if (this.needsCompile === false) {
          return this.glTexture;
      } else {
          return WebGLTexture_getGLTexture(this);
      }
  };
  
  function WebGLTexture_getGLTexture(_this) {
      var texture = _this.texture,
  
          context = _this.context,
          gl = context.gl,
  
          glTexture = _this.glTexture || (_this.glTexture = gl.createTexture()),
  
          image = texture.data,
          notNull = !isNullOrUndefined(image),
          isCubeMap = isArray(image),
  
          width = texture.width,
          height = texture.height,
          isPOT = _this.getIsPOT(),
  
          generateMipmap = texture.generateMipmap,
          flipY = texture.flipY,
          premultiplyAlpha = texture.premultiplyAlpha,
          anisotropy = texture.anisotropy,
          filter = texture.filter,
  
          format = _this.getFormat(),
          wrap = _this.getWrap(),
          type = _this.getType(),
  
          TFA = (anisotropy > 0) && context.getExtension("EXT_texture_filter_anisotropic"),
          TEXTURE_TYPE = isCubeMap ? gl.TEXTURE_CUBE_MAP : gl.TEXTURE_2D,
          minFilter, magFilter, images, i, il;
  
      if (TFA) {
          anisotropy = mathf.clamp(anisotropy, 1, context.__maxAnisotropy);
      }
  
      if (notNull) {
          if (isCubeMap) {
              images = [];
              i = -1;
              il = image.length - 1;
  
              while (i++ < il) {
                  images[i] = context.clampMaxSize(image[i], isCubeMap);
              }
          } else {
              image = context.clampMaxSize(image, false);
          }
      }
  
      if (filter === filterMode.NONE) {
          magFilter = gl.NEAREST;
          minFilter = isPOT && generateMipmap ? gl.LINEAR_MIPMAP_NEAREST : gl.NEAREST;
      } else { //filterMode.LINEAR
          magFilter = gl.LINEAR;
          minFilter = isPOT && generateMipmap ? gl.LINEAR_MIPMAP_LINEAR : gl.LINEAR;
      }
  
      gl.bindTexture(TEXTURE_TYPE, glTexture);
  
      gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY ? 1 : 0);
      gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha ? 1 : 0);
  
      if (notNull) {
          if (isCubeMap) {
              i = images.length;
              while (i--) {
                  gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, format, format, type, images[i]);
              }
          } else {
              gl.texImage2D(TEXTURE_TYPE, 0, format, format, type, image);
          }
      } else {
          if (isCubeMap) {
              i = image.length;
              while (i--) {
                  gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, format, width, height, 0, format, type, null);
              }
          } else {
              if (type === textureType.DEPTH_COMPONENT) {
                  gl.texImage2D(TEXTURE_TYPE, 0, type, width, height, 0, type, gl.UNSIGNED_SHORT, null);
              } else {
                  gl.texImage2D(TEXTURE_TYPE, 0, format, width, height, 0, format, type, null);
              }
          }
      }
  
      gl.texParameteri(TEXTURE_TYPE, gl.TEXTURE_MAG_FILTER, magFilter);
      gl.texParameteri(TEXTURE_TYPE, gl.TEXTURE_MIN_FILTER, minFilter);
  
      gl.texParameteri(TEXTURE_TYPE, gl.TEXTURE_WRAP_S, wrap);
      gl.texParameteri(TEXTURE_TYPE, gl.TEXTURE_WRAP_T, wrap);
  
      if (TFA) {
          gl.texParameterf(TEXTURE_TYPE, TFA.TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
      }
      if (generateMipmap && isPOT) {
          gl.generateMipmap(TEXTURE_TYPE);
      }
  
      _this.isCubeMap = isCubeMap;
      _this.needsCompile = false;
  
      gl.bindTexture(TEXTURE_TYPE, null);
  
      return glTexture;
  }
  
  function getFormat(gl, format) {
      switch (format) {
          case gl.RGB:
              return gl.RGB;
          case gl.ALPHA:
              return gl.ALPHA;
          case gl.LUMINANCE:
              return gl.LUMINANCE;
          case gl.LUMINANCE_ALPHA:
              return gl.LUMINANCE_ALPHA;
          default:
              return gl.RGBA;
      }
  }
  
  function getType(context, type) {
      var gl = context.gl;
  
      if (
          (type === textureType.FLOAT && !context.getExtension("OES_texture_float")) ||
          (type === textureType.DEPTH_COMPONENT && !context.getExtension("WEBGL_depth_texture"))
      ) {
          type = textureType.UNSIGNED_BYTE;
      }
  
      switch (type) {
          case gl.FLOAT:
              return gl.FLOAT;
          case gl.DEPTH_COMPONENT:
              return gl.DEPTH_COMPONENT;
          case gl.UNSIGNED_SHORT:
              return gl.UNSIGNED_SHORT;
          case gl.UNSIGNED_SHORT_5_6_5:
              return gl.UNSIGNED_SHORT_5_6_5;
          case gl.UNSIGNED_SHORT_4_4_4_4:
              return gl.UNSIGNED_SHORT_4_4_4_4;
          case gl.UNSIGNED_SHORT_5_5_5_1:
              return gl.UNSIGNED_SHORT_5_5_5_1;
          default:
              return gl.UNSIGNED_BYTE;
      }
  }
  
  function getWrap(gl, wrap) {
      switch (wrap) {
          case gl.REPEAT:
              return gl.REPEAT;
          case gl.MIRRORED_REPEAT:
              return gl.MIRRORED_REPEAT;
          default:
              return gl.CLAMP_TO_EDGE;
      }
  }
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/WebGLFrameBuffer.js-=@*/
  var WebGLFrameBufferPrototype;
  
  
  module.exports = WebGLFrameBuffer;
  
  
  function WebGLFrameBuffer(context, framebuffer) {
      var _this = this;
  
      this.context = context;
  
      this.__lastTexture = null;
      this.isCubeMap = false;
      this.framebuffer = framebuffer;
  
      this.needsCompile = true;
  
      this.glFrameBuffer = null;
      this.glRenderBuffer = null;
  
      framebuffer.on("update", function() {
          _this.needsCompile = true;
      });
  }
  WebGLFrameBufferPrototype = WebGLFrameBuffer.prototype;
  
  function WebGLFrameBuffer_needsCompile(_this) {
      var context = _this.context,
          framebuffer = _this.framebuffer,
          texture = framebuffer.texture;
  
      return (
          _this.needsCompile ||
          _this.__lastTexture !== texture ||
          context.createTexture(texture).needsCompile
      );
  }
  
  WebGLFrameBufferPrototype.destroy = function() {
      var glFrameBuffer = this.glFrameBuffer,
          glRenderBuffer = this.glRenderBuffer,
          gl, i;
  
      if (glFrameBuffer && glRenderBuffer) {
          gl = this.context.gl;
  
          if (this.isCubeMap) {
              i = 6;
              while (i--) {
                  gl.deleteFramebuffer(glFrameBuffer[i]);
                  gl.deleteRenderbuffer(glRenderBuffer[i]);
              }
          } else {
              gl.deleteFramebuffer(glFrameBuffer);
              gl.deleteRenderbuffer(glRenderBuffer);
          }
  
          this.glFrameBuffer = null;
          this.glRenderBuffer = null;
          this.needsCompile = true;
      }
  
      return this;
  };
  
  WebGLFrameBufferPrototype.getGLFrameBuffer = function() {
      if (WebGLFrameBuffer_needsCompile(this)) {
          return WebGLFrameBuffer_compile(this).glFrameBuffer;
      } else {
          return this.glFrameBuffer;
      }
  };
  
  WebGLFrameBufferPrototype.getGLRenderBuffer = function() {
      if (WebGLFrameBuffer_needsCompile(this)) {
          return WebGLFrameBuffer_compile(this).glRenderBuffer;
      } else {
          return this.glRenderBuffer;
      }
  };
  
  function WebGLFrameBuffer_compile(_this) {
      var context = _this.context,
          gl = context.gl,
  
          framebuffer = _this.framebuffer,
          depthBuffer = framebuffer.depthBuffer,
          stencilBuffer = framebuffer.stencilBuffer,
  
          texture = framebuffer.texture,
          webglTexture = context.createTexture(texture),
  
          glTexture = webglTexture.getGLTexture(),
  
          isCubeMap = webglTexture.isCubeMap,
  
          width = webglTexture.getWidth(),
          height = webglTexture.getHeight(),
  
          glFrameBuffer, glRenderBuffer, i;
  
      if (isCubeMap) {
          glFrameBuffer = new Array(6);
          glRenderBuffer = new Array(6);
      }
  
      if (isCubeMap) {
          i = 6;
          while (i--) {
              glFrameBuffer[i] = gl.createFramebuffer();
              glRenderBuffer[i] = gl.createRenderbuffer();
  
              setupFrameBuffer(gl, glFrameBuffer[i], gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, glTexture);
              setupRenderBuffer(gl, glRenderBuffer[i], width, height, depthBuffer, stencilBuffer);
          }
      } else {
          glFrameBuffer = gl.createFramebuffer();
          glRenderBuffer = gl.createRenderbuffer();
  
          setupFrameBuffer(gl, glFrameBuffer, gl.TEXTURE_2D, glTexture);
          setupRenderBuffer(gl, glRenderBuffer, width, height, depthBuffer, stencilBuffer);
      }
  
      _this.__lastTexture = texture;
      _this.glFrameBuffer = glFrameBuffer;
      _this.glRenderBuffer = glRenderBuffer;
      _this.isCubeMap = isCubeMap;
  
      _this.needsCompile = false;
  
      gl.bindRenderbuffer(gl.RENDERBUFFER, null);
      gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  
      return _this;
  }
  
  function setupFrameBuffer(gl, glFrameBuffer, glTextureTarget, glTexture) {
      gl.bindFramebuffer(gl.FRAMEBUFFER, glFrameBuffer);
      gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, glTextureTarget, glTexture, 0);
  }
  
  function setupRenderBuffer(gl, glRenderBuffer, width, height, depthBuffer, stencilBuffer) {
      gl.bindRenderbuffer(gl.RENDERBUFFER, glRenderBuffer);
  
      if (depthBuffer && !stencilBuffer) {
  
          gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
          gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, glRenderBuffer);
          /* Not working. Defaulting to RGBA4.
          } else if (!depthBuffer && stencilBuffer) {
              
              gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, width, height);
              gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, glRenderBuffer);
          */
      } else if (depthBuffer && stencilBuffer) {
  
          gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
          gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, glRenderBuffer);
  
      } else {
          gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, width, height);
      }
  }
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/WebGLProgram.js-=@*/
  var isArray = require(64),
      FastHash = require(67),
  
      enums = require(33),
      uniforms = require(68),
      attributes = require(69);
  
  
  var reUniformName = /[^\[]+/,
      WebGLProgramPrototype;
  
  
  module.exports = WebGLProgram;
  
  
  function WebGLProgram(context) {
  
      this.context = context;
  
      this.floatPrecision = context.__precision;
      this.intPrecision = context.__precision;
  
      this.uniforms = new FastHash("name");
      this.attributes = new FastHash("name");
  
      this.needsCompile = true;
      this.glProgram = null;
  }
  WebGLProgramPrototype = WebGLProgram.prototype;
  
  WebGLProgramPrototype.destroy = function() {
  
      if (this.glProgram) {
          this.context.gl.deleteProgram(this.glProgram);
          this.glProgram = null;
          this.needsCompile = true;
      }
  
      return this;
  };
  
  WebGLProgramPrototype.compile = function(vertex, fragment) {
      var context = this.context,
          floatPrecision = this.floatPrecision,
          intPrecision = this.intPrecision,
          uniforms = this.uniforms,
          attributes = this.attributes,
          gl = context.gl,
          glProgram = this.glProgram;
  
      if (glProgram) {
          uniforms.clear();
          attributes.clear();
          gl.deleteProgram(glProgram);
      }
  
      glProgram = this.glProgram = createProgram(
          gl,
          prependPrecision(floatPrecision, intPrecision, vertex),
          prependPrecision(floatPrecision, intPrecision, fragment)
      );
  
      parseUniforms(gl, context, glProgram, uniforms);
      parseAttributes(gl, context, glProgram, attributes);
  
      this.needsCompile = false;
  
      return this;
  };
  
  function parseUniforms(gl, context, glProgram, hash) {
      var length = gl.getProgramParameter(glProgram, gl.ACTIVE_UNIFORMS),
          glValues = enums.glValues,
          i = -1,
          il = length - 1,
          uniform, name, location;
  
      while (i++ < il) {
          uniform = gl.getActiveUniform(glProgram, i);
          name = reUniformName.exec(uniform.name)[0];
          location = gl.getUniformLocation(glProgram, name);
          hash.add(new uniforms[glValues[uniform.type]](context, name, location, uniform.size));
      }
  }
  
  function parseAttributes(gl, context, glProgram, hash) {
      var length = gl.getProgramParameter(glProgram, gl.ACTIVE_ATTRIBUTES),
          glValues = enums.glValues,
          i = -1,
          il = length - 1,
          attribute, name, location;
  
      while (i++ < il) {
          attribute = gl.getActiveAttrib(glProgram, i);
          name = attribute.name;
          location = gl.getAttribLocation(glProgram, name);
          hash.add(new attributes[glValues[attribute.type]](context, name, location));
      }
  }
  
  function prependPrecision(floatPrecision, intPrecision, shader) {
      return "precision " + floatPrecision + " float;\nprecision " + intPrecision + " int;\n" + shader;
  }
  
  function createProgram(gl, vertex, fragment) {
      var program = gl.createProgram(),
          shader, i, il, programInfoLog;
  
      vertex = isArray(vertex) ? vertex : [vertex];
      fragment = isArray(fragment) ? fragment : [fragment];
  
      i = -1;
      il = vertex.length - 1;
      while (i++ < il) {
          shader = createShader(gl, vertex[i], gl.VERTEX_SHADER);
          gl.attachShader(program, shader);
          gl.deleteShader(shader);
      }
  
      i = -1;
      il = fragment.length - 1;
      while (i++ < il) {
          shader = createShader(gl, fragment[i], gl.FRAGMENT_SHADER);
          gl.attachShader(program, shader);
          gl.deleteShader(shader);
      }
  
      gl.linkProgram(program);
      gl.validateProgram(program);
      gl.useProgram(program);
  
      if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
          programInfoLog = gl.getProgramInfoLog(program);
          gl.deleteProgram(program);
          throw new Error("createProgram: problem compiling Program " + programInfoLog);
      }
  
      return program;
  }
  
  function createShader(gl, source, type) {
      var shader = gl.createShader(type),
          shaderInfoLog;
  
      gl.shaderSource(shader, source);
      gl.compileShader(shader);
  
      if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
          shaderInfoLog = gl.getShaderInfoLog(shader);
          gl.deleteShader(shader);
          throw new Error("createShader: problem compiling shader " + shaderInfoLog);
      }
  
      return shader;
  }
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/inherits@0.0.3/src/index.js-=@*/
  var create = require(40),
      extend = require(41),
      mixin = require(42),
      defineProperty = require(43);
  
  
  var descriptor = {
      configurable: true,
      enumerable: false,
      writable: true,
      value: null
  };
  
  
  module.exports = inherits;
  
  
  function inherits(child, parent) {
  
      mixin(child, parent);
  
      if (child.__super) {
          child.prototype = extend(create(parent.prototype), child.__super, child.prototype);
      } else {
          child.prototype = extend(create(parent.prototype), child.prototype);
      }
  
      defineNonEnumerableProperty(child, "__super", parent.prototype);
      defineNonEnumerableProperty(child.prototype, "constructor", child);
  
      child.defineStatic = defineStatic;
      child.super_ = parent;
  
      return child;
  }
  inherits.defineProperty = defineNonEnumerableProperty;
  
  function defineNonEnumerableProperty(object, name, value) {
      descriptor.value = value;
      defineProperty(object, name, descriptor);
      descriptor.value = null;
  }
  
  function defineStatic(name, value) {
      defineNonEnumerableProperty(this, name, value);
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/fast_slice@0.0.1/src/index.js-=@*/
  var clamp = require(9),
      isNumber = require(7);
  
  
  module.exports = fastSlice;
  
  
  function fastSlice(array, offset) {
      var length = array.length,
          newLength, i, il, result, j;
  
      offset = clamp(isNumber(offset) ? offset : 0, 0, length);
      i = offset - 1;
      il = length - 1;
      newLength = length - offset;
      result = new Array(newLength);
      j = 0;
  
      while (i++ < il) {
          result[j++] = array[i];
      }
  
      return result;
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/create@0.0.2/src/index.js-=@*/
  var isNull = require(18),
      isNative = require(12),
      isPrimitive = require(44);
  
  
  var nativeCreate = Object.create;
  
  
  module.exports = create;
  
  
  function create(object) {
      return nativeCreate(isPrimitive(object) ? null : object);
  }
  
  if (!isNative(nativeCreate)) {
      nativeCreate = function nativeCreate(object) {
          var newObject;
  
          function F() {
              this.constructor = F;
          }
  
          if (isNull(object)) {
              F.prototype = null;
              newObject = new F();
              newObject.constructor = newObject.__proto__ = null;
              delete newObject.__proto__;
              return newObject;
          } else {
              F.prototype = object;
              return new F();
          }
      };
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/extend@0.0.2/src/index.js-=@*/
  var keys = require(45),
      isNative = require(12);
  
  
  var nativeAssign = Object.assign,
      extend, baseExtend;
  
  
  if (isNative(nativeAssign)) {
      extend = nativeAssign;
  } else {
      extend = function extend(out) {
          var i = 0,
              il = arguments.length - 1;
  
          while (i++ < il) {
              baseExtend(out, arguments[i]);
          }
  
          return out;
      };
      baseExtend = function baseExtend(a, b) {
          var objectKeys = keys(b),
              i = -1,
              il = objectKeys.length - 1,
              key;
  
          while (i++ < il) {
              key = objectKeys[i];
              a[key] = b[key];
          }
      };
  }
  
  
  module.exports = extend;
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/mixin@0.0.2/src/index.js-=@*/
  var keys = require(8),
      isNullOrUndefined = require(13);
  
  
  module.exports = mixin;
  
  
  function mixin(out) {
      var i = 0,
          il = arguments.length - 1;
  
      while (i++ < il) {
          baseMixin(out, arguments[i]);
      }
  
      return out;
  }
  
  function baseMixin(a, b) {
      var objectKeys = keys(b),
          i = -1,
          il = objectKeys.length - 1,
          key, value;
  
      while (i++ < il) {
          key = objectKeys[i];
  
          if (isNullOrUndefined(a[key]) && !isNullOrUndefined((value = b[key]))) {
              a[key] = value;
          }
      }
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/define_property@0.0.2/src/index.js-=@*/
  var isObject = require(14),
      isFunction = require(16),
      isPrimitive = require(44),
      isNative = require(12),
      has = require(46);
  
  
  var nativeDefineProperty = Object.defineProperty;
  
  
  module.exports = defineProperty;
  
  
  function defineProperty(object, name, descriptor) {
      if (isPrimitive(descriptor) || isFunction(descriptor)) {
          descriptor = {
              value: descriptor
          };
      }
      return nativeDefineProperty(object, name, descriptor);
  }
  
  defineProperty.hasGettersSetters = true;
  
  if (!isNative(nativeDefineProperty) || !(function() {
          var object = {},
              value = {};
  
          try {
              nativeDefineProperty(object, "key", {
                  value: value
              });
              if (has(object, "key") && object.key === value) {
                  return true;
              } else {
                  return false;
              }
          } catch (e) {}
  
          return false;
      }())) {
  
      defineProperty.hasGettersSetters = false;
  
      nativeDefineProperty = function defineProperty(object, name, descriptor) {
          if (!isObject(object)) {
              throw new TypeError("defineProperty(object, name, descriptor) called on non-object");
          }
          if (has(descriptor, "get") || has(descriptor, "set")) {
              throw new TypeError("defineProperty(object, name, descriptor) this environment does not support getters or setters");
          }
          object[name] = descriptor.value;
      };
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/is_primitive@0.0.2/src/index.js-=@*/
  var isNullOrUndefined = require(13);
  
  
  module.exports = isPrimitive;
  
  
  function isPrimitive(obj) {
      var typeStr;
      return isNullOrUndefined(obj) || ((typeStr = typeof(obj)) !== "object" && typeStr !== "function") || false;
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/keys@0.0.1/src/index.js-=@*/
  var has = require(46),
      isNative = require(12),
      isNullOrUndefined = require(13),
      isObject = require(14);
  
  
  var nativeKeys = Object.keys;
  
  
  module.exports = keys;
  
  
  function keys(value) {
      if (isNullOrUndefined(value)) {
          return [];
      } else {
          return nativeKeys(isObject(value) ? value : Object(value));
      }
  }
  
  if (!isNative(nativeKeys)) {
      nativeKeys = function keys(value) {
          var localHas = has,
              out = [],
              i = 0,
              key;
  
          for (key in value) {
              if (localHas(value, key)) {
                  out[i++] = key;
              }
          }
  
          return out;
      };
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/has@0.0.1/src/index.js-=@*/
  var isNative = require(12),
      getPrototypeOf = require(15),
      isNullOrUndefined = require(13);
  
  
  var nativeHasOwnProp = Object.prototype.hasOwnProperty,
      baseHas;
  
  
  module.exports = has;
  
  
  function has(object, key) {
      if (isNullOrUndefined(object)) {
          return false;
      } else {
          return baseHas(object, key);
      }
  }
  
  if (isNative(nativeHasOwnProp)) {
      baseHas = function baseHas(object, key) {
          if (object.hasOwnProperty) {
              return object.hasOwnProperty(key);
          } else {
              return nativeHasOwnProp.call(object, key);
          }
      };
  } else {
      baseHas = function baseHas(object, key) {
          var proto = getPrototypeOf(object);
  
          if (isNullOrUndefined(proto)) {
              return key in object;
          } else {
              return (key in object) && (!(key in proto) || proto[key] !== object[key]);
          }
      };
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/event_listener@0.0.2/src/event_table.js-=@*/
  var isNode = require(48),
      environment = require(22);
  
  
  var window = environment.window,
  
      XMLHttpRequest = window.XMLHttpRequest,
      OfflineAudioContext = window.OfflineAudioContext;
  
  
  function returnEvent() {
      return window.Event;
  }
  
  
  module.exports = {
      abort: function(target) {
          if (XMLHttpRequest && target instanceof XMLHttpRequest) {
              return window.ProgressEvent || window.Event;
          } else {
              return window.UIEvent || window.Event;
          }
      },
  
      afterprint: returnEvent,
  
      animationend: function() {
          return window.AnimationEvent || window.Event;
      },
      animationiteration: function() {
          return window.AnimationEvent || window.Event;
      },
      animationstart: function() {
          return window.AnimationEvent || window.Event;
      },
  
      audioprocess: function() {
          return window.AudioProcessingEvent || window.Event;
      },
  
      beforeprint: returnEvent,
      beforeunload: function() {
          return window.BeforeUnloadEvent || window.Event;
      },
      beginevent: function() {
          return window.TimeEvent || window.Event;
      },
  
      blocked: returnEvent,
      blur: function() {
          return window.FocusEvent || window.Event;
      },
  
      cached: returnEvent,
      canplay: returnEvent,
      canplaythrough: returnEvent,
      chargingchange: returnEvent,
      chargingtimechange: returnEvent,
      checking: returnEvent,
  
      click: function() {
          return window.MouseEvent || window.Event;
      },
  
      close: returnEvent,
      compassneedscalibration: function() {
          return window.SensorEvent || window.Event;
      },
      complete: function(target) {
          if (OfflineAudioContext && target instanceof OfflineAudioContext) {
              return window.OfflineAudioCompletionEvent || window.Event;
          } else {
              return window.Event;
          }
      },
  
      compositionend: function() {
          return window.CompositionEvent || window.Event;
      },
      compositionstart: function() {
          return window.CompositionEvent || window.Event;
      },
      compositionupdate: function() {
          return window.CompositionEvent || window.Event;
      },
  
      contextmenu: function() {
          return window.MouseEvent || window.Event;
      },
      copy: function() {
          return window.ClipboardEvent || window.Event;
      },
      cut: function() {
          return window.ClipboardEvent || window.Event;
      },
  
      dblclick: function() {
          return window.MouseEvent || window.Event;
      },
      devicelight: function() {
          return window.DeviceLightEvent || window.Event;
      },
      devicemotion: function() {
          return window.DeviceMotionEvent || window.Event;
      },
      deviceorientation: function() {
          return window.DeviceOrientationEvent || window.Event;
      },
      deviceproximity: function() {
          return window.DeviceProximityEvent || window.Event;
      },
  
      dischargingtimechange: returnEvent,
  
      DOMActivate: function() {
          return window.UIEvent || window.Event;
      },
      DOMAttributeNameChanged: function() {
          return window.MutationNameEvent || window.Event;
      },
      DOMAttrModified: function() {
          return window.MutationEvent || window.Event;
      },
      DOMCharacterDataModified: function() {
          return window.MutationEvent || window.Event;
      },
      DOMContentLoaded: returnEvent,
      DOMElementNameChanged: function() {
          return window.MutationNameEvent || window.Event;
      },
      DOMFocusIn: function() {
          return window.FocusEvent || window.Event;
      },
      DOMFocusOut: function() {
          return window.FocusEvent || window.Event;
      },
      DOMNodeInserted: function() {
          return window.MutationEvent || window.Event;
      },
      DOMNodeInsertedIntoDocument: function() {
          return window.MutationEvent || window.Event;
      },
      DOMNodeRemoved: function() {
          return window.MutationEvent || window.Event;
      },
      DOMNodeRemovedFromDocument: function() {
          return window.MutationEvent || window.Event;
      },
      DOMSubtreeModified: function() {
          return window.FocusEvent || window.Event;
      },
      downloading: returnEvent,
  
      drag: function() {
          return window.DragEvent || window.Event;
      },
      dragend: function() {
          return window.DragEvent || window.Event;
      },
      dragenter: function() {
          return window.DragEvent || window.Event;
      },
      dragleave: function() {
          return window.DragEvent || window.Event;
      },
      dragover: function() {
          return window.DragEvent || window.Event;
      },
      dragstart: function() {
          return window.DragEvent || window.Event;
      },
      drop: function() {
          return window.DragEvent || window.Event;
      },
  
      durationchange: returnEvent,
      ended: returnEvent,
  
      endEvent: function() {
          return window.TimeEvent || window.Event;
      },
      error: function(target) {
          if (XMLHttpRequest && target instanceof XMLHttpRequest) {
              return window.ProgressEvent || window.Event;
          } else if (isNode(target)) {
              return window.UIEvent || window.Event;
          } else {
              return window.Event;
          }
      },
      focus: function() {
          return window.FocusEvent || window.Event;
      },
      focusin: function() {
          return window.FocusEvent || window.Event;
      },
      focusout: function() {
          return window.FocusEvent || window.Event;
      },
  
      fullscreenchange: returnEvent,
      fullscreenerror: returnEvent,
  
      gamepadconnected: function() {
          return window.GamepadEvent || window.Event;
      },
      gamepaddisconnected: function() {
          return window.GamepadEvent || window.Event;
      },
  
      hashchange: function() {
          return window.HashChangeEvent || window.Event;
      },
  
      input: returnEvent,
      invalid: returnEvent,
  
      keydown: function() {
          return window.KeyboardEvent || window.Event;
      },
      keyup: function() {
          return window.KeyboardEvent || window.Event;
      },
      keypress: function() {
          return window.KeyboardEvent || window.Event;
      },
  
      languagechange: returnEvent,
      levelchange: returnEvent,
  
      load: function(target) {
          if (XMLHttpRequest && target instanceof XMLHttpRequest) {
              return window.ProgressEvent || window.Event;
          } else {
              return window.UIEvent || window.Event;
          }
      },
  
      loadeddata: returnEvent,
      loadedmetadata: returnEvent,
  
      loadend: function() {
          return window.ProgressEvent || window.Event;
      },
      loadstart: function() {
          return window.ProgressEvent || window.Event;
      },
  
      message: function() {
          return window.MessageEvent || window.Event;
      },
  
      mousedown: function() {
          return window.MouseEvent || window.Event;
      },
      mouseenter: function() {
          return window.MouseEvent || window.Event;
      },
      mouseleave: function() {
          return window.MouseEvent || window.Event;
      },
      mousemove: function() {
          return window.MouseEvent || window.Event;
      },
      mouseout: function() {
          return window.MouseEvent || window.Event;
      },
      mouseover: function() {
          return window.MouseEvent || window.Event;
      },
      mouseup: function() {
          return window.MouseEvent || window.Event;
      },
  
      noupdate: returnEvent,
      obsolete: returnEvent,
      offline: returnEvent,
      online: returnEvent,
      open: returnEvent,
      orientationchange: returnEvent,
  
      pagehide: function() {
          return window.PageTransitionEvent || window.Event;
      },
      pageshow: function() {
          return window.PageTransitionEvent || window.Event;
      },
  
      paste: function() {
          return window.ClipboardEvent || window.Event;
      },
      pause: returnEvent,
      pointerlockchange: returnEvent,
      pointerlockerror: returnEvent,
      play: returnEvent,
      playing: returnEvent,
  
      popstate: function() {
          return window.PopStateEvent || window.Event;
      },
      progress: function() {
          return window.ProgressEvent || window.Event;
      },
  
      ratechange: returnEvent,
      readystatechange: returnEvent,
  
      repeatevent: function() {
          return window.TimeEvent || window.Event;
      },
  
      reset: returnEvent,
  
      resize: function() {
          return window.UIEvent || window.Event;
      },
      scroll: function() {
          return window.UIEvent || window.Event;
      },
  
      seeked: returnEvent,
      seeking: returnEvent,
  
      select: function() {
          return window.UIEvent || window.Event;
      },
      show: function() {
          return window.MouseEvent || window.Event;
      },
      stalled: returnEvent,
      storage: function() {
          return window.StorageEvent || window.Event;
      },
      submit: returnEvent,
      success: returnEvent,
      suspend: returnEvent,
  
      SVGAbort: function() {
          return window.SVGEvent || window.Event;
      },
      SVGError: function() {
          return window.SVGEvent || window.Event;
      },
      SVGLoad: function() {
          return window.SVGEvent || window.Event;
      },
      SVGResize: function() {
          return window.SVGEvent || window.Event;
      },
      SVGScroll: function() {
          return window.SVGEvent || window.Event;
      },
      SVGUnload: function() {
          return window.SVGEvent || window.Event;
      },
      SVGZoom: function() {
          return window.SVGEvent || window.Event;
      },
      timeout: function() {
          return window.ProgressEvent || window.Event;
      },
  
      timeupdate: returnEvent,
  
      touchcancel: function() {
          return window.TouchEvent || window.Event;
      },
      touchend: function() {
          return window.TouchEvent || window.Event;
      },
      touchenter: function() {
          return window.TouchEvent || window.Event;
      },
      touchleave: function() {
          return window.TouchEvent || window.Event;
      },
      touchmove: function() {
          return window.TouchEvent || window.Event;
      },
      touchstart: function() {
          return window.TouchEvent || window.Event;
      },
  
      transitionend: function() {
          return window.TransitionEvent || window.Event;
      },
      unload: function() {
          return window.UIEvent || window.Event;
      },
  
      updateready: returnEvent,
      upgradeneeded: returnEvent,
  
      userproximity: function() {
          return window.SensorEvent || window.Event;
      },
  
      visibilitychange: returnEvent,
      volumechange: returnEvent,
      waiting: returnEvent,
  
      wheel: function() {
          return window.WheelEvent || window.Event;
      }
  };
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/is_node@0.0.1/src/index.js-=@*/
  var isString = require(21),
      isNullOrUndefined = require(13),
      isNumber = require(7),
      isFunction = require(16);
  
  
  var isNode;
  
  
  if (typeof(Node) !== "undefined" && isFunction(Node)) {
      isNode = function isNode(value) {
          return value instanceof Node;
      };
  } else {
      isNode = function isNode(value) {
          return (!isNullOrUndefined(value) &&
              isNumber(value.nodeType) &&
              isString(value.nodeName)
          );
      };
  }
  
  
  module.exports = isNode;
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/vec4@0.0.3/src/index.js-=@*/
  var mathf = require(5),
      isNumber = require(7);
  
  
  var vec4 = exports;
  
  
  vec4.ArrayType = typeof(Float32Array) !== "undefined" ? Float32Array : mathf.ArrayType;
  
  
  vec4.create = function(x, y, z, w) {
      var out = new vec4.ArrayType(4);
  
      out[0] = isNumber(x) ? x : 0;
      out[1] = isNumber(y) ? y : 0;
      out[2] = isNumber(z) ? z : 0;
      out[3] = isNumber(w) ? w : 1;
  
      return out;
  };
  
  vec4.copy = function(out, a) {
  
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
  
      return out;
  };
  
  vec4.clone = function(a) {
      var out = new vec4.ArrayType(4);
  
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
  
      return out;
  };
  
  vec4.set = function(out, x, y, z, w) {
  
      out[0] = isNumber(x) ? x : 0;
      out[1] = isNumber(y) ? y : 0;
      out[2] = isNumber(z) ? z : 0;
      out[3] = isNumber(w) ? w : 1;
  
      return out;
  };
  
  vec4.add = function(out, a, b) {
  
      out[0] = a[0] + b[0];
      out[1] = a[1] + b[1];
      out[2] = a[2] + b[2];
      out[3] = a[3] + b[3];
  
      return out;
  };
  
  vec4.sub = function(out, a, b) {
  
      out[0] = a[0] - b[0];
      out[1] = a[1] - b[1];
      out[2] = a[2] - b[2];
      out[3] = a[3] - b[3];
  
      return out;
  };
  
  vec4.mul = function(out, a, b) {
  
      out[0] = a[0] * b[0];
      out[1] = a[1] * b[1];
      out[2] = a[2] * b[2];
      out[3] = a[3] * b[3];
  
      return out;
  };
  
  vec4.div = function(out, a, b) {
      var bx = b[0],
          by = b[1],
          bz = b[2],
          bw = b[3];
  
      out[0] = a[0] * (bx !== 0 ? 1 / bx : bx);
      out[1] = a[1] * (by !== 0 ? 1 / by : by);
      out[2] = a[2] * (bz !== 0 ? 1 / bz : bz);
      out[3] = a[3] * (bw !== 0 ? 1 / bw : bw);
  
      return out;
  };
  
  vec4.sadd = function(out, a, s) {
  
      out[0] = a[0] + s;
      out[1] = a[1] + s;
      out[2] = a[2] + s;
      out[3] = a[3] + s;
  
      return out;
  };
  
  vec4.ssub = function(out, a, s) {
  
      out[0] = a[0] - s;
      out[1] = a[1] - s;
      out[2] = a[2] - s;
      out[3] = a[3] - s;
  
      return out;
  };
  
  vec4.smul = function(out, a, s) {
  
      out[0] = a[0] * s;
      out[1] = a[1] * s;
      out[2] = a[2] * s;
      out[3] = a[3] * s;
  
      return out;
  };
  
  vec4.sdiv = function(out, a, s) {
      s = s !== 0 ? 1 / s : s;
  
      out[0] = a[0] * s;
      out[1] = a[1] * s;
      out[2] = a[2] * s;
      out[3] = a[3] * s;
  
      return out;
  };
  
  vec4.lengthSqValues = function(x, y, z, w) {
  
      return x * x + y * y + z * z + w * w;
  };
  
  vec4.lengthValues = function(x, y, z, w) {
      var lsq = vec4.lengthSqValues(x, y, z, w);
  
      return lsq !== 0 ? mathf.sqrt(lsq) : lsq;
  };
  
  vec4.invLengthValues = function(x, y, z, w) {
      var lsq = vec4.lengthSqValues(x, y, z, w);
  
      return lsq !== 0 ? 1 / mathf.sqrt(lsq) : lsq;
  };
  
  vec4.dot = function(a, b) {
      return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
  };
  
  vec4.lengthSq = function(a) {
  
      return vec4.dot(a, a);
  };
  
  vec4.length = function(a) {
      var lsq = vec4.lengthSq(a);
  
      return lsq !== 0 ? mathf.sqrt(lsq) : lsq;
  };
  
  vec4.invLength = function(a) {
      var lsq = vec4.lengthSq(a);
  
      return lsq !== 0 ? 1 / mathf.sqrt(lsq) : lsq;
  };
  
  vec4.setLength = function(out, a, length) {
      var x = a[0],
          y = a[1],
          z = a[2],
          w = a[3],
          s = length * vec4.invLengthValues(x, y, z, w);
  
      out[0] = x * s;
      out[1] = y * s;
      out[2] = z * s;
      out[3] = w * s;
  
      return out;
  };
  
  vec4.normalize = function(out, a) {
      var x = a[0],
          y = a[1],
          z = a[2],
          w = a[3],
          lsq = vec4.invLengthValues(x, y, z, w);
  
      out[0] = x * lsq;
      out[1] = y * lsq;
      out[2] = z * lsq;
      out[3] = w * lsq;
  
      return out;
  };
  
  vec4.inverse = function(out, a) {
  
      out[0] = a[0] * -1;
      out[1] = a[1] * -1;
      out[2] = a[2] * -1;
      out[3] = a[3] * -1;
  
      return out;
  };
  
  vec4.lerp = function(out, a, b, x) {
      var lerp = mathf.lerp;
  
      out[0] = lerp(a[0], b[0], x);
      out[1] = lerp(a[1], b[1], x);
      out[2] = lerp(a[2], b[2], x);
      out[3] = lerp(a[3], b[3], x);
  
      return out;
  };
  
  vec4.min = function(out, a, b) {
      var ax = a[0],
          ay = a[1],
          az = a[2],
          aw = a[3],
          bx = b[0],
          by = b[1],
          bz = b[2],
          bw = b[3];
  
      out[0] = bx < ax ? bx : ax;
      out[1] = by < ay ? by : ay;
      out[2] = bz < az ? bz : az;
      out[3] = bw < aw ? bw : aw;
  
      return out;
  };
  
  vec4.max = function(out, a, b) {
      var ax = a[0],
          ay = a[1],
          az = a[2],
          aw = a[3],
          bx = b[0],
          by = b[1],
          bz = b[2],
          bw = b[3];
  
      out[0] = bx > ax ? bx : ax;
      out[1] = by > ay ? by : ay;
      out[2] = bz > az ? bz : az;
      out[3] = bw > aw ? bw : aw;
  
      return out;
  };
  
  vec4.clamp = function(out, a, min, max) {
      var x = a[0],
          y = a[1],
          z = a[2],
          w = a[3],
          minx = min[0],
          miny = min[1],
          minz = min[2],
          minw = min[3],
          maxx = max[0],
          maxy = max[1],
          maxz = max[2],
          maxw = max[3];
  
      out[0] = x < minx ? minx : x > maxx ? maxx : x;
      out[1] = y < miny ? miny : y > maxy ? maxy : y;
      out[2] = z < minz ? minz : z > maxz ? maxz : z;
      out[3] = w < minw ? minw : w > maxw ? maxw : w;
  
      return out;
  };
  
  vec4.transformMat4 = function(out, a, m) {
      var x = a[0],
          y = a[1],
          z = a[2],
          w = a[3];
  
      out[0] = x * m[0] + y * m[4] + z * m[8] + w * m[12];
      out[1] = x * m[1] + y * m[5] + z * m[9] + w * m[13];
      out[2] = x * m[2] + y * m[6] + z * m[10] + w * m[14];
      out[3] = x * m[3] + y * m[7] + z * m[11] + w * m[15];
  
      return out;
  };
  
  vec4.transformProjection = function(out, a, m) {
      var x = a[0],
          y = a[1],
          z = a[2],
          w = a[3],
          d = x * m[3] + y * m[7] + z * m[11] + w * m[15];
  
      d = d !== 0 ? 1 / d : d;
  
      out[0] = (x * m[0] + y * m[4] + z * m[8] + w * m[12]) * d;
      out[1] = (x * m[1] + y * m[5] + z * m[9] + w * m[13]) * d;
      out[2] = (x * m[2] + y * m[6] + z * m[10] + w * m[14]) * d;
      out[3] = (x * m[3] + y * m[7] + z * m[11] + w * m[15]) * d;
  
      return out;
  };
  
  vec4.positionFromMat4 = function(out, m) {
  
      out[0] = m[12];
      out[1] = m[13];
      out[2] = m[14];
      out[3] = m[15];
  
      return out;
  };
  
  vec4.scaleFromMat4 = function(out, m) {
  
      out[0] = vec4.lengthValues(m[0], m[4], m[8], m[12]);
      out[1] = vec4.lengthValues(m[1], m[5], m[9], m[13]);
      out[2] = vec4.lengthValues(m[2], m[6], m[10], m[14]);
      out[3] = vec4.lengthValues(m[3], m[7], m[11], m[15]);
  
      return out;
  };
  
  vec4.equals = function(a, b, e) {
      return !vec4.notEquals(a, b, e);
  };
  
  vec4.notEquals = function(a, b, e) {
      return (!mathf.equals(a[0], b[0], e) ||
          !mathf.equals(a[1], b[1], e) ||
          !mathf.equals(a[2], b[2], e) ||
          !mathf.equals(a[3], b[3], e)
      );
  };
  
  vec4.str = function(out) {
      return "Vec4(" + out[0] + ", " + out[1] + ", " + out[2] + ", " + out[3] + ")";
  };
  
  vec4.string = vec4.toString = vec4.str;
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/color@0.0.4/src/colorNames.js-=@*/
  module.exports = {
      aliceblue: "#f0f8ff",
      antiquewhite: "#faebd7",
      aqua: "#00ffff",
      aquamarine: "#7fffd4",
      azure: "#f0ffff",
      beige: "#f5f5dc",
      bisque: "#ffe4c4",
      black: "#000000",
      blanchedalmond: "#ffebcd",
      blue: "#0000ff",
      blueviolet: "#8a2be2",
      brown: "#a52a2a",
      burlywood: "#deb887",
      cadetblue: "#5f9ea0",
      chartreuse: "#7fff00",
      chocolate: "#d2691e",
      coral: "#ff7f50",
      cornflowerblue: "#6495ed",
      cornsilk: "#fff8dc",
      crimson: "#dc143c",
      cyan: "#00ffff",
      darkblue: "#00008b",
      darkcyan: "#008b8b",
      darkgoldenrod: "#b8860b",
      darkgray: "#a9a9a9",
      darkgreen: "#006400",
      darkkhaki: "#bdb76b",
      darkmagenta: "#8b008b",
      darkolivegreen: "#556b2f",
      darkorange: "#ff8c00",
      darkorchid: "#9932cc",
      darkred: "#8b0000",
      darksalmon: "#e9967a",
      darkseagreen: "#8fbc8f",
      darkslateblue: "#483d8b",
      darkslategray: "#2f4f4f",
      darkturquoise: "#00ced1",
      darkviolet: "#9400d3",
      deeppink: "#ff1493",
      deepskyblue: "#00bfff",
      dimgray: "#696969",
      dodgerblue: "#1e90ff",
      firebrick: "#b22222",
      floralwhite: "#fffaf0",
      forestgreen: "#228b22",
      fuchsia: "#ff00ff",
      gainsboro: "#dcdcdc",
      ghostwhite: "#f8f8ff",
      gold: "#ffd700",
      goldenrod: "#daa520",
      gray: "#808080",
      green: "#008000",
      greenyellow: "#adff2f",
      grey: "#808080",
      honeydew: "#f0fff0",
      hotpink: "#ff69b4",
      indianred: "#cd5c5c",
      indigo: "#4b0082",
      ivory: "#fffff0",
      khaki: "#f0e68c",
      lavender: "#e6e6fa",
      lavenderblush: "#fff0f5",
      lawngreen: "#7cfc00",
      lemonchiffon: "#fffacd",
      lightblue: "#add8e6",
      lightcoral: "#f08080",
      lightcyan: "#e0ffff",
      lightgoldenrodyellow: "#fafad2",
      lightgrey: "#d3d3d3",
      lightgreen: "#90ee90",
      lightpink: "#ffb6c1",
      lightsalmon: "#ffa07a",
      lightseagreen: "#20b2aa",
      lightskyblue: "#87cefa",
      lightslategray: "#778899",
      lightsteelblue: "#b0c4de",
      lightyellow: "#ffffe0",
      lime: "#00ff00",
      limegreen: "#32cd32",
      linen: "#faf0e6",
      magenta: "#ff00ff",
      maroon: "#800000",
      mediumaquamarine: "#66cdaa",
      mediumblue: "#0000cd",
      mediumorchid: "#ba55d3",
      mediumpurple: "#9370d8",
      mediumseagreen: "#3cb371",
      mediumslateblue: "#7b68ee",
      mediumspringgreen: "#00fa9a",
      mediumturquoise: "#48d1cc",
      mediumvioletred: "#c71585",
      midnightblue: "#191970",
      mintcream: "#f5fffa",
      mistyrose: "#ffe4e1",
      moccasin: "#ffe4b5",
      navajowhite: "#ffdead",
      navy: "#000080",
      oldlace: "#fdf5e6",
      olive: "#808000",
      olivedrab: "#6b8e23",
      orange: "#ffa500",
      orangered: "#ff4500",
      orchid: "#da70d6",
      palegoldenrod: "#eee8aa",
      palegreen: "#98fb98",
      paleturquoise: "#afeeee",
      palevioletred: "#d87093",
      papayawhip: "#ffefd5",
      peachpuff: "#ffdab9",
      peru: "#cd853f",
      pink: "#ffc0cb",
      plum: "#dda0dd",
      powderblue: "#b0e0e6",
      purple: "#800080",
      red: "#ff0000",
      rosybrown: "#bc8f8f",
      royalblue: "#4169e1",
      saddlebrown: "#8b4513",
      salmon: "#fa8072",
      sandybrown: "#f4a460",
      seagreen: "#2e8b57",
      seashell: "#fff5ee",
      sienna: "#a0522d",
      silver: "#c0c0c0",
      skyblue: "#87ceeb",
      slateblue: "#6a5acd",
      slategray: "#708090",
      snow: "#fffafa",
      springgreen: "#00ff7f",
      steelblue: "#4682b4",
      tan: "#d2b48c",
      teal: "#008080",
      thistle: "#d8bfd8",
      tomato: "#ff6347",
      turquoise: "#40e0d0",
      violet: "#ee82ee",
      wheat: "#f5deb3",
      white: "#ffffff",
      whitesmoke: "#f5f5f5",
      yellow: "#ffff00",
      yellowgreen: "#9acd32"
  };
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/object-reverse@0.0.1/src/index.js-=@*/
  var has = require(11);
  
  
  module.exports = objectReverse;
  
  
  function objectReverse(object) {
      var localHas = has,
          out = {},
          key;
  
      for (key in object) {
          if (localHas(object, key)) {
              out[object[key]] = key;
          }
      }
  
      return out;
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/enums/blending.js-=@*/
  var enums = require(60);
  
  
  module.exports = enums([
      "NONE",
      "DEFAULT",
      "ADDITIVE",
      "SUBTRACTIVE",
      "MULTIPLY"
  ]);
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/enums/cullFace.js-=@*/
  var enums = require(60),
      gl = require(56);
  
  
  module.exports = enums({
      NONE: 1,
      BACK: gl.BACK,
      FRONT: gl.FRONT,
      FRONT_AND_BACK: gl.FRONT_AND_BACK
  });
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/enums/depth.js-=@*/
  var enums = require(60),
      gl = require(56);
  
  
  module.exports = enums({
      NONE: 1,
      NEVER: gl.NEVER,
      LESS: gl.LESS,
      EQUAL: gl.EQUAL,
      LEQUAL: gl.LEQUAL,
      GREATER: gl.GREATER,
      NOTEQUAL: gl.NOTEQUAL,
      GEQUAL: gl.GEQUAL,
      ALWAYS: gl.ALWAYS
  });
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/enums/filterMode.js-=@*/
  var enums = require(60);
  
  
  module.exports = enums({
      NONE: 1,
      LINEAR: 2
  });
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/enums/gl.js-=@*/
  var enums = require(60);
  
  
  module.exports = enums({
      DEPTH_BUFFER_BIT: 256,
      STENCIL_BUFFER_BIT: 1024,
      COLOR_BUFFER_BIT: 16384,
      POINTS: 0,
      LINES: 1,
      LINE_LOOP: 2,
      LINE_STRIP: 3,
      TRIANGLES: 4,
      TRIANGLE_STRIP: 5,
      TRIANGLE_FAN: 6,
      ZERO: 0,
      ONE: 1,
      SRC_COLOR: 768,
      ONE_MINUS_SRC_COLOR: 769,
      SRC_ALPHA: 770,
      ONE_MINUS_SRC_ALPHA: 771,
      DST_ALPHA: 772,
      ONE_MINUS_DST_ALPHA: 773,
      DST_COLOR: 774,
      ONE_MINUS_DST_COLOR: 775,
      SRC_ALPHA_SATURATE: 776,
      FUNC_ADD: 32774,
      BLEND_EQUATION: 32777,
      BLEND_EQUATION_RGB: 32777,
      BLEND_EQUATION_ALPHA: 34877,
      FUNC_SUBTRACT: 32778,
      FUNC_REVERSE_SUBTRACT: 32779,
      BLEND_DST_RGB: 32968,
      BLEND_SRC_RGB: 32969,
      BLEND_DST_ALPHA: 32970,
      BLEND_SRC_ALPHA: 32971,
      CONSTANT_COLOR: 32769,
      ONE_MINUS_CONSTANT_COLOR: 32770,
      CONSTANT_ALPHA: 32771,
      ONE_MINUS_CONSTANT_ALPHA: 32772,
      BLEND_COLOR: 32773,
      ARRAY_BUFFER: 34962,
      ELEMENT_ARRAY_BUFFER: 34963,
      ARRAY_BUFFER_BINDING: 34964,
      ELEMENT_ARRAY_BUFFER_BINDING: 34965,
      STREAM_DRAW: 35040,
      STATIC_DRAW: 35044,
      DYNAMIC_DRAW: 35048,
      BUFFER_SIZE: 34660,
      BUFFER_USAGE: 34661,
      CURRENT_VERTEX_ATTRIB: 34342,
      FRONT: 1028,
      BACK: 1029,
      FRONT_AND_BACK: 1032,
      TEXTURE_2D: 3553,
      CULL_FACE: 2884,
      BLEND: 3042,
      DITHER: 3024,
      STENCIL_TEST: 2960,
      DEPTH_TEST: 2929,
      SCISSOR_TEST: 3089,
      POLYGON_OFFSET_FILL: 32823,
      SAMPLE_ALPHA_TO_COVERAGE: 32926,
      SAMPLE_COVERAGE: 32928,
      NO_ERROR: 0,
      INVALID_ENUM: 1280,
      INVALID_VALUE: 1281,
      INVALID_OPERATION: 1282,
      OUT_OF_MEMORY: 1285,
      CW: 2304,
      CCW: 2305,
      LINE_WIDTH: 2849,
      ALIASED_POINT_SIZE_RANGE: 33901,
      ALIASED_LINE_WIDTH_RANGE: 33902,
      CULL_FACE_MODE: 2885,
      FRONT_FACE: 2886,
      DEPTH_RANGE: 2928,
      DEPTH_WRITEMASK: 2930,
      DEPTH_CLEAR_VALUE: 2931,
      DEPTH_FUNC: 2932,
      STENCIL_CLEAR_VALUE: 2961,
      STENCIL_FUNC: 2962,
      STENCIL_FAIL: 2964,
      STENCIL_PASS_DEPTH_FAIL: 2965,
      STENCIL_PASS_DEPTH_PASS: 2966,
      STENCIL_REF: 2967,
      STENCIL_VALUE_MASK: 2963,
      STENCIL_WRITEMASK: 2968,
      STENCIL_BACK_FUNC: 34816,
      STENCIL_BACK_FAIL: 34817,
      STENCIL_BACK_PASS_DEPTH_FAIL: 34818,
      STENCIL_BACK_PASS_DEPTH_PASS: 34819,
      STENCIL_BACK_REF: 36003,
      STENCIL_BACK_VALUE_MASK: 36004,
      STENCIL_BACK_WRITEMASK: 36005,
      VIEWPORT: 2978,
      SCISSOR_BOX: 3088,
      COLOR_CLEAR_VALUE: 3106,
      COLOR_WRITEMASK: 3107,
      UNPACK_ALIGNMENT: 3317,
      PACK_ALIGNMENT: 3333,
      MAX_TEXTURE_SIZE: 3379,
      MAX_VIEWPORT_DIMS: 3386,
      SUBPIXEL_BITS: 3408,
      RED_BITS: 3410,
      GREEN_BITS: 3411,
      BLUE_BITS: 3412,
      ALPHA_BITS: 3413,
      DEPTH_BITS: 3414,
      STENCIL_BITS: 3415,
      POLYGON_OFFSET_UNITS: 10752,
      POLYGON_OFFSET_FACTOR: 32824,
      TEXTURE_BINDING_2D: 32873,
      SAMPLE_BUFFERS: 32936,
      SAMPLES: 32937,
      SAMPLE_COVERAGE_VALUE: 32938,
      SAMPLE_COVERAGE_INVERT: 32939,
      COMPRESSED_TEXTURE_FORMATS: 34467,
      DONT_CARE: 4352,
      FASTEST: 4353,
      NICEST: 4354,
      GENERATE_MIPMAP_HINT: 33170,
      BYTE: 5120,
      UNSIGNED_BYTE: 5121,
      SHORT: 5122,
      UNSIGNED_SHORT: 5123,
      INT: 5124,
      UNSIGNED_INT: 5125,
      FLOAT: 5126,
      DEPTH_COMPONENT: 6402,
      ALPHA: 6406,
      RGB: 6407,
      RGBA: 6408,
      LUMINANCE: 6409,
      LUMINANCE_ALPHA: 6410,
      UNSIGNED_SHORT_4_4_4_4: 32819,
      UNSIGNED_SHORT_5_5_5_1: 32820,
      UNSIGNED_SHORT_5_6_5: 33635,
      FRAGMENT_SHADER: 35632,
      VERTEX_SHADER: 35633,
      MAX_VERTEX_ATTRIBS: 34921,
      MAX_VERTEX_UNIFORM_VECTORS: 36347,
      MAX_VARYING_VECTORS: 36348,
      MAX_COMBINED_TEXTURE_IMAGE_UNITS: 35661,
      MAX_VERTEX_TEXTURE_IMAGE_UNITS: 35660,
      MAX_TEXTURE_IMAGE_UNITS: 34930,
      MAX_FRAGMENT_UNIFORM_VECTORS: 36349,
      SHADER_TYPE: 35663,
      DELETE_STATUS: 35712,
      LINK_STATUS: 35714,
      VALIDATE_STATUS: 35715,
      ATTACHED_SHADERS: 35717,
      ACTIVE_UNIFORMS: 35718,
      ACTIVE_ATTRIBUTES: 35721,
      SHADING_LANGUAGE_VERSION: 35724,
      CURRENT_PROGRAM: 35725,
      NEVER: 512,
      LESS: 513,
      EQUAL: 514,
      LEQUAL: 515,
      GREATER: 516,
      NOTEQUAL: 517,
      GEQUAL: 518,
      ALWAYS: 519,
      KEEP: 7680,
      REPLACE: 7681,
      INCR: 7682,
      DECR: 7683,
      INVERT: 5386,
      INCR_WRAP: 34055,
      DECR_WRAP: 34056,
      VENDOR: 7936,
      RENDERER: 7937,
      VERSION: 7938,
      NEAREST: 9728,
      LINEAR: 9729,
      NEAREST_MIPMAP_NEAREST: 9984,
      LINEAR_MIPMAP_NEAREST: 9985,
      NEAREST_MIPMAP_LINEAR: 9986,
      LINEAR_MIPMAP_LINEAR: 9987,
      TEXTURE_MAG_FILTER: 10240,
      TEXTURE_MIN_FILTER: 10241,
      TEXTURE_WRAP_S: 10242,
      TEXTURE_WRAP_T: 10243,
      TEXTURE: 5890,
      TEXTURE_CUBE_MAP: 34067,
      TEXTURE_BINDING_CUBE_MAP: 34068,
      TEXTURE_CUBE_MAP_POSITIVE_X: 34069,
      TEXTURE_CUBE_MAP_NEGATIVE_X: 34070,
      TEXTURE_CUBE_MAP_POSITIVE_Y: 34071,
      TEXTURE_CUBE_MAP_NEGATIVE_Y: 34072,
      TEXTURE_CUBE_MAP_POSITIVE_Z: 34073,
      TEXTURE_CUBE_MAP_NEGATIVE_Z: 34074,
      MAX_CUBE_MAP_TEXTURE_SIZE: 34076,
      TEXTURE0: 33984,
      TEXTURE1: 33985,
      TEXTURE2: 33986,
      TEXTURE3: 33987,
      TEXTURE4: 33988,
      TEXTURE5: 33989,
      TEXTURE6: 33990,
      TEXTURE7: 33991,
      TEXTURE8: 33992,
      TEXTURE9: 33993,
      TEXTURE10: 33994,
      TEXTURE11: 33995,
      TEXTURE12: 33996,
      TEXTURE13: 33997,
      TEXTURE14: 33998,
      TEXTURE15: 33999,
      TEXTURE16: 34000,
      TEXTURE17: 34001,
      TEXTURE18: 34002,
      TEXTURE19: 34003,
      TEXTURE20: 34004,
      TEXTURE21: 34005,
      TEXTURE22: 34006,
      TEXTURE23: 34007,
      TEXTURE24: 34008,
      TEXTURE25: 34009,
      TEXTURE26: 34010,
      TEXTURE27: 34011,
      TEXTURE28: 34012,
      TEXTURE29: 34013,
      TEXTURE30: 34014,
      TEXTURE31: 34015,
      ACTIVE_TEXTURE: 34016,
      REPEAT: 10497,
      CLAMP_TO_EDGE: 33071,
      MIRRORED_REPEAT: 33648,
      FLOAT_VEC2: 35664,
      FLOAT_VEC3: 35665,
      FLOAT_VEC4: 35666,
      INT_VEC2: 35667,
      INT_VEC3: 35668,
      INT_VEC4: 35669,
      BOOL: 35670,
      BOOL_VEC2: 35671,
      BOOL_VEC3: 35672,
      BOOL_VEC4: 35673,
      FLOAT_MAT2: 35674,
      FLOAT_MAT3: 35675,
      FLOAT_MAT4: 35676,
      SAMPLER_2D: 35678,
      SAMPLER_CUBE: 35680,
      VERTEX_ATTRIB_ARRAY_ENABLED: 34338,
      VERTEX_ATTRIB_ARRAY_SIZE: 34339,
      VERTEX_ATTRIB_ARRAY_STRIDE: 34340,
      VERTEX_ATTRIB_ARRAY_TYPE: 34341,
      VERTEX_ATTRIB_ARRAY_NORMALIZED: 34922,
      VERTEX_ATTRIB_ARRAY_POINTER: 34373,
      VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: 34975,
      IMPLEMENTATION_COLOR_READ_TYPE: 35738,
      IMPLEMENTATION_COLOR_READ_FORMAT: 35739,
      COMPILE_STATUS: 35713,
      LOW_FLOAT: 36336,
      MEDIUM_FLOAT: 36337,
      HIGH_FLOAT: 36338,
      LOW_INT: 36339,
      MEDIUM_INT: 36340,
      HIGH_INT: 36341,
      FRAMEBUFFER: 36160,
      RENDERBUFFER: 36161,
      RGBA4: 32854,
      RGB5_A1: 32855,
      RGB565: 36194,
      DEPTH_COMPONENT16: 33189,
      STENCIL_INDEX: 6401,
      STENCIL_INDEX8: 36168,
      DEPTH_STENCIL: 34041,
      RENDERBUFFER_WIDTH: 36162,
      RENDERBUFFER_HEIGHT: 36163,
      RENDERBUFFER_INTERNAL_FORMAT: 36164,
      RENDERBUFFER_RED_SIZE: 36176,
      RENDERBUFFER_GREEN_SIZE: 36177,
      RENDERBUFFER_BLUE_SIZE: 36178,
      RENDERBUFFER_ALPHA_SIZE: 36179,
      RENDERBUFFER_DEPTH_SIZE: 36180,
      RENDERBUFFER_STENCIL_SIZE: 36181,
      FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: 36048,
      FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: 36049,
      FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: 36050,
      FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: 36051,
      COLOR_ATTACHMENT0: 36064,
      DEPTH_ATTACHMENT: 36096,
      STENCIL_ATTACHMENT: 36128,
      DEPTH_STENCIL_ATTACHMENT: 33306,
      NONE: 0,
      FRAMEBUFFER_COMPLETE: 36053,
      FRAMEBUFFER_INCOMPLETE_ATTACHMENT: 36054,
      FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: 36055,
      FRAMEBUFFER_INCOMPLETE_DIMENSIONS: 36057,
      FRAMEBUFFER_UNSUPPORTED: 36061,
      FRAMEBUFFER_BINDING: 36006,
      RENDERBUFFER_BINDING: 36007,
      MAX_RENDERBUFFER_SIZE: 34024,
      INVALID_FRAMEBUFFER_OPERATION: 1286,
      UNPACK_FLIP_Y_WEBGL: 37440,
      UNPACK_PREMULTIPLY_ALPHA_WEBGL: 37441,
      CONTEXT_LOST_WEBGL: 37442,
      UNPACK_COLORSPACE_CONVERSION_WEBGL: 37443,
      BROWSER_DEFAULT_WEBGL: 37444
  });
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/enums/textureFormat.js-=@*/
  var enums = require(60),
      gl = require(56);
  
  
  module.exports = enums({
      RGB: gl.RGB,
      RGBA: gl.RGBA,
      ALPHA: gl.ALPHA,
      LUMINANCE: gl.LUMINANCE,
      LUMINANCE_ALPHA: gl.LUMINANCE_ALPHA
  });
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/enums/textureType.js-=@*/
  var enums = require(60),
      gl = require(56);
  
  
  module.exports = enums({
      UNSIGNED_BYTE: gl.UNSIGNED_BYTE,
      FLOAT: gl.FLOAT,
      DEPTH_COMPONENT: gl.DEPTH_COMPONENT,
      UNSIGNED_SHORT: gl.UNSIGNED_SHORT,
      UNSIGNED_SHORT_5_6_5: gl.UNSIGNED_SHORT_5_6_5,
      UNSIGNED_SHORT_4_4_4_4: gl.UNSIGNED_SHORT_4_4_4_4,
      UNSIGNED_SHORT_5_5_5_1: gl.UNSIGNED_SHORT_5_5_5_1
  });
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/enums/textureWrap.js-=@*/
  var enums = require(60),
      gl = require(56);
  
  
  module.exports = enums({
      REPEAT: gl.REPEAT,
      CLAMP: gl.CLAMP_TO_EDGE,
      MIRRORED_REPEAT: gl.MIRRORED_REPEAT
  });
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/enums@0.0.2/src/index.js-=@*/
  var create = require(40),
      defineProperty = require(61),
      objectForEach = require(62),
      arrayForEach = require(63),
      isString = require(21),
      isNumber = require(7),
      isArray = require(64),
      emptyFunction = require(23),
      stringHashCode = require(65);
  
  
  var reSpliter = /[\s\, ]+/,
      descriptor = {
          configurable: false,
          enumerable: true,
          writable: false,
          value: null
      },
      freeze = Object.freeze || emptyFunction;
  
  
  module.exports = enums;
  
  
  function enums(values) {
      if (isString(values)) {
          return createEnums(values.split(reSpliter));
      } else if (values) {
          return createEnums(values);
      } else {
          throw new TypeError("enums(values) values must be an array, object, or a string");
      }
  }
  
  function createEnums(values) {
      var object = create(null);
  
      if (isArray(values)) {
          arrayForEach(values, createEnum.set(object));
      } else {
          objectForEach(values, createEnum.set(object));
      }
      freeze(object);
  
      return object;
  }
  
  function createEnum(value, key) {
      if (isNumber(key)) {
          key = value;
          value = stringHashCode(value);
      }
  
      descriptor.value = value;
      defineProperty(createEnum.object, key, descriptor);
      descriptor.value = null;
  }
  
  createEnum.set = function(object) {
      createEnum.object = object;
      return createEnum;
  };
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/define_property@0.0.3/src/index.js-=@*/
  var isObject = require(14),
      isFunction = require(16),
      isPrimitive = require(44),
      isNative = require(12),
      has = require(11);
  
  
  var nativeDefineProperty = Object.defineProperty;
  
  
  module.exports = defineProperty;
  
  
  function defineProperty(object, name, descriptor) {
      if (isPrimitive(descriptor) || isFunction(descriptor)) {
          descriptor = {
              value: descriptor
          };
      }
      return nativeDefineProperty(object, name, descriptor);
  }
  
  defineProperty.hasGettersSetters = true;
  
  if (!isNative(nativeDefineProperty) || !(function() {
          var object = {},
              value = {};
  
          try {
              nativeDefineProperty(object, "key", {
                  value: value
              });
              if (has(object, "key") && object.key === value) {
                  return true;
              } else {
                  return false;
              }
          } catch (e) {}
  
          return false;
      }())) {
  
      defineProperty.hasGettersSetters = false;
  
      nativeDefineProperty = function defineProperty(object, name, descriptor) {
          if (!isObject(object)) {
              throw new TypeError("defineProperty(object, name, descriptor) called on non-object");
          }
          if (has(descriptor, "get") || has(descriptor, "set")) {
              throw new TypeError("defineProperty(object, name, descriptor) this environment does not support getters or setters");
          }
          object[name] = descriptor.value;
      };
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/object-for_each@0.0.2/src/index.js-=@*/
  var keys = require(8);
  
  
  module.exports = objectForEach;
  
  
  function objectForEach(object, callback) {
      var objectKeys = keys(object),
          i = -1,
          il = objectKeys.length - 1,
          key;
  
      while (i++ < il) {
          key = objectKeys[i];
  
          if (callback(object[key], key, object) === false) {
              break;
          }
      }
  
      return object;
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/array-for_each@0.0.1/src/index.js-=@*/
  module.exports = arrayForEach;
  
  
  function arrayForEach(array, callback) {
      var i = -1,
          il = array.length - 1;
  
      while (i++ < il) {
          if (callback(array[i], i, array) === false) {
              break;
          }
      }
  
      return array;
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/is_array@0.0.1/src/index.js-=@*/
  var isNative = require(12),
      isLength = require(66),
      isObject = require(14);
  
  
  var objectToString = Object.prototype.toString,
      nativeIsArray = Array.isArray,
      isArray;
  
  
  if (isNative(nativeIsArray)) {
      isArray = nativeIsArray;
  } else {
      isArray = function isArray(value) {
          return (
              isObject(value) &&
              isLength(value.length) &&
              objectToString.call(value) === "[object Array]"
          ) || false;
      };
  }
  
  
  module.exports = isArray;
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/string-hash_code@0.0.1/src/index.js-=@*/
  var isUndefined = require(19);
  
  
  var STRING_HASH_CACHE_MIN_STRING_LENGTH = 16,
      STRING_HASH_CACHE_MAX_SIZE = 255,
      STRING_HASH_CACHE_SIZE = 0,
      SRTING_HASH_CACHE = {};
  
  
  module.exports = stringHashCode;
  
  
  function stringHashCode(string) {
      if (string.length > STRING_HASH_CACHE_MIN_STRING_LENGTH) {
          return cachedHashString(string);
      } else {
          return hashString(string);
      }
  }
  
  function cachedHashString(string) {
      var hash = SRTING_HASH_CACHE[string];
  
      if (isUndefined(hash)) {
          hash = hashString(string);
  
          if (STRING_HASH_CACHE_SIZE === STRING_HASH_CACHE_MAX_SIZE) {
              STRING_HASH_CACHE_SIZE = 0;
              SRTING_HASH_CACHE = {};
          }
  
          STRING_HASH_CACHE_SIZE += 1;
          SRTING_HASH_CACHE[string] = hash;
      }
  
      return hash;
  }
  
  function hashString(string) {
      var hash = 0,
          i = -1,
          il = string.length - 1;
  
      while (i++ < il) {
          hash = 31 * hash + string.charCodeAt(i) | 0;
      }
  
      return ((hash >>> 1) & 0x40000000) | (hash & 0xBFFFFFFF);
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/is_length@0.0.1/src/index.js-=@*/
  var isNumber = require(7);
  
  
  var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1;
  
  
  module.exports = isLength;
  
  
  function isLength(value) {
      return isNumber(value) && value > -1 && value % 1 === 0 && value <= MAX_SAFE_INTEGER;
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/fast_hash@0.0.3/src/index.js-=@*/
  var has = require(11),
      indexOf = require(70),
      defineProperty = require(61);
  
  
  var FastHashPrototype;
  
  
  module.exports = FastHash;
  
  
  function FastHash(key) {
      this._key = key;
      this._array = [];
      this._hash = {};
  }
  FastHashPrototype = FastHash.prototype;
  
  FastHashPrototype.get = function(key) {
      return this._hash[key];
  };
  
  FastHashPrototype.has = function(key) {
      return has(this._hash, key);
  };
  
  FastHashPrototype.size = function() {
      return this._array.length;
  };
  
  FastHashPrototype.count = FastHashPrototype.size;
  
  if (defineProperty.hasGettersSetters) {
      defineProperty(FastHashPrototype, "length", {
          get: FastHashPrototype.size
      });
  }
  
  FastHashPrototype.clear = function() {
      var localHas = has,
          hash = this._hash,
          key;
  
      for (key in hash) {
          if (localHas(hash, key)) {
              delete hash[key];
          }
      }
      this._array.length = 0;
  
      return this;
  };
  
  FastHashPrototype.getArray = function() {
      return this._array;
  };
  FastHashPrototype.getObject = function() {
      return this._hash;
  };
  
  FastHashPrototype.add = function() {
      var i = -1,
          il = arguments.length - 1;
  
      while (i++ < il) {
          FastHash_add(this, arguments[i]);
      }
  
      return this;
  };
  
  function FastHash_add(_this, value) {
      var array = _this._array,
          hash = _this._hash,
          key = value[_this._key];
  
      if (!has(hash, key)) {
          hash[key] = value;
          array[array.length] = value;
      } else {
          throw new Error("trying to add duplicate keys " + key);
      }
  }
  
  FastHashPrototype.remove = function() {
      var i = -1,
          il = arguments.length - 1;
  
      while (i++ < il) {
          FastHash_remove(this, arguments[i]);
      }
  
      return this;
  };
  
  function FastHash_remove(_this, value) {
      var array = _this._array,
          hash = _this._hash,
          key = value[_this._key];
  
      if (has(hash, key)) {
          delete hash[key];
          array.splice(indexOf(value), 1);
      } else {
          throw new Error("trying to add duplicate keys " + key);
      }
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/uniforms/index.js-=@*/
  module.exports = {
      BOOL: require(72),
      INT: require(73),
      FLOAT: require(74),
  
      BOOL_VEC2: require(75),
      BOOL_VEC3: require(76),
      BOOL_VEC4: require(77),
  
      INT_VEC2: require(75),
      INT_VEC3: require(76),
      INT_VEC4: require(77),
  
      FLOAT_VEC2: require(78),
      FLOAT_VEC3: require(79),
      FLOAT_VEC4: require(80),
  
      FLOAT_MAT2: require(81),
      FLOAT_MAT3: require(82),
      FLOAT_MAT4: require(83),
  
      SAMPLER_2D: require(84),
      SAMPLER_CUBE: require(85)
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/attributes/index.js-=@*/
  module.exports = {
      INT: require(90),
      FLOAT: require(91),
  
      INT_VEC2: require(92),
      INT_VEC3: require(93),
      INT_VEC4: require(94),
  
      FLOAT_VEC2: require(95),
      FLOAT_VEC3: require(96),
      FLOAT_VEC4: require(97)
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/index_of@0.0.1/src/index.js-=@*/
  var isEqual = require(71);
  
  
  module.exports = indexOf;
  
  
  function indexOf(array, value, fromIndex) {
      var i = (fromIndex || 0) - 1,
          il = array.length - 1;
  
      while (i++ < il) {
          if (isEqual(array[i], value)) {
              return i;
          }
      }
  
      return -1;
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/is_equal@0.0.1/src/index.js-=@*/
  module.exports = isEqual;
  
  
  function isEqual(a, b) {
      return !(a !== b && !(a !== a && b !== b));
  }
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/uniforms/Uniform1b.js-=@*/
  var Uniform = require(86);
  
  
  var NativeInt32Array = typeof(Int32Array) !== "undefined" ? Int32Array : Array;
  
  
  module.exports = Uniform1b;
  
  
  function Uniform1b(context, name, location, size) {
      Uniform.call(this, context, name, location, size);
      this.value = size === 1 ? NaN : new NativeInt32Array(size);
  }
  Uniform.extend(Uniform1b);
  
  Uniform1b.prototype.set = function(value, force) {
      var context = this.context;
  
      if (this.size === 1) {
          if (force || context.__programForce || this.value !== value) {
              context.gl.uniform1i(this.location, value);
              this.value = value;
          }
      } else {
          context.gl.uniform1iv(this.location, value);
      }
  
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/uniforms/Uniform1i.js-=@*/
  var Uniform = require(86);
  
  
  var NativeInt32Array = typeof(Int32Array) !== "undefined" ? Int32Array : Array;
  
  
  module.exports = Uniform1i;
  
  
  function Uniform1i(context, name, location, size) {
      Uniform.call(this, context, name, location, size);
      this.value = size === 1 ? NaN : new NativeInt32Array(size);
  }
  Uniform.extend(Uniform1i);
  
  Uniform1i.prototype.set = function(value, force) {
      var context = this.context;
  
      if (this.size === 1) {
          if (force || context.__programForce || this.value !== value) {
              context.gl.uniform1i(this.location, value);
              this.value = value;
          }
      } else {
          context.gl.uniform1iv(this.location, value);
      }
  
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/uniforms/Uniform1f.js-=@*/
  var Uniform = require(86);
  
  
  var NativeFloat32Array = typeof(Float32Array) !== "undefined" ? Float32Array : Array;
  
  
  module.exports = Uniform1f;
  
  
  function Uniform1f(context, name, location, size) {
      Uniform.call(this, context, name, location, size);
      this.value = size === 1 ? NaN : new NativeFloat32Array(size);
  }
  Uniform.extend(Uniform1f);
  
  Uniform1f.prototype.set = function(value, force) {
      var context = this.context;
  
      if (this.size === 1) {
          if (force || context.__programForce || this.value !== value) {
              context.gl.uniform1f(this.location, value);
              this.value = value;
          }
      } else {
          context.gl.uniform1fv(this.location, value);
      }
  
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/uniforms/Uniform2i.js-=@*/
  var vec2 = require(87),
      Uniform = require(86);
  
  
  var NativeInt32Array = typeof(Int32Array) !== "undefined" ? Int32Array : Array;
  
  
  module.exports = Uniform2i;
  
  
  function Uniform2i(context, name, location, size) {
      Uniform.call(this, context, name, location, size);
      this.value = size === 1 ? vec2.create(NaN, NaN) : new NativeInt32Array(size * 2);
  }
  Uniform.extend(Uniform2i);
  
  Uniform2i.prototype.set = function(value, force) {
      var context = this.context;
  
      if (this.size === 1) {
          if (force || context.__programForce || vec2.notEquals(this.value, value)) {
              context.gl.uniform2i(this.location, value[0], value[1]);
              vec2.copy(this.value, value);
          }
      } else {
          context.gl.uniform2iv(this.location, value);
      }
  
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/uniforms/Uniform3i.js-=@*/
  var vec3 = require(6),
      Uniform = require(86);
  
  
  var NativeInt32Array = typeof(Int32Array) !== "undefined" ? Int32Array : Array;
  
  
  module.exports = Uniform3i;
  
  
  function Uniform3i(context, name, location, size) {
      Uniform.call(this, context, name, location, size);
      this.value = size === 1 ? vec3.create(NaN, NaN, NaN) : new NativeInt32Array(size * 3);
  }
  Uniform.extend(Uniform3i);
  
  Uniform3i.prototype.set = function(value, force) {
      var context = this.context;
  
      if (this.size === 1) {
          if (force || context.__programForce || vec3.notEquals(this.value, value)) {
              context.gl.uniform3i(this.location, value[0], value[1], value[2]);
              vec3.copy(this.value, value);
          }
      } else {
          context.gl.uniform3iv(this.location, value);
      }
  
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/uniforms/Uniform4i.js-=@*/
  var vec4 = require(49),
      Uniform = require(86);
  
  
  var NativeInt32Array = typeof(Int32Array) !== "undefined" ? Int32Array : Array;
  
  
  module.exports = Uniform4i;
  
  
  function Uniform4i(context, name, location, size) {
      Uniform.call(this, context, name, location, size);
      this.value = size === 1 ? vec4.create(NaN, NaN, NaN, NaN) : new NativeInt32Array(size * 4);
  }
  Uniform.extend(Uniform4i);
  
  Uniform4i.prototype.set = function(value, force) {
      var context = this.context;
  
      if (this.size === 1) {
          if (force || context.__programForce || vec4.notEquals(this.value, value)) {
              context.gl.uniform4i(this.location, value[0], value[1], value[2], value[3]);
              vec4.copy(this.value, value);
          }
      } else {
          context.gl.uniform4iv(this.location, value);
      }
  
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/uniforms/Uniform2f.js-=@*/
  var vec2 = require(87),
      Uniform = require(86);
  
  
  var NativeFloat32Array = typeof(Float32Array) !== "undefined" ? Float32Array : Array;
  
  
  module.exports = Uniform2f;
  
  
  function Uniform2f(context, name, location, size) {
      Uniform.call(this, context, name, location, size);
      this.value = size === 1 ? vec2.create(NaN, NaN) : new NativeFloat32Array(size * 2);
  }
  Uniform.extend(Uniform2f);
  
  Uniform2f.prototype.set = function(value, force) {
      var context = this.context;
  
      if (this.size === 1) {
          if (force || context.__programForce || vec2.notEquals(this.value, value)) {
              context.gl.uniform2f(this.location, value[0], value[1]);
              vec2.copy(this.value, value);
          }
      } else {
          context.gl.uniform2fv(this.location, value);
      }
  
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/uniforms/Uniform3f.js-=@*/
  var vec3 = require(6),
      Uniform = require(86);
  
  
  var NativeFloat32Array = typeof(Float32Array) !== "undefined" ? Float32Array : Array;
  
  
  module.exports = Uniform3f;
  
  
  function Uniform3f(context, name, location, size) {
      Uniform.call(this, context, name, location, size);
      this.value = size === 1 ? vec3.create(NaN, NaN, NaN) : new NativeFloat32Array(size * 3);
  }
  Uniform.extend(Uniform3f);
  
  Uniform3f.prototype.set = function(value, force) {
      var context = this.context;
  
      if (this.size === 1) {
          if (force || context.__programForce || vec3.notEquals(this.value, value)) {
              context.gl.uniform3f(this.location, value[0], value[1], value[2]);
              vec3.copy(this.value, value);
          }
      } else {
          context.gl.uniform3fv(this.location, value);
      }
  
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/uniforms/Uniform4f.js-=@*/
  var vec4 = require(49),
      Uniform = require(86);
  
  
  var NativeFloat32Array = typeof(Float32Array) !== "undefined" ? Float32Array : Array;
  
  
  module.exports = Uniform4f;
  
  
  function Uniform4f(context, name, location, size) {
      Uniform.call(this, context, name, location, size);
      this.value = size === 1 ? vec4.create(NaN, NaN, NaN, NaN) : new NativeFloat32Array(size * 4);
  }
  Uniform.extend(Uniform4f);
  
  Uniform4f.prototype.set = function(value, force) {
      var context = this.context;
  
      if (this.size === 1) {
          if (force || context.__programForce || vec4.notEquals(this.value, value)) {
              context.gl.uniform4f(this.location, value[0], value[1], value[2], value[3]);
              vec4.copy(this.value, value);
          }
      } else {
          context.gl.uniform4fv(this.location, value);
      }
  
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/uniforms/UniformMatrix2fv.js-=@*/
  var mat2 = require(88),
      Uniform = require(86);
  
  
  var NativeFloat32Array = typeof(Float32Array) !== "undefined" ? Float32Array : Array;
  
  
  module.exports = UniformMatrix2fv;
  
  
  function UniformMatrix2fv(context, name, location, size) {
      Uniform.call(this, context, name, location, size);
      this.value = size === 1 ? mat2.create(NaN, NaN, NaN, NaN) : new NativeFloat32Array(size * 4);
  }
  Uniform.extend(UniformMatrix2fv);
  
  UniformMatrix2fv.prototype.set = function(value, force) {
      var context = this.context;
  
      if (this.size === 1) {
          if (force || context.__programForce || mat2.notEquals(this.value, value)) {
              context.gl.uniformMatrix2fv(this.location, false, value);
              mat2.copy(this.value, value);
          }
      } else {
          context.gl.uniformMatrix2fv(this.location, false, value);
      }
  
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/uniforms/UniformMatrix3fv.js-=@*/
  var mat3 = require(89),
      Uniform = require(86);
  
  
  var NativeFloat32Array = typeof(Float32Array) !== "undefined" ? Float32Array : Array;
  
  
  module.exports = UniformMatrix3fv;
  
  
  function UniformMatrix3fv(context, name, location, size) {
      Uniform.call(this, context, name, location, size);
      this.value = size === 1 ? mat3.create(
          NaN, NaN, NaN,
          NaN, NaN, NaN,
          NaN, NaN, NaN
      ) : new NativeFloat32Array(size * 9);
  }
  Uniform.extend(UniformMatrix3fv);
  
  UniformMatrix3fv.prototype.set = function(value, force) {
      var context = this.context;
  
      if (this.size === 1) {
          if (force || context.__programForce || mat3.notEquals(this.value, value)) {
              context.gl.uniformMatrix3fv(this.location, false, value);
              mat3.copy(this.value, value);
          }
      } else {
          context.gl.uniformMatrix3fv(this.location, false, value);
      }
  
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/uniforms/UniformMatrix4fv.js-=@*/
  var mat4 = require(1),
      Uniform = require(86);
  
  
  var NativeFloat32Array = typeof(Float32Array) !== "undefined" ? Float32Array : Array;
  
  
  module.exports = UniformMatrix4fv;
  
  
  function UniformMatrix4fv(context, name, location, size) {
      Uniform.call(this, context, name, location, size);
      this.value = size === 1 ? mat4.create(
          NaN, NaN, NaN, NaN,
          NaN, NaN, NaN, NaN,
          NaN, NaN, NaN, NaN,
          NaN, NaN, NaN, NaN
      ) : new NativeFloat32Array(size * 16);
  }
  Uniform.extend(UniformMatrix4fv);
  
  UniformMatrix4fv.prototype.set = function(value, force) {
      var context = this.context;
  
      if (this.size === 1) {
          if (force || context.__programForce || mat4.notEquals(this.value, value)) {
              context.gl.uniformMatrix4fv(this.location, false, value);
              mat4.copy(this.value, value);
          }
      } else {
          context.gl.uniformMatrix4fv(this.location, false, value);
      }
  
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/uniforms/UniformTexture.js-=@*/
  var Uniform = require(86);
  
  
  module.exports = UniformTexture;
  
  
  function UniformTexture(context, name, location, size) {
      Uniform.call(this, context, name, location, size);
  }
  Uniform.extend(UniformTexture);
  
  UniformTexture.prototype.set = function(value, force) {
      this.context.setTexture(this.location, value, force);
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/uniforms/UniformTextureCube.js-=@*/
  var Uniform = require(86);
  
  
  module.exports = UniformTextureCube;
  
  
  function UniformTextureCube(context, name, location, size) {
      Uniform.call(this, context, name, location, size);
  }
  Uniform.extend(UniformTextureCube);
  
  UniformTextureCube.prototype.set = function(value, force) {
      this.context.setTexture(this.location, value, force);
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/uniforms/Uniform.js-=@*/
  var inherits = require(38);
  
  
  module.exports = Uniform;
  
  
  function Uniform(context, name, location, size) {
      this.name = name;
      this.location = location;
      this.context = context;
      this.size = size;
      this.value = null;
  }
  
  Uniform.extend = function(child) {
      return inherits(child, this);
  };
  
  Uniform.prototype.set = function( /* value, force */ ) {
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/vec2@0.0.3/src/index.js-=@*/
  var mathf = require(5),
      isNumber = require(7);
  
  
  var vec2 = exports;
  
  
  vec2.ArrayType = typeof(Float32Array) !== "undefined" ? Float32Array : mathf.ArrayType;
  
  
  vec2.create = function(x, y) {
      var out = new vec2.ArrayType(2);
  
      out[0] = isNumber(x) ? x : 0;
      out[1] = isNumber(y) ? y : 0;
  
      return out;
  };
  
  vec2.up = vec2.forward = vec2.create(0.0, 1.0);
  vec2.down = vec2.backward = vec2.create(0.0, -1.0);
  
  vec2.right = vec2.create(1.0, 0.0);
  vec2.left = vec2.create(-1.0, 0.0);
  
  vec2.zero = vec2.create(0.0, 0.0);
  vec2.one = vec2.create(1.0, 1.0);
  
  vec2.copy = function(out, a) {
  
      out[0] = a[0];
      out[1] = a[1];
  
      return out;
  };
  
  vec2.clone = function(a) {
      var out = new vec2.ArrayType(2);
  
      out[0] = a[0];
      out[1] = a[1];
  
      return out;
  };
  
  vec2.set = function(out, x, y) {
  
      out[0] = isNumber(x) ? x : 0;
      out[1] = isNumber(y) ? y : 0;
  
      return out;
  };
  
  vec2.add = function(out, a, b) {
  
      out[0] = a[0] + b[0];
      out[1] = a[1] + b[1];
  
      return out;
  };
  
  vec2.sub = function(out, a, b) {
  
      out[0] = a[0] - b[0];
      out[1] = a[1] - b[1];
  
      return out;
  };
  
  vec2.mul = function(out, a, b) {
  
      out[0] = a[0] * b[0];
      out[1] = a[1] * b[1];
  
      return out;
  };
  
  vec2.div = function(out, a, b) {
      var bx = b[0],
          by = b[1];
  
      out[0] = a[0] * (bx !== 0 ? 1 / bx : bx);
      out[1] = a[1] * (by !== 0 ? 1 / by : by);
  
      return out;
  };
  
  vec2.sadd = function(out, a, s) {
  
      out[0] = a[0] + s;
      out[1] = a[1] + s;
  
      return out;
  };
  
  vec2.ssub = function(out, a, s) {
  
      out[0] = a[0] - s;
      out[1] = a[1] - s;
  
      return out;
  };
  
  vec2.smul = function(out, a, s) {
  
      out[0] = a[0] * s;
      out[1] = a[1] * s;
  
      return out;
  };
  
  vec2.sdiv = function(out, a, s) {
      s = s !== 0 ? 1 / s : s;
  
      out[0] = a[0] * s;
      out[1] = a[1] * s;
  
      return out;
  };
  
  vec2.lengthSqValues = function(x, y) {
      return x * x + y * y;
  };
  
  vec2.lengthValues = function(x, y) {
      var lsq = vec2.lengthSqValues(x, y);
      return lsq !== 0 ? mathf.sqrt(lsq) : lsq;
  };
  
  vec2.invLengthValues = function(x, y) {
      var lsq = vec2.lengthSqValues(x, y);
      return lsq !== 0 ? 1 / mathf.sqrt(lsq) : lsq;
  };
  
  vec2.cross = function(a, b) {
      return a[0] * b[1] - a[1] * b[0];
  };
  
  vec2.dot = function(a, b) {
      return a[0] * b[0] + a[1] * b[1];
  };
  
  vec2.lengthSq = function(a) {
      return vec2.dot(a, a);
  };
  
  vec2.length = function(a) {
      var lsq = vec2.lengthSq(a);
      return lsq !== 0 ? mathf.sqrt(lsq) : lsq;
  };
  
  vec2.invLength = function(a) {
      var lsq = vec2.lengthSq(a);
      return lsq !== 0 ? 1 / mathf.sqrt(lsq) : lsq;
  };
  
  vec2.setLength = function(out, a, length) {
      var x = a[0],
          y = a[1],
          s = length * vec2.invLengthValues(x, y);
  
      out[0] = x * s;
      out[1] = y * s;
  
      return out;
  };
  
  vec2.normalize = function(out, a) {
      var x = a[0],
          y = a[1],
          invlsq = vec2.invLengthValues(x, y);
  
      out[0] = x * invlsq;
      out[1] = y * invlsq;
  
      return out;
  };
  
  vec2.inverse = function(out, a) {
  
      out[0] = -a[0];
      out[1] = -a[1];
  
      return out;
  };
  
  vec2.lerp = function(out, a, b, x) {
      var lerp = mathf.lerp;
  
      out[0] = lerp(a[0], b[0], x);
      out[1] = lerp(a[1], b[1], x);
  
      return out;
  };
  
  vec2.perpL = function(out, a) {
  
      out[0] = a[1];
      out[1] = -a[0];
  
      return out;
  };
  
  vec2.perpR = function(out, a) {
  
      out[0] = -a[1];
      out[1] = a[0];
  
      return out;
  };
  
  vec2.angle = function(a, b) {
      return Math.acos(vec2.dot(a, b) / (vec2.length(a) * vec2.length(b)));
  };
  
  vec2.min = function(out, a, b) {
      var ax = a[0],
          ay = a[1],
          bx = b[0],
          by = b[1];
  
      out[0] = bx < ax ? bx : ax;
      out[1] = by < ay ? by : ay;
  
      return out;
  };
  
  vec2.max = function(out, a, b) {
      var ax = a[0],
          ay = a[1],
          bx = b[0],
          by = b[1];
  
      out[0] = bx > ax ? bx : ax;
      out[1] = by > ay ? by : ay;
  
      return out;
  };
  
  vec2.clamp = function(out, a, min, max) {
      var x = a[0],
          y = a[1],
          minx = min[0],
          miny = min[1],
          maxx = max[0],
          maxy = max[1];
  
      out[0] = x < minx ? minx : x > maxx ? maxx : x;
      out[1] = y < miny ? miny : y > maxy ? maxy : y;
  
      return out;
  };
  
  vec2.transformAngle = function(out, a, angle) {
      var x = a[0],
          y = a[1],
          c = mathf.cos(angle),
          s = mathf.sin(angle);
  
      out[0] = x * c - y * s;
      out[1] = x * s + y * c;
  
      return out;
  };
  
  vec2.transformMat2 = function(out, a, m) {
      var x = a[0],
          y = a[1];
  
      out[0] = x * m[0] + y * m[2];
      out[1] = x * m[1] + y * m[3];
  
      return out;
  };
  
  vec2.transformMat32 = function(out, a, m) {
      var x = a[0],
          y = a[1];
  
      out[0] = x * m[0] + y * m[2] + m[4];
      out[1] = x * m[1] + y * m[3] + m[5];
  
      return out;
  };
  
  vec2.transformMat3 = function(out, a, m) {
      var x = a[0],
          y = a[1];
  
      out[0] = x * m[0] + y * m[3] + m[6];
      out[1] = x * m[1] + y * m[4] + m[7];
  
      return out;
  };
  
  vec2.transformMat4 = function(out, a, m) {
      var x = a[0],
          y = a[1];
  
      out[0] = x * m[0] + y * m[4] + m[12];
      out[1] = x * m[1] + y * m[5] + m[13];
  
      return out;
  };
  
  vec2.transformProjection = function(out, a, m) {
      var x = a[0],
          y = a[1],
          d = x * m[3] + y * m[7] + m[11] + m[15];
  
      d = d !== 0 ? 1 / d : d;
  
      out[0] = (x * m[0] + y * m[4] + m[12]) * d;
      out[1] = (x * m[1] + y * m[5] + m[13]) * d;
  
      return out;
  };
  
  vec2.positionFromMat32 = function(out, m) {
  
      out[0] = m[4];
      out[1] = m[5];
  
      return out;
  };
  
  vec2.positionFromMat4 = function(out, m) {
  
      out[0] = m[12];
      out[1] = m[13];
  
      return out;
  };
  
  vec2.scaleFromMat2 = function(out, m) {
  
      out[0] = vec2.lengthValues(m[0], m[2]);
      out[1] = vec2.lengthValues(m[1], m[3]);
  
      return out;
  };
  
  vec2.scaleFromMat32 = vec2.scaleFromMat2;
  
  vec2.scaleFromMat3 = function(out, m) {
      var m11 = m[0],
          m21 = m[3],
          m31 = m[6],
          m12 = m[1],
          m22 = m[4],
          m32 = m[7],
          x = m11 * m11 + m21 * m21 + m31 * m31,
          y = m12 * m12 + m22 * m22 + m32 * m32;
  
      out[0] = x !== 0 ? Math.sqrt(x) : 0;
      out[1] = y !== 0 ? Math.sqrt(y) : 0;
  
      return out;
  };
  
  vec2.scaleFromMat4 = function(out, m) {
      var m11 = m[0],
          m21 = m[4],
          m31 = m[8],
          m12 = m[1],
          m22 = m[5],
          m32 = m[9],
          x = m11 * m11 + m21 * m21 + m31 * m31,
          y = m12 * m12 + m22 * m22 + m32 * m32;
  
      out[0] = x !== 0 ? Math.sqrt(x) : 0;
      out[1] = y !== 0 ? Math.sqrt(y) : 0;
  
      return out;
  };
  
  vec2.equals = function(a, b) {
      return !vec2.notEquals(a, b);
  };
  
  vec2.notEquals = function(a, b) {
      return !(
          mathf.equals(a[0], b[0]) ||
          mathf.equals(a[1], b[1])
      );
  };
  
  vec2.str = function(out) {
      return "Vec2(" + out[0] + ", " + out[1] + ")";
  };
  
  vec2.string = vec2.toString = vec2.str;
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/mat2@0.0.3/src/index.js-=@*/
  var mathf = require(5),
      isNumber = require(7);
  
  
  var mat2 = exports;
  
  
  mat2.ArrayType = typeof(Float32Array) !== "undefined" ? Float32Array : mathf.ArrayType;
  
  
  mat2.create = function(m11, m12, m21, m22) {
      var out = new mat2.ArrayType(4);
  
      out[0] = isNumber(m11) ? m11 : 1;
      out[2] = isNumber(m12) ? m12 : 0;
      out[1] = isNumber(m21) ? m21 : 0;
      out[3] = isNumber(m22) ? m22 : 1;
  
      return out;
  };
  
  mat2.copy = function(out, a) {
  
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
  
      return out;
  };
  
  mat2.clone = function(a) {
      var out = new mat2.ArrayType(4);
  
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
  
      return out;
  };
  
  mat2.set = function(out, m11, m12, m21, m22) {
  
      out[0] = isNumber(m11) ? m11 : 1;
      out[2] = isNumber(m12) ? m12 : 0;
      out[1] = isNumber(m21) ? m21 : 0;
      out[3] = isNumber(m22) ? m22 : 1;
  
      return out;
  };
  
  mat2.identity = function(out) {
  
      out[0] = 1;
      out[1] = 0;
      out[2] = 0;
      out[3] = 1;
  
      return out;
  };
  
  mat2.zero = function(out) {
  
      out[0] = 0;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
  
      return out;
  };
  
  mat2.mul = function(out, a, b) {
      var a11 = a[0],
          a12 = a[2],
          a21 = a[1],
          a22 = a[3],
  
          b11 = b[0],
          b12 = b[2],
          b21 = b[1],
          b22 = b[3];
  
      out[0] = a11 * b11 + a21 * b12;
      out[1] = a12 * b11 + a22 * b12;
  
      out[2] = a11 * b21 + a21 * b22;
      out[3] = a12 * b21 + a22 * b22;
  
      return out;
  };
  
  mat2.smul = function(out, a, s) {
  
      out[0] = a[0] * s;
      out[1] = a[1] * s;
      out[2] = a[2] * s;
      out[3] = a[3] * s;
  
      return out;
  };
  
  mat2.sdiv = function(out, a, s) {
      s = s !== 0 ? 1 / s : s;
  
      out[0] = a[0] * s;
      out[1] = a[1] * s;
      out[2] = a[2] * s;
      out[3] = a[3] * s;
  
      return out;
  };
  
  mat2.determinant = function(a) {
  
      return a[0] * a[3] - a[2] * a[1];
  };
  
  mat2.inverse = function(out, a) {
      var m11 = a[0],
          m12 = a[2],
          m21 = a[1],
          m22 = a[3],
  
          det = m11 * m22 - m12 * m21;
  
      if (det === 0) {
          return mat2.identity(out);
      }
      det = 1 / det;
  
      out[0] = m22 * det;
      out[1] = -m12 * det;
      out[2] = -m21 * det;
      out[3] = m11 * det;
  
      return out;
  };
  
  mat2.transpose = function(out, a) {
      var tmp;
  
      if (out === a) {
          tmp = a[1];
          out[1] = a[2];
          out[2] = tmp;
      } else {
          out[0] = a[0];
          out[1] = a[2];
          out[2] = a[1];
          out[3] = a[3];
      }
  
      return out;
  };
  
  mat2.setRotation = function(out, angle) {
      var c = mathf.cos(angle),
          s = mathf.sin(angle);
  
      out[0] = c;
      out[1] = s;
      out[2] = -s;
      out[3] = c;
  
      return out;
  };
  
  mat2.getRotation = function(out) {
      return mathf.atan2(out[1], out[0]);
  };
  
  mat2.rotate = function(out, a, angle) {
      var m11 = a[0],
          m12 = a[2],
          m21 = a[1],
          m22 = a[3],
  
          s = mathf.sin(angle),
          c = mathf.cos(angle);
  
      out[0] = m11 * c + m12 * -s;
      out[2] = m21 * c + m22 * -s;
  
      out[1] = m11 * s + m12 * c;
      out[3] = m21 * s + m22 * c;
  
      return out;
  };
  
  mat2.fromMat32 = function(out, m) {
  
      out[0] = m[0];
      out[1] = m[1];
      out[2] = m[2];
      out[3] = m[3];
  
      return out;
  };
  
  mat2.fromMat3 = function(out, m) {
  
      out[0] = m[0];
      out[1] = m[1];
      out[2] = m[3];
      out[3] = m[4];
  
      return out;
  };
  
  mat2.fromMat4 = function(out, m) {
  
      out[0] = m[0];
      out[1] = m[1];
      out[2] = m[4];
      out[3] = m[5];
  
      return out;
  };
  
  mat2.equals = function(a, b, e) {
      return !mat2.notEquals(a, b, e);
  };
  
  mat2.notEquals = function(a, b, e) {
      return (!mathf.equals(a[0], b[0], e) ||
          !mathf.equals(a[1], b[1], e) ||
          !mathf.equals(a[2], b[2], e) ||
          !mathf.equals(a[3], b[3], e)
      );
  };
  
  mat2.str = function(out) {
      return (
          "Mat2[" + out[0] + ", " + out[2] + ",\n" +
          "     " + out[1] + ", " + out[3] + "]"
      );
  };
  
  mat2.string = mat2.toString = mat2.str;
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/mat3@0.0.3/src/index.js-=@*/
  var mathf = require(5),
      isNumber = require(7);
  
  
  var mat3 = exports;
  
  
  mat3.ArrayType = typeof(Float32Array) !== "undefined" ? Float32Array : mathf.ArrayType;
  
  
  mat3.create = function(m11, m12, m13, m21, m22, m23, m31, m32, m33) {
      var out = new mat3.ArrayType(9);
  
      out[0] = isNumber(m11) ? m11 : 1;
      out[1] = isNumber(m21) ? m21 : 0;
      out[2] = isNumber(m31) ? m31 : 0;
      out[3] = isNumber(m12) ? m12 : 0;
      out[4] = isNumber(m22) ? m22 : 1;
      out[5] = isNumber(m32) ? m32 : 0;
      out[6] = isNumber(m13) ? m13 : 0;
      out[7] = isNumber(m23) ? m23 : 0;
      out[8] = isNumber(m33) ? m33 : 1;
  
      return out;
  };
  
  mat3.copy = function(out, a) {
  
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
      out[4] = a[4];
      out[5] = a[5];
      out[6] = a[6];
      out[7] = a[7];
      out[8] = a[8];
  
      return out;
  };
  
  mat3.clone = function(a) {
      var out = new mat3.ArrayType(9);
  
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
      out[4] = a[4];
      out[5] = a[5];
      out[6] = a[6];
      out[7] = a[7];
      out[8] = a[8];
  
      return out;
  };
  
  mat3.set = function(out, m11, m12, m13, m21, m22, m23, m31, m32, m33) {
  
      out[0] = isNumber(m11) ? m11 : 1;
      out[1] = isNumber(m21) ? m21 : 0;
      out[2] = isNumber(m31) ? m31 : 0;
      out[3] = isNumber(m12) ? m12 : 0;
      out[4] = isNumber(m22) ? m22 : 1;
      out[5] = isNumber(m32) ? m32 : 0;
      out[6] = isNumber(m13) ? m13 : 0;
      out[7] = isNumber(m23) ? m23 : 0;
      out[8] = isNumber(m33) ? m33 : 1;
  
      return out;
  };
  
  mat3.identity = function(out) {
  
      out[0] = 1;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 1;
      out[5] = 0;
      out[6] = 0;
      out[7] = 0;
      out[8] = 1;
  
      return out;
  };
  
  mat3.zero = function(out) {
  
      out[0] = 0;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 0;
      out[5] = 0;
      out[6] = 0;
      out[7] = 0;
      out[8] = 0;
  
      return out;
  };
  
  mat3.mul = function(out, a, b) {
      var a11 = a[0],
          a12 = a[3],
          a13 = a[6],
          a21 = a[1],
          a22 = a[4],
          a23 = a[7],
          a31 = a[2],
          a32 = a[5],
          a33 = a[8],
  
          b11 = b[0],
          b12 = b[3],
          b13 = b[6],
          b21 = b[1],
          b22 = b[4],
          b23 = b[7],
          b31 = b[2],
          b32 = b[5],
          b33 = b[8];
  
      out[0] = a11 * b11 + a21 * b12 + a31 * b13;
      out[3] = a12 * b11 + a22 * b12 + a32 * b13;
      out[6] = a13 * b11 + a23 * b12 + a33 * b13;
  
      out[1] = a11 * b21 + a21 * b22 + a31 * b23;
      out[4] = a12 * b21 + a22 * b22 + a32 * b23;
      out[7] = a13 * b21 + a23 * b22 + a33 * b23;
  
      out[2] = a11 * b31 + a21 * b32 + a31 * b33;
      out[5] = a12 * b31 + a22 * b32 + a32 * b33;
      out[8] = a13 * b31 + a23 * b32 + a33 * b33;
  
      return out;
  };
  
  mat3.smul = function(out, a, s) {
  
      out[0] = a[0] * s;
      out[1] = a[1] * s;
      out[2] = a[2] * s;
      out[3] = a[3] * s;
      out[4] = a[4] * s;
      out[5] = a[5] * s;
      out[6] = a[6] * s;
      out[7] = a[7] * s;
      out[8] = a[8] * s;
  
      return out;
  };
  
  mat3.sdiv = function(out, a, s) {
      s = s !== 0 ? 1 / s : s;
  
      out[0] = a[0] * s;
      out[1] = a[1] * s;
      out[2] = a[2] * s;
      out[3] = a[3] * s;
      out[4] = a[4] * s;
      out[5] = a[5] * s;
      out[6] = a[6] * s;
      out[7] = a[7] * s;
      out[8] = a[8] * s;
  
      return out;
  };
  
  mat3.determinant = function(out) {
      var a = out[0],
          b = out[1],
          c = out[2],
          d = out[3],
          e = out[4],
          f = out[5],
          g = out[6],
          h = out[7],
          i = out[8];
  
      return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
  };
  
  mat3.inverseMat = function(out, m11, m12, m13, m21, m22, m23, m31, m32, m33) {
      var m0 = m22 * m33 - m23 * m32,
          m3 = m13 * m32 - m12 * m33,
          m6 = m12 * m23 - m13 * m22,
  
          det = m11 * m0 + m21 * m3 + m31 * m6;
  
      if (det === 0) {
          return mat3.identity(out);
      } else {
          det = 1 / det;
  
          out[0] = m0 * det;
          out[1] = (m23 * m31 - m21 * m33) * det;
          out[2] = (m21 * m32 - m22 * m31) * det;
  
          out[3] = m3 * det;
          out[4] = (m11 * m33 - m13 * m31) * det;
          out[5] = (m12 * m31 - m11 * m32) * det;
  
          out[6] = m6 * det;
          out[7] = (m13 * m21 - m11 * m23) * det;
          out[8] = (m11 * m22 - m12 * m21) * det;
  
          return out;
      }
  };
  
  mat3.inverse = function(out, a) {
      return mat3.inverseMat(
          out,
          a[0], a[3], a[6],
          a[1], a[4], a[7],
          a[2], a[5], a[8]
      );
  };
  
  mat3.inverseMat4 = function(out, a) {
      return mat3.inverseMat(
          out,
          a[0], a[4], a[8],
          a[1], a[5], a[9],
          a[2], a[6], a[10]
      );
  };
  
  mat3.transpose = function(out, a) {
      var a01, a02, a12;
  
      if (out === a) {
          a01 = a[1];
          a02 = a[2];
          a12 = a[5];
          out[1] = a[3];
          out[2] = a[6];
          out[3] = a01;
          out[5] = a[7];
          out[6] = a02;
          out[7] = a12;
      } else {
          out[0] = a[0];
          out[1] = a[3];
          out[2] = a[6];
          out[3] = a[1];
          out[4] = a[4];
          out[5] = a[7];
          out[6] = a[2];
          out[7] = a[5];
          out[8] = a[8];
      }
  
      return out;
  };
  
  mat3.scale = function(out, a, v) {
      var x = v[0],
          y = v[1],
          z = v[2];
  
      out[0] *= x;
      out[3] *= y;
      out[6] *= z;
      out[1] *= x;
      out[4] *= y;
      out[7] *= z;
      out[2] *= x;
      out[5] *= y;
      out[8] *= z;
  
      return out;
  };
  
  mat3.setScale = function(out, v) {
      return mat3.set(
          out,
          v[0], 0, 0,
          0, v[1], 0,
          0, 0, v[2]
      );
  };
  
  mat3.setRotationX = function(out, angle) {
      var c = mathf.cos(angle),
          s = mathf.sin(angle);
  
      return mat3.set(
          out,
          1, 0, 0,
          0, c, -s,
          0, s, c
      );
  };
  
  mat3.setRotationY = function(out, angle) {
      var c = mathf.cos(angle),
          s = mathf.sin(angle);
  
      return mat3.set(
          out,
          c, 0, s,
          0, 1, 0, -s, 0, c
      );
  };
  
  mat3.setRotationZ = function(out, angle) {
      var c = mathf.cos(angle),
          s = mathf.sin(angle);
  
      return mat3.set(
          out,
          c, -s, 0,
          s, c, 0,
          0, 0, 1
      );
  };
  
  mat3.fromQuat = function(out, q) {
      var x = q[0],
          y = q[1],
          z = q[2],
          w = q[3],
          x2 = x + x,
          y2 = y + y,
          z2 = z + z,
          xx = x * x2,
          xy = x * y2,
          xz = x * z2,
          yy = y * y2,
          yz = y * z2,
          zz = z * z2,
          wx = w * x2,
          wy = w * y2,
          wz = w * z2;
  
      out[0] = 1 - (yy + zz);
      out[1] = xy + wz;
      out[2] = xz - wy;
  
      out[3] = xy - wz;
      out[4] = 1 - (xx + zz);
      out[5] = yz + wx;
  
      out[6] = xz + wy;
      out[7] = yz - wx;
      out[8] = 1 - (xx + yy);
  
      return out;
  };
  
  mat3.fromMat2 = function(out, m) {
  
      out[0] = m[0];
      out[1] = m[1];
      out[2] = 0.0;
  
      out[3] = m[2];
      out[4] = m[3];
      out[5] = 0.0;
  
      out[6] = 0.0;
      out[7] = 0.0;
      out[8] = 1.0;
  
      return out;
  };
  
  mat3.fromMat32 = mat3.fromMat2;
  
  mat3.fromMat4 = function(out, m) {
  
      out[0] = m[0];
      out[1] = m[1];
      out[2] = m[2];
  
      out[3] = m[4];
      out[4] = m[5];
      out[5] = m[6];
  
      out[6] = m[8];
      out[7] = m[9];
      out[8] = m[10];
  
      return out;
  };
  
  mat3.equals = function(a, b, e) {
      return !mat3.notEquals(a, b, e);
  };
  
  mat3.notEquals = function(a, b, e) {
      return (!mathf.equals(a[0], b[0], e) ||
          !mathf.equals(a[1], b[1], e) ||
          !mathf.equals(a[2], b[2], e) ||
          !mathf.equals(a[3], b[3], e) ||
          !mathf.equals(a[4], b[4], e) ||
          !mathf.equals(a[5], b[5], e) ||
          !mathf.equals(a[6], b[6], e) ||
          !mathf.equals(a[7], b[7], e) ||
          !mathf.equals(a[8], b[8], e)
      );
  };
  
  mat3.str = function(out) {
      return (
          "Mat3[" + out[0] + ", " + out[3] + ", " + out[6] + ",\n" +
          "     " + out[1] + ", " + out[4] + ", " + out[7] + ",\n" +
          "     " + out[2] + ", " + out[5] + ", " + out[8] + "]"
      );
  };
  
  mat3.string = mat3.toString = mat3.str;
  
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/attributes/Attribute1i.js-=@*/
  var Attribute = require(98);
  
  
  module.exports = Attribute1i;
  
  
  function Attribute1i(context, name, location) {
      Attribute.call(this, context, name, location);
  }
  Attribute.extend(Attribute1i);
  
  Attribute1i.prototype.set = function(buffer, offset, force) {
      var context = this.context,
          gl = context.gl;
  
      context.setAttribPointer(this.location, 1, gl.FLOAT, buffer.stride, offset, context.setArrayBuffer(buffer) || force);
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/attributes/Attribute1f.js-=@*/
  var Attribute = require(98);
  
  
  module.exports = Attribute1f;
  
  
  function Attribute1f(context, name, location) {
      Attribute.call(this, context, name, location);
  }
  Attribute.extend(Attribute1f);
  
  Attribute1f.prototype.set = function(buffer, offset, force) {
      var context = this.context,
          gl = context.gl;
  
      context.setAttribPointer(this.location, 1, gl.FLOAT, buffer.stride, offset, context.setArrayBuffer(buffer) || force);
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/attributes/Attribute2i.js-=@*/
  var Attribute = require(98);
  
  
  module.exports = Attribute2i;
  
  
  function Attribute2i(context, name, location) {
      Attribute.call(this, context, name, location);
  }
  Attribute.extend(Attribute2i);
  
  Attribute2i.prototype.set = function(buffer, offset, force) {
      var context = this.context,
          gl = context.gl;
  
      context.setAttribPointer(this.location, 2, gl.FLOAT, buffer.stride, offset, context.setArrayBuffer(buffer) || force);
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/attributes/Attribute3i.js-=@*/
  var Attribute = require(98);
  
  
  module.exports = Attribute3i;
  
  
  function Attribute3i(context, name, location) {
      Attribute.call(this, context, name, location);
  }
  Attribute.extend(Attribute3i);
  
  Attribute3i.prototype.set = function(buffer, offset, force) {
      var context = this.context,
          gl = context.gl;
  
      context.setAttribPointer(this.location, 3, gl.FLOAT, buffer.stride, offset, context.setArrayBuffer(buffer) || force);
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/attributes/Attribute4i.js-=@*/
  var Attribute = require(98);
  
  
  module.exports = Attribute4i;
  
  
  function Attribute4i(context, name, location) {
      Attribute.call(this, context, name, location);
  }
  Attribute.extend(Attribute4i);
  
  Attribute4i.prototype.set = function(buffer, offset, force) {
      var context = this.context,
          gl = context.gl;
  
      context.setAttribPointer(this.location, 4, gl.FLOAT, buffer.stride, offset, context.setArrayBuffer(buffer) || force);
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/attributes/Attribute2f.js-=@*/
  var Attribute = require(98);
  
  
  module.exports = Attribute2f;
  
  
  function Attribute2f(context, name, location) {
      Attribute.call(this, context, name, location);
  }
  Attribute.extend(Attribute2f);
  
  Attribute2f.prototype.set = function(buffer, offset, force) {
      var context = this.context,
          gl = context.gl;
  
      context.setAttribPointer(this.location, 2, gl.FLOAT, buffer.stride, offset, context.setArrayBuffer(buffer) || force);
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/attributes/Attribute3f.js-=@*/
  var Attribute = require(98);
  
  
  module.exports = Attribute3f;
  
  
  function Attribute3f(context, name, location) {
      Attribute.call(this, context, name, location);
  }
  Attribute.extend(Attribute3f);
  
  Attribute3f.prototype.set = function(buffer, offset, force) {
      var context = this.context,
          gl = context.gl;
  
      context.setAttribPointer(this.location, 3, gl.FLOAT, buffer.stride, offset, context.setArrayBuffer(buffer) || force);
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/attributes/Attribute4f.js-=@*/
  var Attribute = require(98);
  
  
  module.exports = Attribute4f;
  
  
  function Attribute4f(context, name, location) {
      Attribute.call(this, context, name, location);
  }
  Attribute.extend(Attribute4f);
  
  Attribute4f.prototype.set = function(buffer, offset, force) {
      var context = this.context,
          gl = context.gl;
  
      context.setAttribPointer(this.location, 4, gl.FLOAT, buffer.stride, offset, context.setArrayBuffer(buffer) || force);
      return this;
  };
  },
  function(require, exports, module, undefined, global) {
  /*@=-@nathanfaucett/webgl_context@0.0.1/src/attributes/Attribute.js-=@*/
  var inherits = require(38);
  
  
  module.exports = Attribute;
  
  
  function Attribute(context, name, location) {
      this.name = name;
      this.location = location;
      this.context = context;
  }
  
  Attribute.extend = function(child) {
      return inherits(child, this);
  };
  
  Attribute.prototype.set = function( /* buffer, offset, force */ ) {
      return this;
  };
  }], {}, void(0), (new Function("return this;"))()));
  