openglvbovertex-attributes

how to split values from coordinates in OpenGL vertex buffer objects


For drawing a heatmap in OpenGL we want to give each point x,y, and value.

We could just store a vbo with these values and split it into two vertexattrib pointers:

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void*)0);
glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void*)sizeof(float));

However, when updating the values this would require writing only to the value between the xy points that are not changing. Is there a way to specify a separate array for the values so that each vertexattrib pointer comes from a different source?

@genpfault is suggesting a solution like this:

glBind(vboPoints);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBind(vboVals);
glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, (void*)0);

If this is correct, is there a limit to the number of different vbos that can be used in this way?

Is this slower than using a single block of memory with all values interleaved?


Solution

  • Is there a way to specify a separate array for the values so that each vertexattrib pointer comes from a different source?

    Bind a different VBO before each glVertexAttribPointer() call. Don't forget to adjust the stride/offset appropriately.

    There's no limit to the number of VBOs used this way other than the vertex attribute limit (query via glGet*() with GL_MAX_VERTEX_ATTRIBS)

    The performance difference vs. interleaved data will be implementation-dependent: there's no way to query what (if any) caching a GL implementation is doing internally on buffer accesses. For all anyone knows it could re-interleave the data streams internally.

    Best you can really do is give the driver usage hints via the usage parameter to glBufferData():

    usage is a hint to the GL implementation as to how a buffer object's data store will be accessed. This enables the GL implementation to make more intelligent decisions that may significantly impact buffer object performance. It does not, however, constrain the actual usage of the data store.

    So for your example the vboPoints buffer could be GL_STATIC_DRAW while the vboVals might be better off as GL_DYNAMIC_DRAW.