为什么我的变换矩阵不能转换点?

Why won't my transformation matrix translate the points?

我一直在尝试在 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); 点得到翻译。但是,这破坏了使用矩阵的要点。

原因在于您的着色器数学运算,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 被定义为 vec3 并且代码为每个顶点传递 2 个值,因此 z = 0。当 z = 0矩阵中的平移乘以 0。

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

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