How does this code work with multiple buffer bound to same target?

I have this webgl code

const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positionData, gl.STATIC_DRAW);

const pointSizeBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, pointSizeBuffer);
gl.bufferData(gl.ARRAY_BUFFER, pointSizeData, gl.STATIC_DRAW);

gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.vertexAttribPointer(aPositionLoc, 2, gl.FLOAT, false, 0, 0);

gl.bindBuffer(gl.ARRAY_BUFFER, pointSizeBuffer);
gl.vertexAttribPointer(aPointSizeLoc, 1, gl.FLOAT, false, 0, 0);

other things are in place and this code works fine, so I am not pasting the whole code to keep the code short.

I am new to WebGL and I am trying to form a mental model of things.

So my current thought process is that only one buffer is bound to a target (ARRAY_BUFFER in this case ), and when a draw call happens, data is read from that.

But how I am interpreting this code is that

  1. when I bind the pointSizeBuffer, positionBuffer should not be bound
  2. If positionBuffer is no longer bound and the code is still working, that means vertextAttribPointer is able to bind the values to attributes and even if the buffer is not bound anymore, those values persist.

Is this the correct thinking?

I tried googling a bit and I found that only one buffer can be bound at once, so this code's behavior was surprising to me, I was expecting that shaders would not get position data and would only get pointSize data because that was the last one bound.

I am a Webgl noob, so not very clear in understanding these terms like buffer, target, etc, but I am trying to go step by step.

PS I know that we can interleave values in one buffer and I made that work so don't suggest that. I am just trying to understand how things are working


  • The Vertex Buffer binding (ARRAY_BUFFER) is a global state. However, the binding of the array buffer to a specific vertex array specification is stored in the state vector of the Vertex Array Object. Each attribute which is stated in the VAOs state vector may refer to a different array buffer. When vertexAttribPointer is called the buffer which is currently bound to the target ARRAY_BUFFER, is associated to the specified attribute index and the ID of the object is stored in the state vector of the currently bound VAO.
    (By the way, the WebGL 2.0 API conforms closely to the OpenGL ES 3.0 API.)