# Fun with glDraw*Elements

This topic is 4861 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm researching vertex arrays and I'm almost ready to pounce. I've done my prep work and now I have a few questions before I start putting some code down. First, the only difference between glDrawRangeElements and glDrawElements is the specified range of indices, right? I'll only have one giant array with something like 800,000 values in it, would it still be worth while to use glDrawRangeElements? Second, am I still going to use the gl*Pointer functions if I'm going to be using glDraw*Elements? I'm only storying normal and vertex data, so if I do should I assemble them both into a big interleved array and then pass the stride and such to glVertex/NormalPointer and then call gl*Elements using the pointer returned from that? Also, I'm thinking about using the glInterleavedArrays function. The only problem is the normal data I have is per plane constructed of three vertices, not per vertex. Is there a way around this, such that I can specify a normal for the triangle and then the three vertices of the triangle, then the next normal and so on? The data is arranged as 3 floats for the normal and 9 floats for the vertex data. Do I specify that I want it to read in the 3 values for the normal, give a stride of 9 so it knows that's where the next one starts, and then have it read in the 9 values for the triangle vertex position? I'm a little confused on that part. Also, the pointer to the array that all the gl*Pointer functions and glInterLeavedArray take, can that just be a dynamically allocated array of type GLfloat of my own creation? It doesn't have to be static, right? I've got all my data stored in a giant dynamic array of floats, it would be real simple to switch those over to GLfloats and pass the pointer to that to the functions. Doable? And finally, would it be worth while to put my vertex arrays in a display list? Thanks in advance!

##### Share on other sites
Quote:
 Original post by CyberSlag5kFirst, the only difference between glDrawRangeElements and glDrawElements is the specified range of indices, right? I'll only have one giant array with something like 800,000 values in it, would it still be worth while to use glDrawRangeElements?

Haven't used glDrawRangeElements but if you are looking for speed look at VBO's.
The whole purpose of these calls is to work with giant arrays.

Quote:
 Original post by CyberSlag5kSecond, am I still going to use the gl*Pointer functions if I'm going to be using glDraw*Elements? I'm only storying normal and vertex data, so if I do should I assemble them both into a big interleved array and then pass the stride and such to glVertex/NormalPointer and then call gl*Elements using the pointer returned from that?

Yes you will still use gl*Pointer functions to specify the stride and pointer info. Better to have them in a structure in such a way that that structure can be passed into an glInterleaved* function in my opinion.

Quote:
 Original post by CyberSlag5kAlso, I'm thinking about using the glInterleavedArrays function. The only problem is the normal data I have is per plane constructed of three vertices, not per vertex. Is there a way around this, such that I can specify a normal for the triangle and then the three vertices of the triangle, then the next normal and so on? The data is arranged as 3 floats for the normal and 9 floats for the vertex data. Do I specify that I want it to read in the 3 values for the normal, give a stride of 9 so it knows that's where the next one starts, and then have it read in the 9 values for the triangle vertex position? I'm a little confused on that part.

I dont think there is a way around it. You probably have to make a copy of the normals per face.

Quote:
 Original post by CyberSlag5kAlso, the pointer to the array that all the gl*Pointer functions and glInterLeavedArray take, can that just be a dynamically allocated array of type GLfloat of my own creation? It doesn't have to be static, right? I've got all my data stored in a giant dynamic array of floats, it would be real simple to switch those over to GLfloats and pass the pointer to that to the functions. Doable?

It can be of your own creation provided the info held in it is of the same type and one that is supported by the function. For example :-

struct{    float texCoord[2];    float color[4];    float normal[3];    float vertex[3];} vertices;vertices *vert;.....glInterleavedArrays(GL_T2F_C4F_N3F_V3F, 0, vert);

Quote:
 Original post by CyberSlag5kAnd finally, would it be worth while to put my vertex arrays in a display list?

Yes if you data remains static, no if your data changes over time. If any kind of animation or modification is involved on the data and it required a recompiling it into the display list then display lists are useless.

##### Share on other sites
Quote:
 Haven't used glDrawRangeElements but if you are looking for speed look at VBO's.The whole purpose of these calls is to work with giant arrays.

