Discussion:
glMultiDrawElements
(too old to reply)
scott
2007-08-03 16:12:58 UTC
Permalink
The example code below draws a cube. It uses buffered vertex and index
data.

glBindBuffer(GL_ARRAY_BUFFER, buffers[BUFFER_Cube]);
glVertexPointer(3,GL_FLOAT,0,(GLvoid*)((char*)NULL));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[BUFFER_Cube2Indices]);
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, 0);

It works fine, but I would like to know how to use
glMultiDrawElements, as I understand it is much faster than
glDrawElements (?)

However, the following crashes when it gets to the draw call:

GLsizei indices_per_quad[] = {4,4,4,4,4,4};
glBindBuffer(GL_ARRAY_BUFFER, buffers[BUFFER_Cube]);
glVertexPointer(3,GL_FLOAT,0,(GLvoid*)((char*)NULL));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[BUFFER_Cube2Indices]);
glMultiDrawElements(GL_QUADS, indices_per_quad, GL_UNSIGNED_BYTE, 0,
6);

I know my vertex and index data is buffered correctly, as the
glDrawElements versions works, and just before glMultiDrawElements is
called, glGetError returns no error.

What am I doing wrong?

Thanks in advance!

-scott
Marcel Heinz
2007-08-03 19:25:55 UTC
Permalink
Hi,
Post by scott
The example code below draws a cube. It uses buffered vertex and index
data.
glBindBuffer(GL_ARRAY_BUFFER, buffers[BUFFER_Cube]);
glVertexPointer(3,GL_FLOAT,0,(GLvoid*)((char*)NULL));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[BUFFER_Cube2Indices]);
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, 0);
It works fine, but I would like to know how to use
glMultiDrawElements, as I understand it is much faster than
glDrawElements (?)
No, not in this case. MultiDrawElements is for cases where it is
impossible to draw an object with a single DrawElements call, for
example if it consists of a number of separate triangle strips.
Post by scott
GLsizei indices_per_quad[] = {4,4,4,4,4,4};
glBindBuffer(GL_ARRAY_BUFFER, buffers[BUFFER_Cube]);
glVertexPointer(3,GL_FLOAT,0,(GLvoid*)((char*)NULL));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[BUFFER_Cube2Indices]);
glMultiDrawElements(GL_QUADS, indices_per_quad, GL_UNSIGNED_BYTE, 0,
6);
You have to provide two arrays in client memory, one for the counts
(your indices_per_quad) and one containing the pointers to the elements.
Specifying a NULL pointer for the latter is surely causing your crash.

Calling MultiDrawElements(mode, sizes, type, indices, num) is equivalent
to the code:

for (i=0; i<num; i++)
glDrawElements(mode, sizes[i], type, indices[i]);

Regards, Marcel
--
Marcel Heinz | <***@s2001.tu-chemnitz.de> | PGP-KeyID: E78E9442

"Perfection is attained not when there is nothing more to add,
but when there is nothing more to remove." -- Antoine de Saint-Exupéry
scott
2007-08-05 12:29:12 UTC
Permalink
Post by Marcel Heinz
You have to provide two arrays in client memory, one for the counts
(your indices_per_quad) and one containing the pointers to the elements.
Specifying a NULL pointer for the latter is surely causing your crash.
In the book, "OpenGL Distilled", it says if a buffer object is
currently bound to GL_ELEMENT_ARRAY_BUFFER, GL interprets the indices
pointer as an offset into that buffer instead of a pointer to indices
in client memory.

This is why I provide 0. I know the index buffer is valid, as the
glDrawElements approach works...so how do I make glMultiDrawElements
use a bound index buffer instead of me having to provide a pointer to
the indices in client memory? I assume providing 0 should correctly
tell it to use an offset of 0 into the currently bound element_array
buffer?

I know I can just use glDrawElements instead, but I would like to know
what I'm doing wrong with glMutliDraw. =)

