# Once & Again: glDrawElements

Hey,

I have couple questions regarding glDrawElements… I’ve got it succesfully working, but it’s slower than glDrawArrays AND also slower than immediate mode. This shouldn’t be the case, should it?
And what does glDrawElements’ 2nd parameter ‘count’ actually mean? The number n of faces to be drawn or the number of vertex indices used in drawing n number of faces?

To clear my last question a bit:

glDrawElements(GL_TRIANGLES, numFaces*3, GL_UNSIGNED_SHORT, faces);

works just fine, but:

glDrawElements(GL_TRIANGLES, numFaces, GL_UNSIGNED_SHORT, faces);

doesn’t. It only draws a partial 3d-object to the screen.

-teemu

The 2’nd parameter means sizeof(indices)/sizeof(indices[0])
or sizeof (faces)/sizeof(faces[0]) in your notation.

also as michail used ‘indices’ is the correct term which is very differnt to face
eg to draw 2 faces/triangles
using GL_TRIANGLES u need 6 indices
but using GL_TRIANGLE_STRIP u need 4 indices.
2 triangles but one uses 6 indices and the other only 4

Ok, that clears things up a bit…

So if i have n faces which are constructed of 3 vertices, that means I then have n*3 indices, right?

But glDrawElements is still much slower than immediate mode… and I can’t figure out why…

-teemu

[This message has been edited by mu-337 (edited 06-01-2001).]

sizeof(indices)/sizeof(indices[0]) is not a very good explanation, sorry. Sounds like static array. The ‘count’ means number of indices.

[b]
So if i have n faces which are constructed of 3 vertices, that means I then have n*3 indices, right?

[/b]
That is true only for independent triangles.

[b]
But glDrawElements is still much slower than immediate mode… and I can’t figure out why…

[/b]
Can you give more details ? (card\driver\arrays format)
Probably you are trying to use a not accelerated data formats.

[This message has been edited by Michail Bespalov (edited 06-01-2001).]

Ok, i think i get it now what that count parameter means…

Here’s some details:

card: Riva TNT2
drivers: detonator3, display driver version 5.12.01.0650
data formats:
struct vertexdata {
float x,y,z;
};

struct texcoordata {
float u,v;
};

struct facedata {
unsigned short int a,b,c;
};

vertexdata *verts;
texcoordata *texVerts;
vertexdata *normVerts;
facedata *faces;
facedata *texFaces;
vertexdata *normFaces;

and here’s how i do the drawing:

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, verts);
glTexCoordPointer(2, GL_FLOAT, 0, texVerts);
glDrawElements(GL_TRIANGLES, numFaces*3, GL_UNSIGNED_SHORT, faces);

I’ve also tried glDrawArrays and that works just fine and it’s faster than immediate mode.
And what are those ‘not accelerated data formats’?

-teemu

You are doing a call to glDrawElements that exactly mirrors calling glDrawArrays. Unless you are using Vertex_Array_Range (or perhaps CVA’s), you aren’t going to get better performance out of glDrawElements.

I would suggest downloading nVidia’s stripper. Except for a few cases where it gives odd results with quads, it works very well. Use it to transform your face data into strips and draw them that way with glDrawElements. It will likely be faster than glDrawArrays.

You will also need to compress your vertex data. Remove redundant array entries (where a unique vertex is the same as another) and adjust the face array to compensate, before you use the stripper.

Originally posted by Korval:
You will also need to compress your vertex data. Remove redundant array entries (where a unique vertex is the same as another) and adjust the face array to compensate, before you use the stripper.

I already have an initialization code where i get rid off those duplicate vertices…
Well, i guess i gotta test those CVA’s if they make a difference.

-teemu

> You are doing a call to glDrawElements
> that exactly mirrors calling glDrawArrays.
> Unless you are using Vertex_Array_Range
> (or perhaps CVA’s), you aren’t going to
> get better performance out of
> glDrawElements.

You don’t know that – that depends on his definition of “face”. If there is vertex re-use among the faces (i e more than one face uses the same vertex index) then he’s using DrawElements correctly.

I’ve found that on TNT2, putting an unused float after the x,y,z (so the stride is 16) and aligning the vertex array on a 32-byte boundary leads to a noticeable speed-up. Perhaps this is just a lucky cache interaction, or perhaps they have a fast path (say, using MOVAPS instead of MOVUPS in places, or something).