Search code examples
ipadopengl-es-2.0vertex-buffer

How do you use glVerttexAttribPointer in conjunction with glBufferData?


In the stock "rotating cube" OpenGL example for iOS 5, they have this code:

glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW);

glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));

The messed up part there is the last argument to glVertexAttribPointer. The docs say the last argument is a pointer to an array.

But in this program they are using straight numbers. Indeed, BUFFER_OFFSET is defined as

#define BUFFER_OFFSET(i) ((char *)NULL + (i))

So are they relying on their gCubeVertexData array starting at memory address 0?

So, I don't understand 2 things:

  1. Why doesn't the example work (no cubes are drawn) when I "correct" the 3rd line of code to

    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, gCubeVertexData );
    
  2. What is the correct way to invoke glVertexAttribPointer?

I thought you were supposed to pass a memory pointer for the last index as the documentation says. Indeed, here another sample uses glVertexAttribPointer:

glVertexAttribPointer(ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(vertexStruct), &vertices[0].position);
glEnableVertexAttribArray(ATTRIB_POSITION);
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(vertexStruct), &vertices[0].color);
glEnableVertexAttribArray(ATTRIB_COLOR);

So you see in the latter example they have passed memory addresses for pointer (last arg), not straight numbers.


Solution

  • glVertexAttribPointer can be used in two ways:

    1) With client side vertex arrays. In this case, the final argument is a pointer to an array, you're correct about this.

    2) In addition to being used as a pointer, if you read further down in that documentation page you linked, it says this:

    If a non-zero named buffer object is bound to the GL_ARRAY_BUFFER target (see glBindBuffer) while a generic vertex attribute array is specified, pointer is treated as a byte offset into the buffer object's data store.

    This is for when you're using the glVertexAttribPointer to point at a VBO, a buffer that you've previously uploaded to opengl (glBindBuffer/glBufferData).

    To clarify:

    If you don't have an active buffer bound with glBindBuffer, glVertexAttribArray takes a pointer. If you do have a buffer bound, then glVertexAttribArray takes an offset into the bound buffer. This will be the value 0 if you want to start drawing from the start of the buffer.