1

I have a VBO that contains multiple 3d models stored one after another with the intention of drawing the models conditionally with multiple calls to functions like glDrawElements. Each model is meant to have a fixed position. Before each call to glDrawElements, I can pass the model's position as a uniform, however because there are a lot of models doing so is very costly.

I'd like to store each model position in the VBO memory once per model (not per vertex) and have access to it from every vertex in the shader while drawing that model.

My hope was to have a vertex attrib pointer with an offset that points to the model position and with a stride of 0 so that it doesn't increment the memory per vertex, but unfortunately a stride of 0 moves the pointer forward as if it's tightly packed.

Is there any way to accomplish what I want? Also, I'm curious why OpenGL doesn't allow a stride of 0. It would have been so convenient.

user3124047
  • 153
  • 11

1 Answers1

2

It is possible to set a stride to be 0. You just have to use the vertex attrib binding API. The stride set by glBindVertexBuffer can be 0 and it has the expected meaning (since there is no way to determine what a tightly packed stride ought to be from the available parameters).

However, if you're doing this for performance, this isn't particularly helpful. To switch to a different value in the VBO, you have to issue a glBindVertexBuffer call, which is going to be about as expensive as a glProgramUniform call. Indeed, according to NVIDIA's AZDO presentation, changing uniforms is cheaper than vertex buffer bindings.

If you want to beat the cost of uniform updates, then you're going to have to use something else. Your best bet here is to put your per-mesh "uniforms" into an SSBO (or UBO if you don't have that many models), then draw all of your meshes at once (so they have to come from the same vertex buffers with the same vertex formats) using a single glMultiDraw* command. And then you have to use the GL 4.6/ARB_shader_draw_parameters feature to access gl_DrawID from your shader to pick which "uniform" value to fetch out of the SSBO array.

This allows you to draw all of these objects with a single draw command.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982