• Advertisement
Sign in to follow this  

Vertex array and vertex buffer question

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am developing a 3d application to navigate throught a 3d world. I was using direct mode to draw each triangle of the scene but I heard that this is the slowest mode because there are many CPU calls for each triangle. I decide to develope an algorithm to group single triangles in triangle fans and use vertex arrays to made less CPU calls and improve performance. Once I made the previous, I proceed to measure the draw process and I obtain the next results Diret mode before triangle fan grouping: 14632022 CPU cycles per frame Direct mode after triangle fan grouping: 8867726 CPU cycles per frame Vertex array mode using triangle fans : 12697546 CPU cycles per frame Vertex buffer mode using triangle fans : 17295508 CPU cycles per frame Its extrange but I the results using direct mode before triangle fan grouping and using vertex arrays are similars. More extrange is the results obtined using Vertex buffer because is greather than direct modo before triangle fan grouping. Some one know the reason to this contradiction ? I am using MinGW to compile with codeblocks ide and SDL to start the drawing surface. I have an ATI Radeon X600 whit 128MB, Intel pentium4 ht 3GHz, windows xp sp2.

Share this post


Link to post
Share on other sites
Advertisement
Ok, there are some considerations:

- I am using octrees so I am displaying the faces inside each octant.
- Time meassurement done with a couple of assembler lines using Read Time Stamp Counter ( RDTSC ).
- Time meassurement done after drawing all octant faces but before swaping opengl display buffer.


--------------------------------------------------------------------------------


Version 1.- Using direct mode befor triangle fan grouping.


// For each octant face
for( int nface = 0 ; nface < octant->numberOfFaces ; nface++ )
{
FaceStruct *face = &octant->faces_array[nface]; // Obtaining current face

// For each face vertex
for( int nvert = 0 ; nvert < 3 ; nvert++ )
{
glBegin( GL_TRIANGLES );
glTexCoord2f( face->textCoords[nvert][0], face->textCoord[nvert][1] );
glNormal3f(face->normals[nvert][0], face->normals[nvert][1], face->normals[nvert][2] );
glVertex3f( face->vertex[nvert][0], face->vertex[nvert][1], face->vertices[nvert][2] );
glEnd();
}
}


--------------------------------------------------------------------------------


Version 2.- Using direct mode after triangle fan grouping.


// For each octant triangle fan
for( int ntfan = 0 ; ntfan < octant->numberOfTriangleFans ; ntfan++ )
{
TFanStruct *tfan = &octant->triangleFan_array[ntfan]; // Obtaining current triangle fan

glBegin( GL_TRIANGLE_FAN );

// For each triangle fan vertex
for( int nvert = 0 ; nvert < tfan->numberOfVertices ; nvert++ )
{
glTexCoord2f( tfan->textCoordsArray[nvert][0], tfan->textCoordsArray[nvert][1] );
glNormal3f( tfan->normalsArray[nvert][0], tfan->normalsArray[nvert][1], tfan->normalsArray[nvert][2] );
glVertex3f( tfan->verticesArray[nvert][0], tfan->verticesArray[nvert][1], tfan->verticesArray[nvert][2] );
}

glEnd();
}


--------------------------------------------------------------------------------


Version 3.- Using Vertex arrays after triangle fan grouping.


glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glEnableClientState( GL_NORMAL_ARRAY );
glEnableClientState( GL_VERTEX_ARRAY );


...


// For each octant triangle fan
for( int ntfan = 0 ; ntfan < octant->numberOfTriangleFans ; ntfan++ )
{
TFanStruct *tfan = &octant->triangleFan_array[ntfan]; // Obtaining current triangle fan

glTexCoordPointer( 2, GL_FLOAT, 0, tfan->textCoordsArray );
glNormalPointer( GL_FLOAT, 0, tfan->normalsArray );
glVertexPointer( 3, GL_FLOAT, 0, tfan->verticesArray );

glDrawArrays( GL_TRIANGLE_FAN, 0, tfan->numberOfVertices );

}


--------------------------------------------------------------------------------


Version 4.- Using Vertex buffer after triangle fan grouping.


...


// Code to build each triangle fan buffer


for( int ntfan = 0 ; ntfan < octant->numberOfTriangleFans ; ntfan++ )
{

TFanStruct *tfan = &octant->triangleFan_array[ntfan]; // Obtaining current triangle fan

// Current triangle fan textures buffer
glGenBuffersARB(1, &tfan->textBufferID );
glBindBufferARB(GL_ARRAY_BUFFER_ARB, tfan->textBufferID );
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(M3DFVector2) * tfan->numberOfVertices, tfan->textCoordsArray, GL_STATIC_DRAW_ARB);

// Current triangle normals buffer
glGenBuffersARB(1, &tfan->normalsBufferID );
glBindBufferARB(GL_ARRAY_BUFFER_ARB, tfan->normalsBufferID );
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(M3DFVector3) * tfan->numberOfVertices, tfan->normalsArray, GL_STATIC_DRAW_ARB);

// Current triangle vertices buffer
glGenBuffersARB(1, &tfan->verticesBufferID );
glBindBufferARB(GL_ARRAY_BUFFER_ARB, tfan->verticesBufferID );
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(M3DFVector3) * tfan->numberOfVertices, tfan->verticesArray, GL_STATIC_DRAW_ARB);

}


...


// Code to display each triangle fan buffer


// For each octant triangle fan
for( int ntfan = 0 ; ntfan < octant->numberOfTriangleFans ; ntfan++ )
{

TFanStruct *tfan = &octant->triangleFan_array[ntfan]; // Obtaining current triangle fan


glBindBufferARB( GL_ARRAY_BUFFER_ARB, tfan->textBufferID );
glTexCoordPointer( 2, GL_FLOAT, 0, (char *) NULL );

glBindBufferARB( GL_ARRAY_BUFFER_ARB, tfan->normalsBufferID );
glNormalPointer( GL_FLOAT, 0, (char *) NULL );

glBindBufferARB( GL_ARRAY_BUFFER_ARB, tfan->verticesBufferID );
glVertexPointer( 3, GL_FLOAT, 0, (char *) NULL );

glDrawArrays( GL_TRIANGLE_FAN, 0, tfan->numberofvertices );

}

Share this post


Link to post
Share on other sites
Reduce your calls to glBindBuffer, glTexCoordPointer, glNormalPointer, glVertexPointer as much as possible. Perhaps 10 calls to render all of your scene with your millions of triangles. A couple of large VBOs is enough, each 2 or 4 MB

Share this post


Link to post
Share on other sites
There are a number of improvements you can make, I'll just list them here to give you something to search for:

1. Indexed mode. This allows the GPU to potentially cache transformed vertices, thereby speeding it up.
2. Use plain indexed triangles, or triangle strips, not triangle fans. Triangle strips can get longer than fans (normally), but normal triangles are fast enough nowadays. Don't need to convert to fan or strip, just make sure they are indexed.
3. Make sure you draw large amounts of triangles in one go. We're talking about 100s of triangles per draw at least. I assume your octree is going down to a much lower level, which isn't necessary.

Share this post


Link to post
Share on other sites
I reduced the calls ( 1 call per octant ) and I reemplace triangle fans to plain triangles. I obtained a %500 speed bost.
Tank you very much guys!.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement