Нужно ли повторно связывать IBO после привязки VAO во время розыгрыша? - PullRequest
0 голосов
/ 31 января 2019

Привет, я изучал webgl.

Я читал эту книгу под названием Real-Time 3D Graphics with WebGL 2, и здесь говорится, что объекты массива Vertex позволяют нам хранить всю информацию о привязке вершин / индексов для набора буферов водин, простой в управлении объект.

И он предоставляет этот пример для VAO.

 function initBuffers() {
      /*
        V0                    V3
        (-0.5, 0.5, 0)        (0.5, 0.5, 0)
        X---------------------X
        |                     |
        |                     |
        |       (0, 0)        |
        |                     |
        |                     |
        X---------------------X
        V1                    V2
        (-0.5, -0.5, 0)       (0.5, -0.5, 0)
      */
      const vertices = [
        -0.5, 0.5, 0,
        -0.5, -0.5, 0,
        0.5, -0.5, 0,
        0.5, 0.5, 0
      ];

      // Indices defined in counter-clockwise order
      indices = [0, 1, 2, 0, 2, 3];

      // Create VAO instance
      squareVAO = gl.createVertexArray();

      // Bind it so we can work on it
      gl.bindVertexArray(squareVAO);

      const squareVertexBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

      // Provide instructions for VAO to use data later in draw
      gl.enableVertexAttribArray(program.aVertexPosition);
      gl.vertexAttribPointer(program.aVertexPosition, 3, gl.FLOAT, false, 0, 0);

      // Setting up the IBO
      squareIndexBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, squareIndexBuffer);
      gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

      // Clean
      gl.bindVertexArray(null);
      gl.bindBuffer(gl.ARRAY_BUFFER, null);
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
    }

    // We call draw to render to our canvas
    function draw() {
      // Clear the scene
      gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
      gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

      // Bind the VAO
      gl.bindVertexArray(squareVAO);

      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, squareIndexBuffer);

      // Draw to the scene using triangle primitives
      gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);

      // Clean
      gl.bindVertexArray(null);
      gl.bindBuffer(gl.ARRAY_BUFFER, null);
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
    }

    // Entry point to our application
    function init() {
      // Retrieve the canvas
      const canvas = utils.getCanvas('webgl-canvas');

      // Set the canvas to the size of the screen
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;

      // Retrieve a WebGL context
      gl = utils.getGLContext(canvas);
      // Set the clear color to be black
      gl.clearColor(0, 0, 0, 1);

      // Call the functions in an appropriate order
      initProgram();
      initBuffers();
      draw();
    }

Вопрос здесь в том, нужно ли нам gl.bindBuffer(); после того, как мы свяжем VAO в draw()?

Я посмотрел на эту ссылку Что такое массивы вершин в OpenGL и WebGL2? и там написано At draw time it then only takes one call to gl.bindVertexArray to setup all the attributes and the ELEMENT_ARRAY_BUFFER.Итак, я полагаю, что нет необходимости в gl.bindBuffer(); после того, как мы свяжем VAO в draw()?Код из учебника вводит в заблуждение?

1 Ответ

0 голосов
/ 31 января 2019

Нет, вам не нужно перепривязывать буфер

Привязка ELEMENT_ARRAY_BUFFER является частью текущего состояния массива вершин в качестве ответа, на который вы ссылаетесь, указывает.

Эти строки в вашем примеретакже не имеет значения

In initBuffers

  // Clean
  gl.bindVertexArray(null);
  gl.bindBuffer(gl.ARRAY_BUFFER, null);
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);

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

Эта строка

  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);

на самом деле ничего не делает, потому что, как указано выше, состояние ELEMENT_ARRAY_BUFFER является частью текущего массива вершин, поэтомупросто изменение текущего массива вершин с помощью gl.bindVertexArray уже изменило эту привязку.

Эта строка

  gl.bindBuffer(gl.ELEMENT_BUFFER, null);

на самом деле не имеет смысла, потому что AFAIK почти ни в одной из программ не предполагает, что текущая привязка ARRAY_BUFFER установленани к чему.Они всегда связывают буфер перед работой с ним.Это неплохо, и я уверен, что вы могли бы найти какой-то запутанный способ сделать это важным, но в реальной жизни я не видел его.

Эта линия имеет точку.

  gl.bindVertexArray(null);

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

  // at init time
  for each thing I plan to draw
    (1) create buffers and fill with positions/normals/texcoords/indices
    (2) create/bind vertex array
    (3) setup attributes and ELEMENT_ARRAY_BUFFER

Тогда, если вы не привязываете null после шага 3, шаг 1 в итоге изменит привязку ELEMENT_ARRAY_BUFFER дляранее связанный массив вершин

Другими словами, возможно, эта строка

  gl.bindVertexArray(null);

имеет точку.Тем не менее, это спорно.Если вы поменяли местами шаги 1 и 2 и изменили инициализацию на

  // at init time
  for each thing I plan to draw
    (1) create/bind vertex array
    (2) create buffers and fill with positions/normals/texcoords/indices
    (3) setup attributes

, тогда проблема исчезнет

Те же 3 строки существуют в draw

  // Clean
  gl.bindVertexArray(null);
  gl.bindBuffer(gl.ARRAY_BUFFER, null);
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);

Где они опять не имеют смысла

...