1
\$\begingroup\$

I need to replace client side vertex arrays in order to upgrade to a new version of OpenGL but I'm not sure what the best way to buffer data is now.

What I have is a 2D sprite engine which is using batching to push as many vertices to the GPU (using fixed pipeline functions glVertexPointer etc...) but frequently the batch is only a single quad. Because of how sorting works the buffer needs to be updated every frame (or more).

I need to use glBufferData/glVertexAttribPointer now so what is the best way to handle this case? I can allocate the buffer for glBufferData large enough to hold the maximum size of a batch (which is more than maybe 5000 vertices) so should I just push the old vertex array to glBufferData every frame or use another method? Maybe calling glVertexPointer/glBufferData has the same costs associated with them to copy memory to the GPU so I don't need to worry about it but I'd like to know since I'm still pretty new to OpenGL.

CONCLUSION:

In my simple tests I found calling glBufferData every frame with all vertices (OpenGL 4.1) actually slightly faster than client side vertex arrays (OpenGL 2.1).

Thanks.

\$\endgroup\$
1
\$\begingroup\$

Basically, you're sending between 4 and 5000 vertices in an array. The time to upload will likely be the same between glBufferData() and other methods. The docs for glBufferData() lay it out pretty nicely. You can specify how the vertex data is going to be handled once it's uploaded:

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.

You don't say how you're drawing things, but I would assume that there's some coherence from one frame to the next. You probably aren't drawing completely different sprites on each frame. So you can take advantage of that by not uploading the same geometry every frame. Only upload the new stuff, or change what has changed. You can use glBufferSubData() for that.

\$\endgroup\$
  • \$\begingroup\$ Why do you say glBufferData is the same as other methods? It's a sprite batcher and the sprites are sorted so I do basically send the entire the array each frame (then draw with glDrawArrays). In the cases I only send a single quad I guess I could keep the buffer and just bind a new texture/shader but I'm probably over optimizing at this point considering there's never more than 10,000 verts in a worse case scenario. \$\endgroup\$ – GenericPtr Nov 15 '17 at 7:15
  • \$\begingroup\$ I thought of a better way to phrase this: What is glVertexPointer analogous to outside of the fixed pipeline (i.e what does it do internally)? I'm sure it could be expanded to a series of other gl* functions but I'm not sure which ones. \$\endgroup\$ – GenericPtr Nov 15 '17 at 7:32
  • \$\begingroup\$ In my simple tests I found calling glBufferData every frame with all vertices (OpenGL 4.1) actually slightly faster than client side vertex arrays (OpenGL 2.1). I guess at least on Mac for my purposes this is the simplest and best solution. Thanks. \$\endgroup\$ – GenericPtr Nov 15 '17 at 13:50
  • \$\begingroup\$ Since this is a 2D sprite engine, you likely have an orthographic projection matrix. Why don't you use the Z-component and a depth buffer and skip sorting the sprites? The depth buffer will cause the sorting to happen automatically. \$\endgroup\$ – user1118321 Nov 16 '17 at 2:21
  • \$\begingroup\$ It's isometric and the depth buffer doesn't help for reasons I can't go into in a comment. :) Thanks. \$\endgroup\$ – GenericPtr Nov 16 '17 at 6:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.