I've looked a bit into VBOs since you and someone else have suggested them and I'll definitely implement them. I'll do it right after I get the VA's working as I'd like to observe the speed increase and just to see how pure VA's are done.

Quote:
 Yes you will still use gl*Pointer functions to specify the stride and pointer info. Better to have them in a structure in such a way that that structure can be passed into an glInterleaved* function in my opinion.

Actually I do have them in a structure. Sadly, the structure also contains a 2 byte piece of garbage (which is unavoidable). Would I be able to use the stride to get past that?

Quote:
 I dont think there is a way around it. You probably have to make a copy of the normals per face.

My structure looks like this:

#pragma pack(1)struct _Facet{	GLfloat normal[3]; //surface normal data 	GLfloat vertex[9]; //vertex data	USHORT dummy;} *triangles;#pragma pack()

Again the dummy has to be there. Now, can I just make two calls:

glNormalPointer(3, GL_FLOAT, 0, *triangles);
glVertexPointer(3, GL_FLOAT, 3*sizeof(GLfloat), *triangles);

But that doesn't let me specify that 3 vertices should be read in, doesn't it. So do these things normally have normal data for each vertex rather than for the surface, as I do? Crap. I don't have vertex normal data, only surface normals...

##### Share on other sites
if you use vertex arrays u haveto have a 1to1 colleration between normals and vertices, theres no way around it.

##### Share on other sites
Quote:
 Original post by CyberSlag5kBut that doesn't let me specify that 3 vertices should be read in, doesn't it. So do these things normally have normal data for each vertex rather than for the surface, as I do? Crap. I don't have vertex normal data, only surface normals...

Yeah you need per-vertex normals to pass to OpenGL. If you want "flat" shading, just copy each of your face normals 3 times (1 per vertex). If you want "smooth" shading, you need to average each of the contributing (adjacent) face normals per-vertex.

Regarding the gl*Pointer calls, make sure that you pass the initial address as the address of the first element IN the structure. ie. if you're calling glNormalPointer, you'll want to pass something like "Vertices[0].Normal". Then for each of them pass a stride of "sizeof(VertexType)" where VertexType is your vertex structure.

##### Share on other sites
Quote:
 Original post by CyberSlag5kglNormalPointer(3, GL_FLOAT, 0, *triangles);glVertexPointer(3, GL_FLOAT, 3*sizeof(GLfloat), *triangles);
It'd be more like:

glNormalPointer(3, GL_FLOAT, sizeof(_Facet), triangles);
glVertexPointer(3, GL_FLOAT, sizeof(_Facet), &(triangles[0].vertex));

I'm not sure whether the pointer in the second line is correct, but the idea is that you need to pass a pointer to where the vertex data actually begins. The stride is the distance between consecutive attributes.

##### Share on other sites
Quote:
 Original post by CyberSlag5kActually I do have them in a structure. Sadly, the structure also contains a 2 byte piece of garbage (which is unavoidable). Would I be able to use the stride to get past that?

Yes. Just use sizeof(structure) in the stride, in that case it will just ignore the dummy. Follow Myopic Rhino's example.

Quote:
 Original post by CyberSlag5kMy structure looks like this:#pragma pack(1)struct _Facet{ GLfloat normal[3]; //surface normal data GLfloat vertex[9]; //vertex data USHORT dummy;} *triangles;Again the dummy has to be there. Now, can I just make two calls:glNormalPointer(3, GL_FLOAT, , *triangles);glVertexPointer(3, GL_FLOAT, 3*sizeof(GLfloat), *triangles);But that doesn't let me specify that 3 vertices should be read in, doesn't it. So do these things normally have normal data for each vertex rather than for the surface, as I do? Crap. I don't have vertex normal data, only surface normals...

You should be specifying 1 vertex at a time. Not 3 at a time. So your facet should be like the following.

struct _Facet
{
GLfloat normal[3]; //surface normal data
GLfloat vertex[3]; //vertex data - not vertex[9]
USHORT dummy;
} *triangles;

All you need to do is make copies of the normal data - each face has a normal data, copy that normal data into the 3 vertex normals for that face. You don't need to recalculate.

