PDA

View Full Version : glDrawElements (using VBOs) in display list



Narann
11-22-2011, 03:43 PM
Hi OpenGL community,

Hope you can help me on this. :)

I have a simple VBO of vertex.

For a reason (it's 3d modeler software), I can't have a nice index array to draw my geometry.

What I've thinked about was to use display list to do a loop of glDrawElements with, each time, indices it need to draw his polygon:



int facesCount = (int)faces.size();
glNewList(_quadDisplayList, GL_COMPILE);

for(int faceID = 0; faceID < facesCount; ++faceID){ // go throug each face and get an array of indice for this face
const std::vector<int> &amp;face = faces[faceID]; // return "face", an array of 3,4,5+ index.
glDrawElements(GL_POLYGON, face.size(), GL_INT, &amp;face[0]);
}

glEndList();

This doesn't seems to work... (a simplest display list work well so my display list call is ok, the problem doesn't came from here).

I've searched and find something interesting of the OpenGL doc:


glDrawElements is included in display lists. If glDrawElements is entered into a display list, the necessary array data (determined by the array pointers and enables) is also entered into the display list. Because the array pointers and enables are client-side state, their values affect display lists when the lists are created, not when the lists are executed.

But when I create this display list, no pointer is set because I set all of this after just before the draw...

So (first question), my solution is impossible using this way right?

Maybe I should store all indices (using a loop because indices are by face) in an array, store it in a VBO.

And do a display list using pointer offset:



int facesCount = (int)faces.size();

GLint quadIndices[idxArraySize];
int quadIndiceOffset = 0;
for(int faceID = 0; faceID < facesCount; ++faceID){
const std::vector<int> &amp;face = faces[faceID];
for(unsigned int index = 0; index < face.size(); ++index){
quadIndices[indiceOffset] = face[index]; // the index of the polygon of the face
indiceOffset++;
}
}

// store as VBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _idxBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint)*idxArraySize, (GLvoid*)&amp;quadIndices[0], GL_STATIC_DRAW);

int idOffset = 0;
glNewList(_quadDisplayList, GL_COMPILE);

for(int faceID = 0; faceID < facesCount; ++faceID){ // go throug each face and get an array of indice for this face
const std::vector<int> &amp;face = faces[faceID]; // return "face", an array of 3,4,5+ index.
glDrawElements(GL_POLYGON, face.size(), GL_INT, (GLint*)0+idOffset);
idOffset += face.size();

}

glEndList();

But this doesn't work too...

So (second question), my solution is impossible using this way right?

If any of you have suggestions, this could really help me.

Thanks in advance! :)

Regards,

Dorian

aqnuep
11-23-2011, 01:44 AM
Using VBOs and display lists together is not a good idea.

Unfortunately, display lists work by fetching the buffer data and storing it into the display list thus you actually duplicate the data and in fact when rendering the display list the VBO eventually won't be used.

In general, I would not suggest anything like this, simply do your glDrawElements calls without display lists in case you want to use VBO.

V-man
11-23-2011, 01:59 AM
And what does glGetError() say?

>>glDrawElements(GL_POLYGON, face.size(), GL_INT, (GLint*)0+idOffset)

GL_INT is invalid.
I also suggest to never use that ugly GL_POLYGON. Use GL_TRIANGLE_FAN instead.

http://www.opengl.org/wiki/FAQ#glGetError_.28or_.22How_do_I_check_for_GL_erro rs.3F.29
http://www.opengl.org/wiki/GL_Error_Codes

Narann
11-23-2011, 03:07 AM
@aqnuep
Ok, that was I was thinking... Display list is a whole packaged data so it need all data available during the display list definition, it's not just a "gl call list".



simply do your glDrawElements calls without display lists

That is what I've done actually. :)

There is what I've done:

Store every indices in a VBO: {"1,2,3,4," "2,5,6," "5,7,8,6," etc...}
(quotes are here to say how indices will be used. Sometime 3, sometime 4, sometime 5, etc... depending of the face).

And a loop:

int idOffset = 0;
int facesCount = (int)faces.size();
for(int faceID = 0; faceID < facesCount; ++faceID){
const std::vector<int> &amp;face = faces[faceID];
glDrawElements(GL_POLYGON, face.size(), GL_UNSIGNED_INT, (GLuint*)NULL+idOffset);
idOffset += face.size();
}

This work perfectly. It's just you have one call by face, sending a number and a pointer offset by call...

@V-man

Yes! I will put GL_UNSIGNED_INT and GL_TRIANGLE_FAN, thanks for the tip! :)

Thanks a lot guys!