Search code examples
openglvbovertexvertex-buffer

glMultiDrawElements: Values to pass to "indices" parameter (GLvoid**)


I had to convert some code (which deals with building a VBO of data for the outlines of 2D shapes, i.e. they are not just triangle meshes, they can be an arbitrary length polygon outline) from using primitive restart to using glMultiDrawElements. I now realize glMultiDrawArrays is actually more appropriate for my application but that is not relevant to the question (indeed I would not have encountered this curious problem if I had been smarter and ported it to use glMultiDrawArrays instead).

I assembled two vectors to store the data for storing the requisite values:

struct E_MDEGBuffer {
    std::vector<GLvoid*> indices;
    std::vector<GLsizei> lengths;
};

Then what I did was for each polygon with N vertices push a single value to both indices and lengths, in indices I inserted (char*)NULL+index where index is the index in the IBO which corresponds to the first vertex of the polygon, and in lengths I place the integer number of vertices in that polygon.

The E_MDEGBuffer struct is used to pass values to glMultiDrawElements like so:

glMultiDrawElements(GL_TRIANGLE_FAN, mde.lengths.data(), GL_UNSIGNED_INT, (const GLvoid**)mde.indices.data(), mde.indices.size()); 

I test my program and the render is completely screwed up.

Eventually I fiddle around a bit with some hard-coded values passed into glMultiDrawElements and I discover that my indices values were off by a factor of 4.

Consider as an example the first polygon has 3 vertices and the second polygon has 5 vertices.

To get correct results my indices vector contains [0,0xc] and lengths contains [3,5].

Why should indices not be [0,0x3]?


Solution

  • The offset provided to the OpenGL buffer functions (such as glVertexAttribPointer) is always a data size offset, rather than an index.

    The number passed in must be of GLvoid* (or in this case GLvoid**) type but having the value that is the byte offset. It helps to think about how it could ever possibly be justified to have that pointer type for this parameter, and it being a byte-offset value goes (a short way) toward that.

    I don't know what it was at first that made me think it was just the index offset but that is wrong and I paid the price.