Почему мы используем дважды bindVertexArray (vao)? - PullRequest
0 голосов
/ 14 октября 2019

Я новичок в WebGL и пытаюсь выучить WebGL2. Но я не очень понимаю, как работает WebGL. Особенно ВАО и ВБО. Я искал диаграммы того, как работает память, но я не мог ее найти. Я привел следующий пример и постараюсь объяснить, как этот пример работает.

function main(){
    // initialize GL
    // create vertex shader and fragment shader
    // create program

    var positionAttributeLocation = gl.getAttribLocation(program, "a_position");

    var positionBuffer = gl.createBuffer();

    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

    // define positions with array

    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

    var vao = gl.createVertexArray();

    gl.bindVertexArray(vao);

    gl.enableVertexAttribArray(positionAttributeLocation);

    // ....
    gl.vertexAttribPointer(
        positionAttributeLocation, size, type, normalize, stride, offset
    );

    gl.viewport(0, 0, 400, 300);

    // clear canvas
    // use program

    gl.bindVertexArray(vao);        // why we use that here ?

    var primitiveType = gl.TRIANGLES;
    var offset = 0;
    var count = 3;
    gl.drawArrays(primitiveType, offset, count);
}
  1. Во-первых, я получил атрибут в программе вершинного шейдера, который мы будем использовать для VAO. Я могу думать, что это слот 0.
  2. Затем я создал буфер для позиций (массив).
  3. Активированный буфер с функцией bindBuffer().
  4. Затем позиции добавляются в буфер.
  5. Создан VAO и активирован с помощью bindVertexArray().
  6. Включен слот 0, и я добавлю данные (позиции) в слот 0. Это как параметр для vertexAttribFunction().

Это ситуация, которую я могу понять. Тогда ситуация запутывается. Почему мы снова вызываем bindVertexArray (vao)? Существуют ли также подробные схемы работы VAO и VBO в WebGL?

1 Ответ

3 голосов
/ 15 октября 2019

Нормально рисовать отдельный объект в WebGL. Если у вас более 1 объекта и вы используете объекты массива вершин (VAO), тогда

во время инициализации

for each object
  create a vertex array object VAO and bind it
  create all the buffers for this object
  setup all the attributes for this object

во время отрисовки

for each object
  bind the VAO for this object
  set uniforms for this object (and optionally bind textures for this object)
  draw

Такда, если вы рисуете только одну вещь, то связывание VAO дважды может показаться странным, но схема связывания VAO один раз во время инициализации и снова во время рисования является обычной вещью, потому что обычная вещь - рисоватьнесколько объектов.

Обратите внимание, что это ничем не отличается от любого другого API с сохранением состояния. Например, Canvas 2d API. Вы могли бы написать это

ctx.fillStyle = 'red';

function renderLoop(time) {
   ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
   ctx.fillRect(x, y, 20, 20);  // assume X and Y are animated
   ...
}

Но опять же, это ненормально - рисовать только одну вещь, поэтому большинство людей, даже если они только начинают с 1, сделают это

function renderLoop(time) {
   ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
   ctx.fillStyle = 'red';
   ctx.fillRect(x, y, 20, 20);  // assume X and Y are animated
   ...
}

Даже еслиизбыточно устанавливать fillStyle каждый кадр. Они делают это, потому что они ожидают нарисовать больше вещей позже, так что это становится шаблоном для установки состояния, связанного с вещью, которую вы хотите нарисовать, прямо перед тем, как нарисовать .

function renderLoop(time) {
   ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
   ctx.fillStyle = 'red';
   ctx.fillRect(x, y, 20, 20);  // assume X and Y are animated
   ctx.fillStyle = 'blue';
   ctx.fillRect(x2, y2, 20, 20);  // assume x2 and y2 are animated
   ...
}

Каксостояние VAO см. this и состояние текстуры см. this

...