-scott
Dave Eberly
2007-08-05 15:55:35 UTC
Permalink
Post by scott
Post by Marcel Heinz
You have to provide two arrays in client memory, one for the counts
(your indices_per_quad) and one containing the pointers to the elements.
Specifying a NULL pointer for the latter is surely causing your crash.
In the book, "OpenGL Distilled", it says if a buffer object is
currently bound to GL_ELEMENT_ARRAY_BUFFER, GL interprets the indices
pointer as an offset into that buffer instead of a pointer to indices
in client memory.
This is why I provide 0. I know the index buffer is valid, as the
glDrawElements approach works...
The signature for the function is
void glMultiDrawElements(GLenum mode, GLsizei *count, GLenum type, const
GLvoid **indices, GLsizei primcount);
You are passing 0 for "indices". This is the problem the responder was
trying to point out. What you need to pass is an array of pointers,
and those pointers are set to the offsets into the buffer object. For
example,

GLsizei primcount = 2;
const GLvoid* indices[2] = { 0, 16 }; // 0 is the start of first primitive,
16 is start of second primitive
<set up>
glMultiDrawElements(mode, count, indices, primcount);

--
Dave Eberly
http://www.geometrictools.com
scott
2007-08-08 10:48:57 UTC
Permalink
Post by Dave Eberly
Post by scott
Post by Marcel Heinz
You have to provide two arrays in client memory, one for the counts
(your indices_per_quad) and one containing the pointers to the elements.
Specifying a NULL pointer for the latter is surely causing your crash.
In the book, "OpenGL Distilled", it says if a buffer object is
currently bound to GL_ELEMENT_ARRAY_BUFFER, GL interprets the indices
pointer as an offset into that buffer instead of a pointer to indices
in client memory.
This is why I provide 0. I know the index buffer is valid, as the
glDrawElements approach works...
The signature for the function is
void glMultiDrawElements(GLenum mode, GLsizei *count, GLenum type, const
GLvoid **indices, GLsizei primcount);
You are passing 0 for "indices". This is the problem the responder was
trying to point out. What you need to pass is an array of pointers,
and those pointers are set to the offsets into the buffer object. For
example,
GLsizei primcount = 2;
const GLvoid* indices[2] = { 0, 16 }; // 0 is the start of first primitive,
16 is start of second primitive
<set up>
glMultiDrawElements(mode, count, indices, primcount);
--
Dave Eberlyhttp://www.geometrictools.com
So it is not possible to use buffered indices (GL_ELEMENT_ARRAY) with
glMultiDrawElements?
scott
2007-08-08 10:50:17 UTC
Permalink
Post by scott
Post by Dave Eberly
Post by scott
Post by Marcel Heinz
You have to provide two arrays in client memory, one for the counts
(your indices_per_quad) and one containing the pointers to the elements.
Specifying a NULL pointer for the latter is surely causing your crash.
In the book, "OpenGL Distilled", it says if a buffer object is
currently bound to GL_ELEMENT_ARRAY_BUFFER, GL interprets the indices
pointer as an offset into that buffer instead of a pointer to indices
in client memory.
This is why I provide 0. I know the index buffer is valid, as the
glDrawElements approach works...
The signature for the function is
void glMultiDrawElements(GLenum mode, GLsizei *count, GLenum type, const
GLvoid **indices, GLsizei primcount);
You are passing 0 for "indices". This is the problem the responder was
trying to point out. What you need to pass is an array of pointers,
and those pointers are set to the offsets into the buffer object. For
example,
GLsizei primcount = 2;
const GLvoid* indices[2] = { 0, 16 }; // 0 is the start of first primitive,
16 is start of second primitive
<set up>
glMultiDrawElements(mode, count, indices, primcount);
--
Dave Eberlyhttp://www.geometrictools.com
So it is not possible to use buffered indices (GL_ELEMENT_ARRAY) with
glMultiDrawElements?
Apologies, I understand now. You do at least need to say where each
primitive's indices start in the bound buffer.

Thanks!

fungus
2007-08-03 22:26:41 UTC
Permalink
Post by scott
It works fine, but I would like to know how to use
glMultiDrawElements, as I understand it is much faster than
glDrawElements (?)
Not in my experience it isn't...


--
<\___/>
/ O O \
\_____/ FTB. Remove my socks for email address.
Loading...