0

Hi guys I been studying webgl these days.

There are two snippets that accomplish the same thing - draw a square. One is using gl.drawArrays for 6 vertices and one is using gl.drawElements for 4 vertices.

However I noticed that when using gl.drawArrays, we can unbind gl.ARRAY_BUFFER before using it, it doesn't matter. See the snippets.

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 = [
        // first triangle (V0, V1, V2)
        -0.5, 0.5, 0,
        -0.5, -0.5, 0,
        0.5, -0.5, 0,

        // second triangle (V0, V2, V3)
        -0.5, 0.5, 0,
        0.5, -0.5, 0,
        0.5, 0.5, 0
      ];

      // Setting up the VBO
      squareVertexBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
        gl.vertexAttribPointer(program.aVertexPosition, 3, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(program.aVertexPosition);
      // Clean
      gl.bindBuffer(gl.ARRAY_BUFFER, null);
    }

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);

      gl.drawArrays(gl.TRIANGLES, 0, 6);

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

initBuffers() is called before draw(). Notice here I already unbind gl.ARRAY_BUFFER before calling gl.drawArrays and it successfully draws the square.

However when using gl.drawElements, I have to make sure gl.ELEMENT_ARRAY_BUFFER is currently binded to the correct indices. e.g.

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, squareIndexBuffer);
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);

if I use gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); like I did for gl.drawArrays, I have to rebind it using gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, squareIndexBuffer); before calling gl.drawElements.

BDL
  • 21,052
  • 22
  • 49
  • 55
Joji
  • 4,703
  • 7
  • 41
  • 86

1 Answers1

1

This is mostly explained in this answer: https://stackoverflow.com/a/27164577/128511

The short version is gl.drawArrays uses only attributes. Attributes have buffers bound to them when you call gl.vertexAttribPointer. Whatever buffer was bound do gl.ARRAY_BUFFER at the time you call gl.verexAttribPointer is copied into the state of that attribute.

Attributes themselves are state of the current Vertex Array Object (VAO) as is the current ELEMENT_ARRAY_BUFFER. VAOs are an optional extension in WebGL1 and a standard part of WebGL2.

Again refer to this answer: https://stackoverflow.com/a/27164577/128511 and also this answer: https://stackoverflow.com/a/50257695/128511

gman
  • 100,619
  • 31
  • 269
  • 393
  • Hi thanks for your reply. I am not exactly sure what you meant by `Whatever buffer was bound do gl.ARRAY_BUFFER at the time you call gl.verexAttribPointer is copied into the state of that attribute.` However I looked at those links you put out and I felt like I am getting the hang of it. Correct me if I am wrong. The reason `gl.drawArrays` doesn't need rebind is because `gl.vertexAttribPointer` has internally stored the arrayBuffer so that we can just use. On the other hand `gl.drawElements` has the global elementArrayBuffer, so we have to rebind it if we unbinded it before. – Joji Jan 29 '19 at 19:12
  • Correct for `gl.drawArrays`. For `gl.drawElements` the elementArrayBuffer is part of the current `vertexArray` state. In WebGL1 there is only one global vertexArray unless you enable the `OES_vertex_array` extension. In WebGL2 there are as many vertexArrays as you create (see `gl.createVertexArray`, `gl.bindVertexArray`). A vertex array contains all of the attribute state **and** the elementArrayBuffer state – gman Jan 29 '19 at 23:12
  • thanks for your reply! Since we can have multiple VAOs in webgl2 to store attribute state and the elementArrayBuffer state, do we need to distinguish which VAO stores which attribute state and which elementArrayBuffer state? Is there a way to check? – Joji Jan 30 '19 at 00:38