Is it possible to store different vertex attributes in different vertex buffers?
All the examples I've seen so far do something like this
float data[] =
{
//position
v1x, v1y, v1z,
v2x, v2y, v2z,
...
vnx, vny, vnz,
//color
c1r, c1g, c1b,
c2r, c2g, c2b,
...
cnr, cng, cnb,
};
GLuint buffname;
glGenBuffers(1, &buffname);
glBindBuffer(GL_ARRAY_BUFFER, buffname);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
And the drawing is done something like this:
glBindBuffer(GL_ARRAY_BUFFER, buffname);
glEnableVertexAttrib(position_location);
glEnableVertexAttrib(color_location);
glVertexAttribPointer(position_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(color_location, 3, GL_FLOAT, GL_FALSE, 0, (void*)(3*n));
glDrawArrays(GL_TRIANGLES, 0, n/3);
glDisableVertexAttrib(position_location);
glDisableVertexAttrib(color_location);
glBindBuffer(GL_ARRAY_BUFFER, 0);
Isn't it possible to store position data and color data in different VBOs? The problem is I don't understand how this would work out because you can't bind two buffers at once, can you?
If there is a simple but inefficient solution, I would prefer it over a more complicated but efficient solution because I am in primary learning state and I don't want to complicate things too much.
Also, if what I'm asking is possible, is it a good idea or not?
To clarify: I do understand how I could store different attributes in different VBO's. I don't understand how I would later draw them.
The association between attribute location X and the buffer object that provides that attribute is made with the glVertexAttribPointer
command. The way it works is simple, but unintuitive.
At the time glVertexAttribPointer
is called (that's the part a lot of people don't get), whatever buffer object is currently bound to GL_ARRAY_BUFFER
becomes associated with the attribute X, where X is the first parameter of glVertexAttribPointer
.
So if you want to have an attribute that comes from one buffer and an attribute that comes from another, you do this:
glEnableVertexAttrib(position_location);
glEnableVertexAttrib(color_location);
glBindBuffer(GL_ARRAY_BUFFER, buffPosition);
glVertexAttribPointer(position_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, buffColor);
glVertexAttribPointer(color_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
As for whether you should split attributes into different buffers... I would say that you should only do it if you have a demonstrable need.
For example, let's say you're doing a dynamic height-map, perhaps for some kind of water effect. The Z position of each element changes, but this also means that the normals change. However, the XY positions and the texture coordinates do not change.
Efficient streaming often requires either double-buffering buffer objects or invalidating them (reallocating them with a glBufferData(NULL) or glMapBufferRange(GL_INVALIDATE_BIT)). Either way only works if the streamed data is in another buffer object from the non-streamed data.
Another example of a demonstrable need is if memory is a concern and several objects share certain attribute lists. Perhaps objects have different position and normal arrays but the same color and texture coordinate arrays. Or something like that.
But otherwise, it's best to just put everything for an object into one buffer. Even if you don't interleave the arrays.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With