Попытка использовать «атрибут mat4», а не «атрибут равномерный» - PullRequest
0 голосов
/ 30 октября 2018

У меня есть эта переменная 'xformMatrix', и каждый элемент содержит массив из 16 значений:

var xformMatrix = 
[[0.9238795325112867, 0.3826834323650898, 0.0,
  -0.3826834323650898, 0.9238795325112867, 0.0, 0.0,
  0.0, 0.0, 1.0, 0.0,
  0.0, 0.0, 0.0, 1.0],
 [0.7071067811865476, 0.7071067811865475, 0.0, 0.0,
  -0.7071067811865475, 0.7071067811865476, 0.0, 0.0,
  0.0, 0.0, 1.0, 0.0,
  0.0, 0.0, 0.0, 1.0],
 [0.38268343236508984, 0.9238795325112867, 0.0, 0.0,
  -0.9238795325112867, 0.38268343236508984, 0.0, 0.0,
  0.0, 0.0, 1.0, 0.0,
  0.0, 0.0, 0.0, 1.0],
 [6.123233995736766e-17, 1, 0.0, 0.0,
  -1, 6.123233995736766e-17, 0.0, 0.0,
  0.0, 0.0, 1.0, 0.0,
  0.0, 0.0, 0.0, 1.0]]

Я пытаюсь использовать матрицу 4x4 в качестве атрибута, чтобы вращать мои треугольники, не заполняя мой массив вершин больше, чем он есть. Я думаю, что я запутался, когда gl.vertexAttribPointer запрашивает размер:

gl.vertexAttribPointer(a_xformMatrix, 1, gl.FLOAT, false, 6 * 
Float32Array.BYTES_PER_ELEMENT, 5 * Float32Array.BYTES_PER_ELEMENT);

Вот как настроены мои шейдеры:

var VSHADER_SOURCE =
  'attribute vec4 a_Position;\n' +
  'attribute mat4 a_xformMatrix;\n' +
  'attribute vec3 a_Color;\n' +
  'varying vec3 v_Color;\n' +
  'void main() {\n' +
  '  v_Color = a_Color;\n' +
  '  gl_Position = a_xformMatrix * a_Position;\n' +
  '}\n';

// Fragment shader program
var FSHADER_SOURCE =
  'precision mediump float;\n' +
  'varying vec3 v_Color;\n' +
  'void main() {\n' +
  '  gl_FragColor = vec4(v_Color, 1.0);\n' +
  '}\n';

Пример моей функции:

function initVertexBuffers(gl) {

  // Triangle Verticies
  var vertices = new Float32Array(
  [ // x, y             r, g, b             rotate matrix
    0.0, 0.5,           1.0, 0.0, 0.0,      xformMatrix[0],
    -0.5, -0.5,         1.0, 0.0, 0.0,      xformMatrix[0],
    0.5, -0.5,          1.0, 0.0, 0.0,      xformMatrix[0],
    0.0, 0.5,           0.0, 1.0, 0.0,      xformMatrix[1],
    -0.5, -0.5,         0.0, 1.0, 0.0,      xformMatrix[1],
    0.5, -0.5,          0.0, 1.0, 0.0,      xformMatrix[1],
    0.0, 0.5,           0.0, 0.0, 1.0,      xformMatrix[2],
    -0.5, -0.5,         0.0, 0.0, 1.0,      xformMatrix[2],
    0.5, -0.5,          0.0, 0.0, 1.0,      xformMatrix[2],
    0.0, 0.5,           1.0, 0.0, 1.0,      xformMatrix[3],
    -0.5, -0.5,         1.0, 0.0, 1.0,      xformMatrix[3],
    0.5, -0.5,          1.0, 0.0, 1.0,      xformMatrix[3]
  ]);

  var n = 12; // The number of vertices

  // Create a buffer object
  var vertexBuffer = gl.createBuffer();
  if (!vertexBuffer) {
    console.log('Failed to create the buffer object');
    return false;
  }

  // Bind the buffer object to target
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  // Write date into the buffer object
  gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

  // Assign the buffer object to the position attribute variable
  var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
  if (a_Position < 0) {
    console.log('Failed to get the storage location of a_Position');
    return -1;
  }
  // Assign the buffer object to the color attribute variable
  var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
  if (a_Color < 0) {
    console.log('Failed to get the storage location of a_Color');
    return -1;
  }
  // Assign the buffer object to the rotation matrix attribute variable
  var a_xformMatrix = gl.getAttribLocation(gl.program, 'a_xformMatrix');
  if (a_xformMatrix < 0) {
    console.log('Failed to get the storage location of a_xformMatrix');
    return -1;
  }

  // Set Pointers
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 6 * Float32Array.BYTES_PER_ELEMENT, 0);
  gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, 6 * Float32Array.BYTES_PER_ELEMENT, 2 * Float32Array.BYTES_PER_ELEMENT);
  gl.vertexAttribPointer(a_xformMatrix, 1, gl.FLOAT, false, 6 * Float32Array.BYTES_PER_ELEMENT, 5 * Float32Array.BYTES_PER_ELEMENT);

  // Enable the assignment to a_Position variable
  gl.enableVertexAttribArray(a_Position);
  gl.enableVertexAttribArray(a_Color);
  gl.enableVertexAttribArray(a_xformMatrix);

  return n;
}

