glMultiDrawElements + VBO

I’m currently using glMultiDrawElements rendering arrays directly:


glPushMatrix();
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer(3, GL_FLOAT, 0, verts);
glMultiDrawElements(GL_LINE_STRIP, globalIndexCount, GL_UNSIGNED_INT,  (const void **) &globalIndices[0], globalIndices.size() );
glDisableClientState( GL_VERTEX_ARRAY );	
glPopMatrix();

To get better performances, I’d like to render the elements with VBO’s: I think buffer are properly initialized and bind, but I can’t figure out how the glMultiDrawElements call should look like.
The one posted below doesn’t work, anybody can help please?


// bind buffers
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, fullHairCounter*HAIRPOINTS*sizeof(vector3_t), verts, GL_STATIC_DRAW_ARB);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, iboId);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, globalIndices.size() *sizeof(unsigned int), (const void **) &globalIndices[0], GL_STATIC_DRAW_ARB);


// render buffers
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, iboId);
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer(3, GL_FLOAT, 0, verts);
glPushMatrix();
glMultiDrawElements(GL_LINE_STRIP, NULL, GL_UNSIGNED_INT,  (const void **) &globalIndices[0], NULL );
glPopMatrix();
glDisableClientState( GL_VERTEX_ARRAY );	
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);

Thanks for any help.

If you are going to put your vertices in a VBO, then the address you pass to glVertexPointer should not be a CPU address. It should be the start of the VBO address, which is 0 or whatever higher address in the VBO you want.

The same applies to indices. Addresses are 0 based.
Don’t pass CPU addresses.

For further info
http://www.opengl.org/wiki/Vertex_Buffer_Object

Hi V-man, thanks for the answer and sorry for the typo.
I wrote

glVertexPointer(3, GL_FLOAT, 0, verts);

because it was like that for the non-VBO version; obviously that is

glVertexPointer(3, GL_FLOAT, 0, 0);

.

I’ve read also the paper you sent me, but still can’t make the glMultiDrawElements to work. To note that I just want to use it so that I can draw all the items (GL_LINE_STRIP) at once, instead to loop glDrawRangeElements n times…

It’s just that glMultiDrawElements call that puzzles me: I thought the one I did was ok, instead doesn’t draw anything on screen. Clearly data is not passed as it expects…

IIRC you have to pass a CPU array for the counts and indexes parameters, only the addresses in the indexes array are VBO addresses/offsets.

If it’s not an index (e.g. a number of indexes or an offset of an index), it is not stored in the GL_ELEMENT_ARRAY_BUFFER !

Also you pass NULL (== 0) as primcount, which explains why your program didn’t crash although you passed a NULL for the counts parameter.

Well, maybe I could show more in detail what I’m doing. As I wrote earlier, it’s just the VBO implementation that doesn’t work: glMultiDrawElements in CPU mode work just fine.


// fill array with data

int *globalIndexCount;
std::vec <int> globalIndices;

	globalIndexCount=new int[fullHairCounter];
	for (int i=0; i<fullHairCounter; i++)
	{
		globalIndexCount[i]=HAIRPOINTS;
		globalIndices.push_back(indices+i*HAIRPOINTS);
	}

// update VBO's
	if (isVBOsupported==true)
	{
		glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);
		glBufferDataARB(GL_ARRAY_BUFFER_ARB, fullHairCounter*HAIRPOINTS*sizeof(vector3_t), verts, GL_STATIC_DRAW_ARB);		
		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, iboId);
	        glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, globalIndices.size() *sizeof(unsigned int), (const void **) &globalIndices[0], GL_STATIC_DRAW_ARB);
	}

// rendering without VBO's works fine, so data is properly initialized and set
		glPushMatrix();
		glEnableClientState( GL_VERTEX_ARRAY );
		glVertexPointer(3, GL_FLOAT, 0, verts);
		glMultiDrawElements(GL_LINE_STRIP, globalIndexCount, GL_UNSIGNED_INT,  (const void **) &globalIndices[0], globalIndices.size() );
		glDisableClientState( GL_VERTEX_ARRAY );	
		glPopMatrix();

// rendering with VBO's doesn't produce any output: it should be just a minimal change and yet it doesn't work
		glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);
		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, iboId);
		glEnableClientState( GL_VERTEX_ARRAY );
		glVertexPointer(3, GL_FLOAT, 0, 0);
		glPushMatrix();
		glMultiDrawElements(GL_LINE_STRIP, globalIndexCount, GL_UNSIGNED_INT, (const void **) &globalIndices[0], globalIndices.size() );
		glPopMatrix();
		glDisableClientState( GL_VERTEX_ARRAY );	
		glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);

You would have to check the contents of your globalIndices array.
Do they contain VBO address or is a CPU address?

Look at globalIndices[0]. It should probably be 0.