My game is played on a fixed-size hex based arena, where each hex can be of a different type, and possibly contain some creatures/items/anything on it.

When I started out, I got the advice to have a VBO per entity, which I took quite literally and ended up creating a VBO per-hex per-frame, which got real slow. This lead me to restructure the data in a way that I pre-calculate all of the VBO data for the "background" hex grid just once, and just repeatedly draw it.

The problem is that now I can't simply rely on changing the model and having everything be updated, as the whole "map" is pre-calculated. Following this I created a separate VBO which is filled just with "dynamic" objects that change on each frame, and first render the static background, and then the dynamic part that changes.

But this leads me to a question. What if I need to change the background at runtime? For example, what if a "wall" gets torn down every once in a while, and I need to update the world data? Currently I can think of only a few options:

  • Change the VBO in place during the frame. This would only work if the change is small enough to not lag the frame.
  • Keep a separate VBO that just has the "changes" and is drawn over the original one. I don't really like this approach, as it doesn't really feel flexible.
  • Build a new VBO in a separate thread and atomically swap them once done. While this would allow me to do a larger update without sacrificing framerate, it could also introduce a weird kind of latency, when the user would still see the old thing for a few frames until the new VBO is calculated.

Ideally I'd just change my "model" and re-build the whole VBO from it, but that's about as slow as it gets, so I'm not really sure if I should even keep thinking this way?

How do larger and more complicated games handle updating geometry on the fly? Is everything just pre-calculated animations that simply get swapped around?

  • \$\begingroup\$ We are discussing the introduction, rather than simple position updates, of game entities, right? Instancing and vertex shader uniforms can be used to efficiently deal with simple updates. \$\endgroup\$ Commented Apr 10, 2016 at 2:26
  • \$\begingroup\$ 2D or 3D? If it's 2D, you can have a single VBO for all vertices and update it each frame. I've tried it and it worked with thousands of sprites without lags. \$\endgroup\$ Commented Jul 17, 2016 at 11:35
  • \$\begingroup\$ Changing VBOs is not slow. Just use glBufferSubData to update the tiles that changed. \$\endgroup\$ Commented Feb 1, 2018 at 2:16

1 Answer 1


Your bullet list reads increasingly more efficient as you go. This should probably be taken as a hint on how to realistically get this done.

The last thing you really want to be doing is modifying vertex data in the middle of a frame, you will stall the render pipeline if you do not have enough unfinished frames queued up by the driver already. Having all those unfinished frames means input latency, so that is convenient but not ideal either. It is great at hiding poorly designed streaming, but that is all it does, hides bad design.

You want a system that can handle updates without interrupting whatever the GPU is presently working on, and your later proposed designs are getting better and better at accomplishing that. You should probably be aware no matter what you do that this "weird" latency is unavoidable, the actual amount of time between staging a frame and it showing up on screen is pretty variable, depending largely on how often you introduce stalls or render exceptionally long or late frames.

One to two frames between the time an entity is introduced CPU-side and shows up GPU-side probably will not kill anything if your target framerate is reasonably high. Modern GL has ways of determining once a command has completed GPU-side called fence sync objects, if you really want to be accurate with all of this -- you can avoid using those new entities on CPU-side stuff until the first frame they go live GPU-side without any major effort.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .