Meu codigo webgl diminui o desenho se sair do centro, porque?

Com o código abaixo você pode desenhar cubo,triângulo,quadrado e pirâmides…
Porém a cada desenho ao se distanciar do centro do canvas o desenho geometrico diminui,
E eu quero saber porque isso acontece,
E como resolver este problema.
Pois o meu desenho no OpenGL2.0 não distorce a imagem geométrica, porém o meu código WebGL distorce, então se alguém poder me ajudar…me ajude por favor eu não sei o que fazer pra resolver isso.

<html>
  <head>
    <meta charset="utf-8"/>
    <script id="shader-vs" type="x-shader/x-vertex">
      attribute vec3 aVertexPosition;
      attribute vec4 aVertexColor;
      
      uniform mat4 uMMatrix;
      uniform mat4 uVMatrix;
      uniform mat4 uPMatrix;
      
      varying vec4 vColor;

      void main(void)
      {
	gl_Position = uPMatrix * uVMatrix * uMMatrix * vec4(aVertexPosition, 1.0);
	vColor = aVertexColor;
      }
    </script>
    <script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
      varying vec4 vColor;

      void main(void)
      {
	gl_FragColor=vColor;
      }
    </script>
    
    <!--Funções-->
    <script type="text/javascript" src="glMatrix-0.9.5.min.js"></script>
    <script type="text/javascript" src="jquery-2.1.0.min.js"></script>
    <script type="text/javascript" src="webgl-utils.js"></script>
    
    <script type="text/javascript">
    
      var gl;
      var shaderProgram;
      var triangleVertexPositionBuffer;
      var squareVertexPositionBuffer;
      var triangleVertexColorBuffer;
      var squareVertexColorBuffer;
      var piramideVertexPositionBuffer;
var piramideVertexColorBuffer;
var cuboVertexPositionBuffer;
var cuboVertexColorBuffer;
      
      var mMatrix = mat4.create();
      var mMatrixPilha = [];
      var pMatrix = mat4.create();
      var vMatrix = mat4.create();
      
      var rTri = 0;
      var rQuad = 0;
      var rPiramide = 0;
  var rCubo = 0;
  
      var ultimo = 0;
      // Iniciar o ambiente quando a página for carregada
      $(function()
      {
	iniciaWebGL();
      });
      
      // Iniciar o ambiente
      function iniciaWebGL()
      {
	var canvas = $('#licao01-canvas')[0];
	iniciarGL(canvas); // Definir como um canvas 3D
	iniciarShaders();  // Obter e processar os Shaders
	iniciarAmbiente(); // Definir background e cor do objeto
	tick();
      }
      
      function tick()
      {
	requestAnimFrame(tick);
	desenharCena();
	animar();
      }
      function iniciarGL(canvas)
      {
	try
	{
	  gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
	  gl.viewportWidth = canvas.width;
	  gl.viewportHeight = canvas.height;
	}
	catch(e)
	{
	  if(!gl)
	  {
	    alert("Não pode inicializar WebGL, desculpe");
	  }
	}
      }
      
      function iniciarShaders()
      {
	var vertexShader = getShader(gl, "#shader-vs");
	var fragmentShader = getShader(gl, "#shader-fs");
	
	shaderProgram = gl.createProgram();
	gl.attachShader(shaderProgram, vertexShader);
	gl.attachShader(shaderProgram, fragmentShader);
	gl.linkProgram(shaderProgram);
	
	if(!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS))
	{
	  alert("Não pode inicializar shaders");
	}
	
	gl.useProgram(shaderProgram);
	
	shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
	gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
	
	shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
	gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);
	
	shaderProgram.vertexTextureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
