4

I'm currently developing my first 3D game for a school project, the game world is completely inspired by minecraft (world completely made out of cubes). I'm currently seeking to improve the performance trying to implement vertex buffer objects but I'm stuck, I already have this methods implemented: Frustum culling, only drawing exposed faces and distance culling but I have the following doubts:

  1. I currently have about 2^24 cubes in my world, divided in 1024 chunks of 16*16*64 cubes, right now I'm doing immediate mode rendering, which works well with frustum culling, if I implement one VBO per chunk, do I have to update that VBO each time I move the camera (to update the frustum)? Is there a performance hit with this?

  2. Can I dynamically change the size of each VBO? Or do I have to make each one the biggest possible size (the chunk completely filled with objects)?.

  3. Would I have to keep each visited chunk in memory or could I efficiently remove that VBO and recreated it when needed.

Boris Month
  • 421
  • 6
  • 14
Isracg
  • 75
  • 3
  • Not that this is off-topic for StackOverflow, but you will probably find more OpenGL-experienced and performance-minded coders over on gamedev.stackexchange.com. – Kylotan Nov 29 '11 at 18:44
  • you're right, i'm also gonna try my luck there. – Isracg Nov 29 '11 at 18:47

2 Answers2

2
  1. Altering the VBO every time you change the camera frustrum is not likely to be a good idea. The overhead from continuously buffering the data would probably outweigh any performance gains you would get from drawing fewer polygons. You would probably be better off culling entire VBOs when they move entirely out of the frustrum. You'll end up drawing more polys than are strictly necessary, but that will be more than balanced out by the fact that drawing from a VBO is drastically faster than drawing in immediate mode.
  2. You can change the size of a VBO, but only by doing a new call to glBufferData which can be an expensive call if you're sending the data to the graphics card.
  3. You would be best off not keeping all chunks you have created a VBO for in memory, that will quickly get out of hand. Keeping your immediate surroundings in memory, and discarding them when you move away is your best bet.
nonVirtualThunk
  • 2,842
  • 20
  • 20
  • to 2.: If he indeed updates the whole VBO every frame, he would (or should) call `glBufferData` anyway, so he can also just put in a different size. And if he doesn't update the VBO (like you suggested in 1.), he doesn't need to resize it either. So I don't see a problem with `glBufferData` in this case. – Christian Rau Nov 29 '11 at 18:58
  • I was just speaking generally regarding changing VBO sizes, rather than addressing his situation specifically. My intent was to indicate that changing the size of a vbo requires a complete rebuffer, so you can't, say, add a few elements to the end easily. – nonVirtualThunk Nov 29 '11 at 19:12
  • @nonVirtualThunk I have another question, do i have to keep an index for every vertex in every VBO? seems kinda memory expensive since i have many many vertex. Can't i just draw all vertex in a given VBO? – Isracg Nov 29 '11 at 22:46
  • @Isracg If you're talking the indices you use when calling glDrawElements(...), then no, they are not strictly required. You can use the glDrawArrays(...) function instead, if you would like. That will use each vertex in your VBO in order to make up primitives. glDrawElements(...) can actually allow you to use less memory overall, however, if you can share vertices between multiple primitives (one corner of a cube being used to draw the three faces it is part of, for example). – nonVirtualThunk Nov 29 '11 at 22:52
2
  1. The first naive (not neccessarily in a bad sense) approach would indeed be to update the VBO every frame based on the frustum and hidden face culling results. Although this may sound evil, keep in mind that using immediate mode does actually the same thing (send each vertex to GPU every frame) but with a million of driver calls (don't underestimate a glVertex) instead of just a few buffer functions and a single draw call.

    So using VBOs (with a usage of GL_DYNAMIC_DRAW or even GL_STREAM_DRAW, of course) will most probably still be faster than immediate mode. It is not only the possible GPU storage but also the reduced number of driver calls that make VBOs (or vertex arrays in general) faster than immediate mode.

    Later on you can also implement some more sophisticated hardware culling techniques, using transform feedback, so you do culling directly on the GPU and don't need to send the vertex data to the GPU each frame.

  2. Since you update the whole buffer each frame (and therefore should call glBufferData) anyway, resizing is absolutely no problem. Just call glBufferData again with a different size.

  3. It depends how many chunks you have. But if their number gets larger, some caching technique (delete VBOs of farther away, distance culled, chunks) may be a good idea.

Christian Rau
  • 45,360
  • 10
  • 108
  • 185
  • hey, i'm making very good progress with your suggestions, i only have one more question. Do i need to keep an index for every vertex in every VBO? – Isracg Nov 29 '11 at 21:41