2

Is it possible to use a single buffer to store multiple types of data? Or should I use two buffers where one stores the Vertex Data and the other stores the Index Data?

Example (using a single buffer):

GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
// Buffer the Vertex Data
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
// Buffer the Index Data
1

2 Answers 2

6

Yes, it's fine and the basis for interleaved storage. Each buffer is just a section of memory that other commands can point to. You don't even need to bind it to GL_ELEMENT_ARRAY_BUFFER while setting the data.

You will have to ensure the data doesn't overlap:

GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
//allocate the buffer, passing in null just allocates
glBufferData(GL_ARRAY_BUFFER, vertexSize+indexSize*sizeof(int), 0, GL_STATIC_DRAW);
// Buffer the Index Data at the start of the buffer
glBufferSubData(GL_ARRAY_BUFFER, 0, indexSize*sizeof(int), indexData);
// Buffer the Vertex Data right after that
glBufferSubData(GL_ARRAY_BUFFER, indexSize*sizeof(int), vertexSize, vertexData);

you'll need to offset the glVertexAttribPointer pointer parameter to signal where it starts.

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(vertex), (void*)(indexSize*sizeof(int)));
glVertexAttribPointer(1, 3, GL_FLOAT, false, sizeof(vertex), (void*)(indexSize*sizeof(int) + 3*sizeof(float)));
//...

and when drawing you need to pass in the proper offset for drawing (0 if you put it first otherwise the offset you specified in the corresponding glBufferSubData call)

glDrawElements(GL_TRIANGLES​, indexSize, GL_UNSIGNED_INT​, 0);
Sign up to request clarification or add additional context in comments.

1 Comment

Works and I understand why. Thanks for a great answer and a good reason to put the index at the start.
1

It is legal to store vertex attributes and indices in the same buffer. The spec always had some language discouraging it, though.

Older GL specs, up to and including 3.0, had this paragraph:

Buffer objects created by binding an unused name to ARRAY BUFFER and to ELEMENT ARRAY BUFFER are formally equivalent, but the GL may make different choices about storage implementation based on the initial binding. In some cases performance will be optimized by storing indices and array data in separate buffer objects, and by creating those buffer objects with the corresponding binding points.

Starting with the 3.1 spec, only the last sentence of this paragraph is still present:

In some cases performance will be optimized by storing indices and array data in separate buffer objects, and by creating those buffer objects with the corresponding binding points.

I'm not sure if performance differences from ignoring this advice are common, but it's still there in the latest (4.5) spec.

1 Comment

and depends very much on implementation of the driver (which the spec says nothing about)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.