gl.enableVertexAttribArray(shaderProgram.vertexTextureCoordAttribute);

	
	shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
	shaderProgram.vMatrixUniform = gl.getUniformLocation(shaderProgram, "uVMatrix");
	shaderProgram.mMatrixUniform = gl.getUniformLocation(shaderProgram, "uMMatrix");
	
	
      }
      
      function getShader(gl, id)
      {
	var shaderScript = $(id)[0];
	if(!shaderScript) 
	{
	  return null;
	}
	
	var str = "";
	var k = shaderScript.firstChild;
	while(k)
	{
	  if(k.nodeType == 3)
	    str += k.textContent;
	  k = k.nextSibling;
	}
	
	var shader;
	if(shaderScript.type == "x-shader/x-fragment")
	{
	  shader = gl.createShader(gl.FRAGMENT_SHADER);
	}
	else if(shaderScript.type == "x-shader/x-vertex")
	{
	  shader = gl.createShader(gl.VERTEX_SHADER);
	}
	else
	{
	  return null;
	}
	
	gl.shaderSource(shader, str);
	gl.compileShader(shader);
	
	if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
	{
	  alert(gl.getShaderInfoLog(shader));
	  return null;
	}
	
	return shader;
      }
      

      
      function iniciarAmbiente()
      {
	gl.clearColor(0.0, 0.0, 0.0, 1.0);
	gl.enable(gl.DEPTH_TEST);
      }
      
      function desenharCena()
      {
	gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
	mat4.perspective(45,gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
	mat4.identity(mMatrix);
	mat4.identity(vMatrix);
drawQuad(0.0,0,-24,1,1,1,60,0,0,1,0,1,0);//parede atraz
drawQuad(4,0,-24,1,1,1,60,0,0,1,1,0,0);//parede atraz

      }
 function drawPiramede(tx,ty,tz,sx,sy,sz,rPiramideX,rPiramideY,rPiramideZ,A,R,G,B){
piramideVertexPositionBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, piramideVertexPositionBuffer);
	var vertices = [
	    // Frente
	    0.0,  1.0,  0.0,
	   -1.0, -1.0,  1.0,
	    1.0, -1.0,  1.0,
	  // Direita
	    0.0,  1.0,  0.0,
	    1.0, -1.0,  1.0,
	    1.0, -1.0, -1.0,
	  // Trás
	    0.0,  1.0,  0.0,
	    1.0, -1.0, -1.0,
	   -1.0, -1.0, -1.0,
	  // Esquerda
	    0.0,  1.0,  0.0,
	   -1.0, -1.0, -1.0,
	   -1.0, -1.0,  1.0
	];
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
	piramideVertexPositionBuffer.itemSize = 3;
	piramideVertexPositionBuffer.numItems = 12;
	
	piramideVertexColorBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, piramideVertexColorBuffer);
	var cores = [
	    // Frente
	    R,G,B,A,
	    R,G,B,A,
	    R,G,B,A,
	    // Direita
	    R,G,B,A,
	    R,G,B,A,
	    R,G,B,A,
	    // Trás
	    R,G,B,A,
	    R,G,B,A,
	    R,G,B,A,
	    // Esquerda
	    R,G,B,A,
	    R,G,B,A,
	    R,G,B,A
	];
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(cores), gl.STATIC_DRAW);
	piramideVertexColorBuffer.itemSize = 4;
	piramideVertexColorBuffer.numItems = 12;
// Desenhando Pirâmide
	mat4.translate(mMatrix,[tx,ty,tz]);
	
	mPushMatrix();
	mat4.rotate(mMatrix, degToRad(rPiramideX),[1,0,0]);
	mat4.rotate(mMatrix, degToRad(rPiramideY),[0,1,0]);
	mat4.rotate(mMatrix, degToRad(rPiramideZ),[0,0,1]);
	mat4.scale(mMatrix,[sx,sy,sz]);
	
	gl.bindBuffer(gl.ARRAY_BUFFER, piramideVertexPositionBuffer);
	gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, piramideVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
	gl.bindBuffer(gl.ARRAY_BUFFER, piramideVertexColorBuffer);
	gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, piramideVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
	setMatrixUniforms();
	gl.drawArrays(gl.TRIANGLES, 0, piramideVertexPositionBuffer.numItems);
	mPopMatrix();
 }
 function drawCube(tx,ty,tz,sx,sy,sz,rPiramideX,rPiramideY,rPiramideZ,A,R,G,B){
cuboVertexPositionBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, cuboVertexPositionBuffer);
	vertices = [
	  // Front face
	  -1.0, -1.0,  1.0,
	  1.0, -1.0,  1.0,
	  1.0,  1.0,  1.0,
	  -1.0,  1.0,  1.0,

	  // Back face
	  -1.0, -1.0, -1.0,
	  -1.0,  1.0, -1.0,
	  1.0,  1.0, -1.0,
	  1.0, -1.0, -1.0,

	  // Top face
	  -1.0,  1.0, -1.0,
	  -1.0,  1.0,  1.0,
	  1.0,  1.0,  1.0,
	  1.0,  1.0, -1.0,

	  // Bottom face
	  -1.0, -1.0, -1.0,
	  1.0, -1.0, -1.0,
	  1.0, -1.0,  1.0,
	  -1.0, -1.0,  1.0,

	  // Right face
	  1.0, -1.0, -1.0,
	  1.0,  1.0, -1.0,
	  1.0,  1.0,  1.0,
	  1.0, -1.0,  1.0,

	  // Left face
	  -1.0, -1.0, -1.0,
	  -1.0, -1.0,  1.0,
	  -1.0,  1.0,  1.0,
	  -1.0,  1.0, -1.0
	];
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
	cuboVertexPositionBuffer.itemSize = 3;
	cuboVertexPositionBuffer.numItems = 4;
	
	cuboVertexColorBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, cuboVertexColorBuffer);
	cores = [
	  [R,G,B,A],     // Frente
	  [R,G,B,A],     // Trás
	  [R,G,B,A],     // Topo
	  [R,G,B,A],     // Base
	  [R,G,B,A],     // Direita
	  [R,G,B,A]      // Esquerda
	];
	var coresReplicadas = [];
	for (var i in cores) {
	  var cor = cores[i];
	  for (var j=0; j < 4; j++) {
	    coresReplicadas = coresReplicadas.concat(cor);
	  }
	}
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(coresReplicadas), gl.STATIC_DRAW);
	cuboVertexColorBuffer.itemSize = 4;
	cuboVertexColorBuffer.numItems = 24;
	
	cuboVertexIndexBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cuboVertexIndexBuffer);
	var indices = [
	  0, 1, 2,      0, 2, 3,    // Frente
	  4, 5, 6,      4, 6, 7,    // Trás
	  8, 9, 10,     8, 10, 11,  // Topo
	  12, 13, 14,   12, 14, 15, // Base
	  16, 17, 18,   16, 18, 19, // Direita
	  20, 21, 22,   20, 22, 23  // Esquerda
	]
	gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
	cuboVertexIndexBuffer.itemSize = 1;
	cuboVertexIndexBuffer.numItems = 36;
