Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BindBuffer and BufferData called back to back

In OpenGL ES (or in my case, WebGL), I don't see how binding vertex and color buffers back to back and then calling drawArrays works. For instance, here is some example code for you to get the idea:

vertexBuffer = glCreateBuffer();
glBindBuffer(GL_ARRAY_BUFFER, vertextBuffer);
glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);

colorBuffer = glCreateBuffer();
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glBufferData(GL_ARRAY_BUFFER, colors, GL_STATIC_DRAW);

glDrawArrays(GL_TRIANGLES, 0, numberOfVertices);

If I bind GL_ARRAY_BUFFER to first the vertices, bufferData, and then go and bind some colors, what is going on behind the scenes there? It somehow seems to me like the vertex information should be ignored because I bound color information to GL_ARRAY_BUFFER right after it.

like image 335
tau Avatar asked Jan 11 '23 14:01

tau


2 Answers

gl.vertexAttribPointer is what actually sets which attributes use which buffers.

You can think of it as

gl = { 
   arrayBuffer: someBuffer, 
   vertexArray: {
     elementArrayBuffer: someOtherBuffer,
     attributes: [], 
   },
};

When you call gl.bindBuffer you're just setting one of 2 global variables in the gl state.

gl.bindBuffer = function(bindPoint, buffer) {
   switch (bindPoint) {
      case: this.ARRAY_BUFFER:
         this.arrayBuffer = buffer;
         break;
      case: this.ELEMENT_ARRAY_BUFFER:
         this.vertexArray.elementArrayBuffer = buffer;
         break;
   }
};

When you call gl.vertexAttribPointer it copies current value of arrayBuffer to the specified attribute.

gl.vertexAttribPointer = function(index, size, type, normalized, stride, offset) {
    var attribute = this.vertexArray.attributes[index];
    attribute.size = size;
    attribute.type = type;
    attribute.normalized = normalized;
    attribute.stride = stride;
    attribute.offset = offset;
    attribute.buffer = this.arrayBuffer;  // copies the current buffer reference.
};

Textures work similarly except there's only 1 global variable

gl = { 
    activeTextureUnit: 0,
    textureUnits: [], 
};

gl.activeTexture sets which texture unit you're working on.

gl.activeTexture = function(unit) {
   this.activeTextureUnit = unit - this.TEXTURE_0;  // make it zero based.
};

Every texture unit has both a TEXTURE_2D and a TEXTURE_CUBEMAP so gl.bindTexture(b, t) is effectively

gl.bindTexture = function(bindPoint, texture) {
   var textureUnit = this.textureUnits[this.activeTextureUnit];
   switch (bindPoint) {
       case this.TEXTURE_2D:
           textureUnit.texture2D = texture;
           break;
       case this.TEXTURE_CUBEMAP:
           textureUnit.textureCubeMap = texture;
           break;
   }
};

Here is a webgl state diagram

like image 61
gman Avatar answered Jan 14 '23 02:01

gman


glDrawArrays() does not care what GL_ARRAY_BUFFER is bound at all. It does care about the vertex attrib pointers.

What really matters here is not shown in the code you pasted: the attribute pointer setup. The reference to the currently bound GL_ARRAY_BUFFER will become part of the attrib pointer when glVertexAttribPointer() is called. Different attributes can come from different VBOs, or you can use one VBO as a source for may attributes, that is completely up to you.

like image 41
derhass Avatar answered Jan 14 '23 02:01

derhass