##### Share on other sites
Quote:
 First, the only difference between glDrawRangeElements and glDrawElements is the specified range of indices, right? I'll only have one giant array with something like 800,000 values in it, would it still be worth while to use glDrawRangeElements?

It's recommended to use glDrawRangeElements instead. There's very little bother involved in doing so, and it can yeild performance benefits on some hardware. It certanly won't slow things down.

##### Share on other sites
Quote:
Original post by Nemesis2k2
Quote:
 First, the only difference between glDrawRangeElements and glDrawElements is the specified range of indices, right? I'll only have one giant array with something like 800,000 values in it, would it still be worth while to use glDrawRangeElements?

It's recommended to use glDrawRangeElements instead. There's very little bother involved in doing so, and it can yeild performance benefits on some hardware. It certanly won't slow things down.

The upper range of indices is easily obtained just by checking the length of my dynamic array, which is all that I'd need to use glDrawRangeElements, correct?

##### Share on other sites
I am having problems getting glDrawElements to work with interleaved data. Here is the simple example I'm trying to get to work. The data is packed with two tex coords and three vert positions for each vertex. When I run this example I don't see anything.

static GLushort g_cubeIndicies[] ={    0, 1, 2, 3,    4, 5, 6, 7,    8, 9, 10, 11,    12, 13, 14, 15,    16, 17, 18, 19,    20, 21, 22, 23};float g_cubeVertices[] ={	0.0f,0.0f, -1.0f,-1.0f, 1.0f,	1.0f,0.0f,  1.0f,-1.0f, 1.0f,	1.0f,1.0f,  1.0f, 1.0f, 1.0f,	0.0f,1.0f, -1.0f, 1.0f, 1.0f,	1.0f,0.0f, -1.0f,-1.0f,-1.0f,	1.0f,1.0f, -1.0f, 1.0f,-1.0f,	0.0f,1.0f,  1.0f, 1.0f,-1.0f,	0.0f,0.0f,  1.0f,-1.0f,-1.0f,	0.0f,1.0f, -1.0f, 1.0f,-1.0f,	0.0f,0.0f, -1.0f, 1.0f, 1.0f,	1.0f,0.0f,  1.0f, 1.0f, 1.0f,	1.0f,1.0f,  1.0f, 1.0f,-1.0f,	1.0f,1.0f, -1.0f,-1.0f,-1.0f,	0.0f,1.0f,  1.0f,-1.0f,-1.0f,	0.0f,0.0f,  1.0f,-1.0f, 1.0f,	1.0f,0.0f, -1.0f,-1.0f, 1.0f,	1.0f,0.0f,  1.0f,-1.0f,-1.0f,	1.0f,1.0f,  1.0f, 1.0f,-1.0f,	0.0f,1.0f,  1.0f, 1.0f, 1.0f,	0.0f,0.0f,  1.0f,-1.0f, 1.0f,	0.0f,0.0f, -1.0f,-1.0f,-1.0f,	1.0f,0.0f, -1.0f,-1.0f, 1.0f,	1.0f,1.0f, -1.0f, 1.0f, 1.0f,	0.0f,1.0f, -1.0f, 1.0f,-1.0f};...glEnableClientState( GL_TEXTURE_COORD_ARRAY );glEnableClientState( GL_VERTEX_ARRAY );glBindTexture( GL_TEXTURE_2D, g_textureID );glTexCoordPointer(2, GL_FLOAT, 5*sizeof(float), &g_cubeVertices[0]);glVertexPointer(3, GL_FLOAT, 5*sizeof(float), &g_cubeVertices[2]);glDrawElements(GL_QUADS, 3, GL_UNSIGNED_SHORT, &g_cubeIndicies[0]);glDisableClientState( GL_TEXTURE_COORD_ARRAY );glDisableClientState( GL_VERTEX_ARRAY );

When I replace the glDrawElements call with the following glDrawArrays call, I can see the textured cube just fine.

glDrawArrays(GL_QUADS, 0, 24);

I would like to be able to use glDrawElements for speed and flexibility reasons.
Thank you,
Malachi

• 32
• 12
• 10
• 9
• 9
• ### Forum Statistics

• Total Topics
631349
• Total Posts
2999473
×