VBO and DrawElements slow?

I have implemented VBO for a model of 12000 tris, one texture, single light scene. vertices, normals and texcoords are in a single buffer but not interleaved. indices are also in VBO.

I use glDrawElements to render and get similiar performance when I use ordinary vertex arrays. However, oddly enough, when rendered with glDrawArrays, I get almost double the fps than before… since indices are also in buffer, there is no way that I am sending data through the bus when VBO used. so my question is, is it normal?

I have a gf4 ti4200 with latest detonators.

Are you using a static VBO? Filling it a loading time and don’t touch it again?

Using streamed (filled every frame) VBO isn’t better than CVA for me. After all you always need to transfert data from client (CPU) side to server side (GPU), no magic inside.

nope, all is static.

Are you using floats for all your components (and unsigned-bytes for colors)? If not, that could be the source of your performance problem.


[This message has been edited by CatAtWork (edited 08-18-2003).]

unfortunately, again nope… floats for everything, no color… unsigned short for indices…

maybe some code might help you figure out…

init code: (Vertex3D and 2D are all floats)
int sz = pMesh->getVertexCount();
int nArrayObjectSize = (2* sizeof(Vertex3D) + sizeof(Vertex2D)) * pMesh->getVertexCount();
char *pData = new char[nArrayObjectSize];
memcpy(pData, pMesh->getVertices(), sizeof(Vertex3D)*sz);
memcpy(&pData[sizeof(Vertex3D)*sz], pMesh->getNormals(), sizeof(Vertex3D)sz);
sizeof(Vertex3D)*sz], pMesh->getTexCoords(), sizeof(Vertex2D)*sz);

int nParam_ArrayObjectSize = 0;

unsigned int id = 0;
glGenBuffersARB( 1, &id );

glBindBufferARB( GL_ARRAY_BUFFER_ARB, id );
glBufferDataARB( GL_ARRAY_BUFFER_ARB, nArrayObjectSize, pData, GL_STATIC_DRAW_ARB );

glGetBufferParameterivARB( GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &nParam_ArrayObjectSize );

if( nParam_ArrayObjectSize <= 0 )

nArrayObjectSize = sizeof(unsigned short) * pMesh->getIndexCount();
nParam_ArrayObjectSize = 0;

glGenBuffersARB( 1, &id );

glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, nArrayObjectSize, pMesh->getIndices(), GL_STATIC_DRAW_ARB );

glGetBufferParameterivARB( GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &nParam_ArrayObjectSize );

if( nParam_ArrayObjectSize <= 0 )


glBindBufferARB( GL_ARRAY_BUFFER_ARB, pMesh->getBufferID() );
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, pMesh->getIndexBufferID());

	long offset = sizeof(Vertex3D)*pMesh->getVertexCount();
	glVertexPointer( 3, GL_FLOAT, 0, BUFFER_OFFSET(0) );
	glNormalPointer( GL_FLOAT, 0, BUFFER_OFFSET(offset));
	glTexCoordPointer( 2, GL_FLOAT, 0, BUFFER_OFFSET(2*offset));

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

	glDrawElements( GL_TRIANGLES, pMesh->getIndexCount(), GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));
	//glDrawArrays( GL_TRIANGLES, 0, pMesh->getIndexCount()/3);

	glDisableClientState( GL_VERTEX_ARRAY );
	glDisableClientState( GL_NORMAL_ARRAY );
	glDisableClientState( GL_TEXTURE_COORD_ARRAY);


I think I’ve found the solution.

From the VBO spec:

Note that it is expected that implementations may have different memory type requirements for efficient storage of indices and vertices. For example, some systems may prefer indices in AGP memory and vertices in video memory, or vice versa; or, on systems where DMA of index data is not supported, index data must be stored in (cacheable) system memory for acceptable performance. As a result, applications are strongly urged to put their models’ vertex and index data in separate buffers, to assist drivers in choosing the most efficient locations.

Separate your index data from your vertex data.

that’s an interesting point. now, I took the indices to system memory… but, yet again there is still no change…

thanks for your answers anyway… at least now I am sure I do everything right…