// Desenhando o Quadrado
	mat4.translate(mMatrix,[tx,ty,tz]);
	
	mPushMatrix();
	mat4.rotate(mMatrix, degToRad(rPiramideX),[1,0,0]);
	mat4.rotate(mMatrix, degToRad(rPiramideY),[0,1,0]);
	mat4.rotate(mMatrix, degToRad(rPiramideZ),[0,0,1]);
	mat4.scale(mMatrix,[sx,sy,sz]);
	
	gl.bindBuffer(gl.ARRAY_BUFFER, cuboVertexPositionBuffer);
	gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, cuboVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
	gl.bindBuffer(gl.ARRAY_BUFFER, cuboVertexColorBuffer);
	gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, cuboVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cuboVertexIndexBuffer);
	setMatrixUniforms();
	gl.drawElements(gl.TRIANGLES, cuboVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT,0);
	mPopMatrix();
 }
 function drawTriangle(tx,ty,tz,sx,sy,sz,rPiramideX,rPiramideY,rPiramideZ,A,R,G,B){
triangleVertexPositionBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
	var vertices = [
	     0.0, 1.0, 0.0,
	    -1.0,-1.0, 0.0,
	     1.0,-1.0, 0.0
	];
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
	triangleVertexPositionBuffer.itemSize = 3;
	triangleVertexPositionBuffer.numItems = 3;
	
	triangleVertexColorBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexColorBuffer);
	var cores = [
	    R,G,B,A,
	    R,G,B,A,
	    R,G,B,A
	];
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(cores), gl.STATIC_DRAW);
	triangleVertexColorBuffer.itemSize = 4;
	triangleVertexColorBuffer.numItems = 3;

 	// Desenhando Triângulo
	mat4.translate(mMatrix,[tx,ty,tz]);
	
	mPushMatrix();
	mat4.rotate(mMatrix, degToRad(rPiramideX),[1,0,0]);
	mat4.rotate(mMatrix, degToRad(rPiramideY),[0,1,0]);
	mat4.rotate(mMatrix, degToRad(rPiramideZ),[0,0,1]);
	mat4.scale(mMatrix,[sx,sy,sz]);
	
	gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
	gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, triangleVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
	gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexColorBuffer);
	gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, triangleVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
	setMatrixUniforms();
	gl.drawArrays(gl.TRIANGLES, 0, triangleVertexPositionBuffer.numItems);
	
	mPopMatrix();
 }
 function drawQuad(tx,ty,tz,sx,sy,sz,rPiramideX,rPiramideY,rPiramideZ,A,R,G,B){
squareVertexPositionBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
	vertices = [
	  1.0, 1.0, 0.0,
	 -1.0, 1.0, 0.0,
	  1.0,-1.0, 0.0,
	 -1.0,-1.0, 0.0
	];
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
	squareVertexPositionBuffer.itemSize = 3;
	squareVertexPositionBuffer.numItems = 4;
	
	squareVertexColorBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer);
	cores = [];
	for(var i =0; i < 4; i++)
	{
	  cores = cores.concat([R,G,B,A]);
	}
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(cores), gl.STATIC_DRAW);
	squareVertexColorBuffer.itemSize = 4;
	squareVertexColorBuffer.numItems = 4;
 // Desenhando o Quadrado
	mat4.translate(mMatrix,[tx,ty,tz]);
	
	mPushMatrix();
	mat4.rotate(mMatrix, degToRad(rPiramideX),[1,0,0]);
	mat4.rotate(mMatrix, degToRad(rPiramideY),[0,1,0]);
	mat4.rotate(mMatrix, degToRad(rPiramideZ),[0,0,1]);
	mat4.scale(mMatrix,[sx,sy,sz]);
	
	gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
	gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
	gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer);
	gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, squareVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
	setMatrixUniforms();
	gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);
mPopMatrix();
 }
      function setMatrixUniforms()
      {
	gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
	gl.uniformMatrix4fv(shaderProgram.vMatrixUniform, false, vMatrix);
	gl.uniformMatrix4fv(shaderProgram.mMatrixUniform, false, mMatrix);
      }
      
      // o 'var ultimo = 0' está no topo (todos as vars globais estão juntas)
      function animar()
      {
	var agora = new Date().getTime();
	if(ultimo != 0)
	{
	  var diferenca = agora-ultimo;
	  rTri  += ((90*diferenca)/1000.0) % 360.0;
	  rQuad += ((75*diferenca)/1000.0) % 360.0;
	rPiramide  += ((90*diferenca)/1000.0) % 360.0;
  rCubo += ((75*diferenca)/1000.0) % 360.0;
	}
	ultimo = agora;
      }
      
      function mPushMatrix()
      {
	var copy = mat4.create();
	mat4.set(mMatrix, copy);
	mMatrixPilha.push(copy);
      }
      
      function mPopMatrix()
      {
	if(mMatrixPilha.length == 0)
	{
	  throw "inválido popMatrix!";
	}
	mMatrix = mMatrixPilha.pop();
      }
      
      function degToRad(graus)
      {
	return graus * Math.PI / 180;
      }
    </script>
    
    <!--Aparência da página (canvas, background...)-->
    <style>
      canvas
      {
	border:none;
	width:500px;
	height:500px;
      }
    </style>
    
  </head>
  
  <body>
    <canvas id="licao01-canvas" width="500" height="500"></canvas>
  </body>
</html>