Skip to main content
GameDev.net gamedev.net
🔒 Locked

glDrawElements mystery

Started by Gergo Sep 7, 2007 at 9:18 AM 6 replies 5.5k views
Original Post
Gergo
Gergo
Hi! Please someone help me solve this mystery because it's driving me crazy! The same code compiles on my computer, while on another computer, it throws an access violation. The code is: float verts[5*3]; GLubyte idx[10]; verts[0]=0; verts[1]=-10; verts[2]=0; verts[3]=-10; verts[4]=0; verts[5]=-10; verts[6]=10; verts[7]=0; verts[8]=-10; verts[9]=0; verts[10]=0; verts[11]=10; verts[12]=0; verts[13]=10; verts[14]=0; idx[0]=0; idx[1]=1; idx[2]=2; idx[3]=3; idx[4]=1; idx[5]=4; idx[6]=2; idx[7]=1; idx[8]=3; idx[9]=2; glGenBuffersARB(1,&vbuff); glBindBufferARB(GL_ARRAY_BUFFER_ARB,vbuff); glBufferDataARB(GL_ARRAY_BUFFER_ARB,15*sizeof(float),verts,GL_STATIC_DRAW_ARB); glGenBuffersARB(1,&ibuff); glBindBufferARB(GL_ARRAY_BUFFER_ARB,ibuff); glBufferDataARB(GL_ARRAY_BUFFER_ARB,10*sizeof(GLubyte),idx,GL_STATIC_DRAW_ARB); drawlist=glGenLists(1); glNewList(drawlist,GL_COMPILE); glEnableClientState(GL_VERTEX_ARRAY); glBindBufferARB(GL_ARRAY_BUFFER,vbuff); glVertexPointer(3,GL_FLOAT,sizeof(float)*3,NULL); glEnableClientState(GL_INDEX_ARRAY); glBindBufferARB(GL_ARRAY_BUFFER,ibuff); glIndexPointer(GL_UNSIGNED_BYTE,sizeof(GLubyte),NULL); glDrawElements(GL_TRIANGLE_FAN,5,GL_UNSIGNED_BYTE,&idx[0]); glDrawElements(GL_TRIANGLE_FAN,5,GL_UNSIGNED_BYTE,&idx[5]); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_INDEX_ARRAY); glEndList(); The problem is with the glDrawElements() calls, it throws an access violation. If I use glDrawArrays() instead, it works fine on both computers.
theZapper
theZapper
I think your call to

glVertexPointer(3,GL_FLOAT,sizeof(float)*3,NULL);

Might be causing it. It looks like you are specifying a stride of sizeof(float)*3 . The Red Book says "Stride is the byte offset between consecutive vertexes. If stride is 0, the vertices are understood to be tightly packed in the array". Which yours are.

The stride setting is used for glInterleavedArrays I believe.
---When I'm in command, every mission's a suicide mission!
Brother Bob
Brother Bob
The stride is correct. The offset between two consecutive vertices is 3 floats. A stride of 0 would also work, since the arrays are tightly packed. It's a special case where the driver automatically calculates the correct stride.

Your use of the index buffer array is wrong. glIndexPointer is not what you think it is. It's for indexed colors, but I assume you're not living in the 1980's and using RGB color mode instead. In that case, colors are specified with glColorPointer.
theZapper
theZapper
Good call Bob.

Also, when perusing the glVertexPointer entry in MSDN, it says "You cannot include glVertexPointer in display lists."

I hardly use display lists, not sure if this applies in GL_COMPILE mode.
---When I'm in command, every mission's a suicide mission!
Kalidor
Kalidor
glIndexPointer is for color indices, not vertex indices. It is the analog of glColorPointer while in color index mode. Vertex indices are only passed through glDraw[Range]Elements. If you want to use a VBO for vertex index data, you have to create a GL_ELEMENT_ARRAY_BUFFER and then pass an offset to glDraw[Range]Elements like you do when using a GL_ARRAY_BUFFER in the gl*Pointer functions.

Also, why are you trying to use display lists and VBOs simultaneously? It should work but it defeats the purpose of using the VBO since it is just compiled into the display list anyway. I could imagine that being an area where driver bugs are more likely because it is such an odd thing to do that it isn't well tested.

Do you have any other client array state enabled that you aren't using? That usually causes crashes on some cards.

What cards are in the two computers?

[EDIT] That post took way too long [depressed]
Quote:
Originally posted by theZapper
Also, when perusing the glVertexPointer entry in MSDN, it says "You cannot include glVertexPointer in display lists."
You can still use it in a display list but it isn't compiled into the list, it is executed immediately. So the vertex data is basically read from the array (or VBO) and stored directly in the display list.
Gergo
Gergo
Then it must be a miracle, that with glIndexPointer() it worked the way I expected :) Anyway, thank you all for the help, I removed the display list, and I'm using the element_array_buffer, but there's still something wrong with the offset. The code:
init:

glGenBuffersARB(1,&vbuff);
glBindBufferARB(GL_ARRAY_BUFFER_ARB,vbuff);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,15*sizeof(float),verts,GL_STATIC_DRAW_ARB);

glGenBuffersARB(1,&ibuff);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,ibuff);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,10*sizeof(GLubyte),idx,GL_STATIC_DRAW_ARB);

drawing:

glEnableClientState(GL_VERTEX_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB,vbuff);
glVertexPointer(3,GL_FLOAT,sizeof(float)*3,NULL);

glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,ibuff);
glDrawElements(GL_TRIANGLE_FAN,5,GL_UNSIGNED_BYTE,&idx[0]);
glDrawElements(GL_TRIANGLE_FAN,5,GL_UNSIGNED_BYTE,&idx[5]);

glDisableClientState(GL_VERTEX_ARRAY);

If I say: glDrawElements(GL_TRIANGLE_FAN,5,GL_UNSIGNED_BYTE,NULL) then it works, but if I pass the pointer as an offset, it doesn't do anything. What did I do wrong?
Kalidor
Kalidor
Quote:
Original post by Gergo
If I say: glDrawElements(GL_TRIANGLE_FAN,5,GL_UNSIGNED_BYTE,NULL) then it works, but if I pass the pointer as an offset, it doesn't do anything. What did I do wrong?
That's what you did wrong. [grin]

When using a GL_ELEMENT_ARRAY_BUFFER (VBO with index data), the indices parameter of glDraw[Range]Elements is treated similarly to the pointer parameter of the various gl*Pointer functions when using VBOs. That is, instead of passing a pointer to the data in system memory you are passing an offset into the currently bound VBO (GL_ARRAY_BUFFER for the gl*Pointer functions or GL_ELEMENT_ARRAY_BUFFER for glDraw[Range]Elements).

So when you use glDrawElements(..., NULL) you're saying to offset 0 bytes into the currently bound GL_ELEMENT_ARRAY_BUFFER and start using the indices from that point. When you use glDrawElements(..., &idx[5]) you're saying to offset some number of bytes equal to the address of the 5th element of the idx array, which doesn't make any sense and I'm surprised that doesn't crash. What you need to do instead is pass the number of bytes that the 5th element is from the 0th element of the idx array. Since you're using 1-byte indices, that should be 5.

Anyway, I hope that was understandable (and correct, it's been a while since I've actually used OpenGL [sad]).
Gergo
Gergo
Thanks a lot, it works!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.