0
votes

I have a flat plane and an index buffer, or EBO with the indices marked on the image:

enter image description here

Now if I call:

glDrawElementsBaseVertex(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0, 0);

I get this:

enter image description here

This I understand. Further, If I do this:

glDrawElementsBaseVertex(GL_TRIANGLES, 9, GL_UNSIGNED_INT, 0, 0);

enter image description here

This makes sense too. But my understanding completely falls apart when I change one of the other parameters. If I do this:

glDrawElementsBaseVertex(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0, 3);

It looks like this:

enter image description here

So by passing the argument 3 to the basevertex argument (the last one), it's started using the index not from 3 positions into the index, and not even from 3 triangles into the index, but it's started about 6 triangles in, or more precisely index number 18. I can't understand this behaviour.

Also, I have read contradicting meanings for the argument of "indices" in these functions:

void glDrawElements(GLenum mode,  GLsizei count,  GLenum type,  const GLvoid * indices);
void glDrawElementsBaseVertex(GLenum mode​, GLsizei count​, GLenum type​, GLvoid *indices​, GLint basevertex​);

I've read that the indices pointer gives you the possibility to refer to an index buffer directly by providing a pointer, and if it is null then the index buffer is taken from the currently bound GL_ELEMENT_ARRAY_BUFFER. However from the documentation in one version it says:

indices Specifies a byte offset (cast to a pointer type) into the buffer bound to GL_ELEMENT_ARRAY_BUFFER to start reading indices from.

And in another version it says:

indices Specifies a pointer to the location where the indices are stored.

If I call glDrawElementsBaseVertex with the second last argument (indices) as (void*)3 I get the first triangle drawn red. If I specify (void*)6 I get no triangles highlighted. And if I specify (void*)9 I get the second triangle highlighted.

I can't make sense of any of this. So is it the case that this argument, indices, is NOT an optional pointer to the indices you wish to use instead of using the element array buffer currently bound?

3
Are your indices zero-based or one-based? Because OpenGL thinks they're zero-based.Nicol Bolas
@Nicol Bolas My indices are based on zero, as normal. I've figured out what the "indices" argument does, it's in fact an offset (in bytes) into my element array, so if you use GL_UNSIGNED_INT and you want to start at your second element you'd do (void*)sizeof(GLuint), that's what got me confused, that it was in bytes. I'm sure you knew this though. The last argument for glDrawElementsBaseVertex, baseVertex, I'm still not sure how this works, but I guess I may not need it if I can pick the beginning index element using the void* indices offset.Zebrafish
"My indices are based on zero, as normal." Then why does your diagram show indices starting at 1?Nicol Bolas
@Nicol Bolas Ah sorry for the confusion. They do start at zero, just when I was making the image I started numbering at 1.Zebrafish
I wonder if you ever resolved this?Anton Duzenko

3 Answers

2
votes

If you want to have an offset for the indices, you can simply use glDrawElements like so:

glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (void*)(sizeof(GLuint)*6));

It will draw 3 elements with an offset of 6 for indices.

The last argument of glDrawElements can be two different things:

  1. if you don't have an indices buffer bound to GL_ELEMENT_ARRAY_BUFFER, it is a pointer to the location where the indices are stored.
  2. if you do have an indices buffer bound to GL_ELEMENT_ARRAY_BUFFER, it is an offset in bytes for that array.
0
votes

You should also show us how you number your vertices. From the screenshot it looks like the vertices are aligned by rows. In that case it correctly renders vertices in the third cell because that's where the 3rd vertex is.

You should set base vertex to 1 if you want to render the first half of cell 2, because that's where vertex 2 is.

Similarly, if you want to render the second half of cell 2 then you should set base pointer to 1 and index pointer to 3.

0
votes

A little late to reply but I just ran into a need to call this GL function and I too struggled with its behavior.

I'm willing to bet that the numbers you've included in your first image are NOT the actual index values in your index buffer, but simply indicate the ORDER that you are specifying vertices. Assuming your vertex buffer is organized as follows:

enter image description here

where the red numbers I've added are the vertex buffer array indices, your actual index buffer contents should begin with {0,1,6,1,7,6,...}.

So with basevertex equal to zero, calling glDrawElementsBaseVertex() does the following:

When i=0, element zero from your index buffer (which has a value of zero), causes element zero (red numbers in the above image) in your vertex buffer to be used as the first vertex of your first triangle. With i=2, element two from the index buffer (value of six), causes element six in your vertex buffer to complete the first triangle.

Quoting the documentation for glDrawElementsBaseVertex()

"the ith element transferred by the corresponding draw call will be taken from element indices[i] + basevertex of each enabled array."

Ya, that's a little confusing but it means that after the index value is retrieved from the index buffer, basevertex is added to it. So with a basevertex of 3, we have the following behavior:

When i=0, element zero from your index buffer is retrieved. As before, it has a value of zero but now three is added to it. So element three in your vertex buffer (again, red numbers in the above image) is used as the first vertex of your first triangle. With i=2, element two from the index buffer is retrieved which has a value of six but three is added to that, so element nine from your vertex buffer is used to complete the first triangle.

Hope this helps.