代码之家  ›  专栏  ›  技术社区  ›  Rojo

矩阵不转换点Webgl

  •  0
  • Rojo  · 技术社区  · 4 年前

    我一直在尝试在WebGL(目前是2d)中使用我自己的矩阵。我的主要参考是 webglfundamentals.com 。我将360度旋转与(1,-1)比例、(-142,6)平移和投影矩阵相乘。我的矩形显示得很好,但没有平移。这是我的代码:

    var vertexShaderSource= `
    attribute vec3 a_position;
    uniform mat3 u_matrix;
    void main() {
      gl_Position = vec4(vec2(u_matrix * a_position), 0, 1);
    }`
    var fragmentShaderSource = `
    precision mediump float;
     
    void main() {
      gl_FragColor = vec4(1, 0, 0.5, 1);
    }`
    var canvas = document.querySelector("#c");
    var gl = canvas.getContext("webgl");
    var m3 = {
      multiply: function(a, b) {
        return [
          b[0] * a[0] + b[1] * a[3] + b[2] * a[6],
          b[0] * a[1] + b[1] * a[4] + b[2] * a[7],
          b[0] * a[2] + b[1] * a[5] + b[2] * a[8],
          b[3] * a[0] + b[4] * a[3] + b[5] * a[6],
          b[3] * a[1] + b[4] * a[4] + b[5] * a[7],
          b[3] * a[2] + b[4] * a[5] + b[5] * a[8],
          b[6] * a[0] + b[7] * a[3] + b[8] * a[6],
          b[6] * a[1] + b[7] * a[4] + b[8] * a[7],
          b[6] * a[2] + b[7] * a[5] + b[8] * a[8],
        ];
      },
      translation: function(tx, ty) {
        return [
          1, 0, 0,
          0, 1, 0,
          tx, ty, 1,
        ];
      },
      rotation: function(angleInRadians) {
        var c = Math.cos(angleInRadians);
        var s = Math.sin(angleInRadians);
        return [
          c, -s, 0,
          s, c, 0,
          0, 0, 1,
        ];
      },
      scaling: function(sx, sy) {
        return [
          sx, 0, 0,
          0, sy, 0,
          0, 0, 1,
        ];
      },
      projection: [
        2 / gl.canvas.clientWidth, 0, 0,
        0, -2 / gl.canvas.clientHeight, 0,
        -1, 1, 1
      ]
    }
    function createShader(gl, type, source) {
      var shader = gl.createShader(type);
      gl.shaderSource(shader, source);
      gl.compileShader(shader);
      if (gl.getShaderParameter(shader, gl.COMPILE_STATUS))
        return shader;
      console.log(gl.getShaderInfoLog(shader));
      return null;
    }
    var vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
    var fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
    function createProgram(gl, vertexShader, fragmentShader) {
      var program = gl.createProgram();
      gl.attachShader(program, vertexShader);
      gl.attachShader(program, fragmentShader);
      gl.linkProgram(program);
      if (gl.getProgramParameter(program, gl.LINK_STATUS))
        return program;
      console.log(gl.getProgramInfoLog(program));
      return null;
    }
    var program = createProgram(gl, vertexShader, fragmentShader);
    var positionAttributeLocation = gl.getAttribLocation(program, "a_position");
    var positionBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
    var positions = [
      10, 20,
      80, 20,
      10, 30,
      10, 30,
      80, 20,
      80, 30
    ];
    var translationMatrix = m3.translation(-142, 6);
    var rotationMatrix = m3.rotation(Math.PI * 2);
    var scaleMatrix = m3.scaling(1, -1);
    var matrix = m3.multiply(m3.projection, translationMatrix);
    matrix = m3.multiply(matrix, rotationMatrix);
    matrix = m3.multiply(matrix, scaleMatrix);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
    var resolutionUniformLocation = gl.getUniformLocation(program, "u_resolution");
    var matrixLocation = gl.getUniformLocation(program, "u_matrix");
    gl.viewport(0, 0, 800, 600);
    gl.clearColor(0.4, 0.4, 0.4, 0);
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.useProgram(program);
    gl.uniform2f(resolutionUniformLocation, 800, 600);
    gl.uniformMatrix3fv(matrixLocation, false, matrix);
    gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(positionAttributeLocation);
    gl.drawArrays(gl.TRIANGLES, 0, positions.length / 2);
    <html>
      <head>
        <title>webgl</title>
        <meta charset="UTF-8">
        <script src="gl-matrix.js"></script>
      </head>
      <body style="background-color: #222223;">
        <canvas id="c" tabindex="1" width="800" height="600">get good browser</canvas>
      </body>
    </html>

    如果我添加这样的翻译: gl_Position = vec4(a_position + translation, 1); 这些观点被翻译了。然而,这破坏了使用矩阵的要点。

    0 回复  |  直到 4 年前
        1
  •  1
  •   gman    4 年前

    原因在于着色器数学,z=0。

    着色器中的这条线

    gl_Position = vec4(vec2(u_matrix * a_position), 0, 1);
    

    与您链接到的文章中的这一行不同

    gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1);
    

    在您的代码中, a_position 被定义为a vec3 代码每个顶点传递2个值,因此 z = 0. 什么时候? z =0时,矩阵中的平移将乘以0。

    您可以更改顶点数据以将z传入1,也可以更改着色器以将其强制为1。

    gl_Position = vec4(vec2(u_matrix * vec3(a_position.xy, 1)), 0, 1);