2013-06-27 4 views
3

У меня проблема с началом работы с WebGL. Я не понимаю, почему, но причина, почему он не работает, - это перспективная матрица.Квадрат не отображается с использованием матрицы перспективы

Таким образом, есть код, который не работает с перспективной матрицей:

<script type="x-shader/x-fragment" id="shader-fs"> 
    void main (void) { 
     gl_FragColor = vec4(1,1,1,1); 
    } 
</script> 
<script type="x-shader/x-vertex" id="shader-vs"> 
    attribute vec3 aVertexPosition; 

    uniform mat4 pMatrix; 
    uniform mat4 mvMatrix; 

    void main(void) { 
     gl_Position = pMatrix * mvMatrix * vec4(aVertexPosition, 1.0); 
    } 
</script> 
<script type="text/javascript"> 
    function makePerspective(fovy, aspect, znear, zfar) { 
     var ymax = znear * Math.tan(fovy * Math.PI/360.0); 
     var ymin = -ymax; 
     var xmin = ymin * aspect; 
     var xmax = ymax * aspect; 

     return makeFrustum(xmin, xmax, ymin, ymax, znear, zfar); 
    } 

    function makeFrustum(left, right, 
         bottom, top, 
         znear, zfar) { 
     var X = 2*znear/(right-left); 
     var Y = 2*znear/(top-bottom); 
     var A = (right+left)/(right-left); 
     var B = (top+bottom)/(top-bottom); 
     var C = -(zfar+znear)/(zfar-znear); 
     var D = -2*zfar*znear/(zfar-znear); 

     return [X, 0, A, 0, 
       0, Y, B, 0, 
       0, 0, C, D, 
       0, 0, -1, 0]; 
    } 

    function identity() { 
     return [ 
      1,0,0,0, 
      0,1,0,0, 
      0,0,1,0, 
      0,0,0,1 
     ]; 
    } 

    var canvas, gl; 
    var win = {w: 0,h: 0}; 
    var shaderProgram, vertexPositionAttribute; 
    var horizAspect = 480/640; 
    var squareVerticesBuffer; 

    function getShader(gl, id) { 
     var shaderScript = document.getElementById(id); 

     if (!shaderScript) { 
      return null; 
     } 

     theSource = ""; 
     currentChild = shaderScript.firstChild; 

     while (currentChild) { 
      if (currentChild.nodeType == currentChild.TEXT_NODE) { 
       theSource += currentChild.textContent; 
      } 

      currentChild = currentChild.nextSibling; 
     } 

     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,theSource); 
     gl.compileShader(shader); 

     if (!gl.getShaderParameter(shader,gl.COMPILE_STATUS)) { 
      alert("An error compiling the shader "+gl.getShaderInfoLog(shader)); 
      return null; 
     } 

     return shader; 
    } 
    function initShaders() { 
     var fragmentShader = getShader(gl,"shader-fs"); 
     var vertexShader = getShader(gl,"shader-vs"); 

     shaderProgram = gl.createProgram(); 
     gl.attachShader(shaderProgram,fragmentShader); 
     gl.attachShader(shaderProgram,vertexShader); 
     gl.linkProgram(shaderProgram); 

     if (!gl.getProgramParameter(shaderProgram,gl.LINK_STATUS)) { 
      alert("Cannot init shaders!"); 
     } 

     gl.useProgram(shaderProgram); 

     vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); 
     gl.enableVertexAttribArray(vertexPositionAttribute); 
    } 
    function initBuffers() { 
     squareVerticesBuffer = gl.createBuffer(); 
     gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer); 

     var vertices = [ 
      1,1,0, 
      -1,1,0, 
      1,-1,0, 
      -1,-1,0, 
     ]; 

     gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices),gl.STATIC_DRAW); 
    } 
    function drawScene() { 
     gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 

     gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer); 
     gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0); 

     var perspectiveMatrix = makePerspective(45,640/480,0.1,100); 
     /* if you set up the line above^to: [ 
       1,0,0,0, 
       0,1,0,0, 
       0,0,1,0, 
       0,0,0,1 
      ] it will work 
     */ 
     var pUniform = gl.getUniformLocation(shaderProgram, "pMatrix"); 
     gl.uniformMatrix4fv(pUniform, false, new Float32Array(perspectiveMatrix)); 

     var mvMatrix = identity(); 

     var mvUniform = gl.getUniformLocation(shaderProgram, "mvMatrix"); 
     gl.uniformMatrix4fv(mvUniform, false, new Float32Array(mvMatrix)); 

     gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 
    } 

    function load() { 
     canvas = document.getElementById("c"); 
     gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); 
     win.w = canvas.width; win.h = canvas.height; 

     if (gl) { // Ok! 
      gl.clearColor(0.0, 0.0, 0.0, 1.0); 
      gl.enable(gl.DEPTH_TEST); 
      gl.depthFunc(gl.LEQUAL); 
      gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT); 

      initShaders(); 
      initBuffers(); 

      drawScene(); 
     } 
     else { // Fallback to 2d! 
      gl = canvas.getContext("2d"); 

      gl.font = "14px Arial"; 
      gl.textAlign = "center"; 
      gl.textBaseline = "bottom"; 
      gl.fillStyle = "#000"; 

      gl.fillText("You're browser doesn't support WebGL!",win.w/2,win.h/2); 
     } 
    } 

    window.onload = load; 
</script> 

Я взял код из этого example. Но я не хочу использовать Sylvester или glMatrix.

ответ

1

Я нашел решение моей проблемы! Я ошибался в идее создания матричных массивов, каждый следующий 4 элемента - это столбцы, а не строки. Таким образом, матрица перевод будет:

var arr = [ 
    1,0,0,0, 
    0,1,0,0, 
    0,0,1,0, 
    vx,vy,vz,1, 
]; 

не нравится:

var arr = [ 
    1,0,0,vx, 
    0,1,0,vy, 
    0,0,1,vz, 
    0,0,0,1, 
]; 
+0

Эта вещь называется транспонированной матрицы. – volter9