Окончательный результат должен выглядеть примерно так:

Output

Есть ли уловка, чтобы сделать это таким образом, или я просто иду в неправильном направлении?

1 Ответ

0 голосов
/ 31 октября 2018

То, что вы делаете, не распространено

У вас есть x, y, r, g, b, m [0], m [1], m [2], m [3], m [4], m [5], m [6 ], m [7], m [8], m [9], m [10], m [11], m [12], m [13], m [14], m [15] на вершину, так что шаг, поскольку вы пытаетесь поместить все данные в один и тот же буфер, будет

 21 * Float32Array.BYTES_PER_ELEMENT

Затем вам нужно установить 4 атрибута для mat4 и размер каждого из них равен 4 (4 атрибута, размер 4 каждый = 16 значений матрицы)

  // Set Pointers
  const stride = 21 * Float32Array.BYTES_PER_ELEMENT;
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, stride, 0);
  gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, stride, 2 * Float32Array.BYTES_PER_ELEMENT);
  gl.vertexAttribPointer(a_xformMatrix + 0, 4, gl.FLOAT, false, stride, 5 * Float32Array.BYTES_PER_ELEMENT);
  gl.vertexAttribPointer(a_xformMatrix + 1, 4, gl.FLOAT, false, stride, 9 * Float32Array.BYTES_PER_ELEMENT);
  gl.vertexAttribPointer(a_xformMatrix + 2, 4, gl.FLOAT, false, stride, 13 * Float32Array.BYTES_PER_ELEMENT);
  gl.vertexAttribPointer(a_xformMatrix + 3, 4, gl.FLOAT, false, stride, 17 * Float32Array.BYTES_PER_ELEMENT);

И, кроме того, этот код не помещает данные матрицы в массив Float32Array. Вы можете написать некоторый код для объединения данных или если вы хотите сделать это вручную

  var vertices = new Float32Array(
  [ // x, y             r, g, b             rotate matrix
    0.0, 0.5,           1.0, 0.0, 0.0,      
    xformMatrix[0][0], xformMatrix[0][1], xformMatrix[0][2], xformMatrix[0][3],
    xformMatrix[0][4], xformMatrix[0][5], xformMatrix[0][6], xformMatrix[0][7],
    xformMatrix[0][8], xformMatrix[0][9], xformMatrix[0][10], xformMatrix[0][11],
    xformMatrix[0][12], xformMatrix[0][13], xformMatrix[0][14], xformMatrix[0][15],
    ... repeat for the next vertex .. 
  ]);

Примечание. Я не удосужился проверить, внесете ли вы все эти изменения, будет ли работать ваш код. Только то, что, как вы сказали, вы пытаетесь сделать, - это наиболее очевидные проблемы.

Вы, вероятно, видите, что если вы пойдете этим путем, у вас будет тонна данных для обновления при попытке повернуть треугольники, чтобы вы, вероятно, захотели найти другой подход.

Ознакомьтесь с этими уроками . Первая статья рисует кучу прямоугольников разных цветов. Он использует один вызов отрисовки на цвет, что является наиболее распространенным способом. Затем он строится на использовании матриц в следующих статьях.

Вы также можете просто передать вращение на треугольник и вычислить вращение в шейдере. Тогда у вас будет только одно значение вращения на треугольник на вершину вместо матрицы на треугольник на вершину. Вам нужно обновить 3 поворота на треугольник, чтобы оживить их.

Вы также можете использовать непрямую текстуру, чтобы вместо поворота на треугольник на вершину у вас был идентификатор треугольника на треугольник на вершину. Таким образом, первые 3 вершины получают ID = 0, следующие 3 ID = 1 и т. Д. Вы передаете это в качестве атрибута, затем вы можете использовать его для генерации вращения, как в rotation = ID * constant, или вы можете использовать этот идентификатор для поиска вращения. в текстуре как в rotation = texture2D(textureWithRotationData, vec2((id + .5) / textureWidth, 0.5).r. Преимущество этого метода в том, что вам нужно всего лишь обновить 1 поворот на треугольник. Тот, что в текстуре.

...