Почему моя матрица преобразования не переводит точки? - PullRequest
0 голосов
/ 21 июня 2020

Я пытался использовать свои собственные матрицы в 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);, очки будут переведены. Однако это лишает смысла использование матриц.

1 Ответ

1 голос
/ 22 июня 2020

Причина в математике вашего шейдера, 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.

Вы можете либо изменить данные вершины, чтобы они передавались в 1 для z, либо измените шейдер, чтобы принудительно установить значение 1.

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