Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm currently working with upgrading and restructuring an OpenGL render engine. The engine is used for visualising large scenes of architectural data (buildings with interior), and the amount of objects can become rather large. As is the case with any building, there is a lot of occluded objects within walls, and you naturally only see the objects that are in the same room as you, or the exterior if you are on the outside. This leaves a large number of objects that should be occluded through occlusion culling and frustum culling.

At the same time there is a lot of repetative geometry that can be batched in renderbatches, and also a lot of objects that can be rendered with instanced rendering.

The way I see it, it can be difficult to combine renderbatching and culling in an optimal fashion. If you batch too many objects in the same VBO it's difficult to cull the objects on the CPU in order to skip rendering that batch. At the same time if you skip the culling on the cpu, a lot of objects will be processed by the GPU while they are not visible. If you skip batching copletely in order to more easily cull on the CPU, there will be an unwanted high amount of render calls.

I have done some research into existing techniques and theories as to how these problems are solved in modern graphics, but I have not been able to find any concrete solution. An idea a colleague and me came up with was restricting batches to objects relatively close to eachother e.g all chairs in a room or within a radius of n meeters. This could be simplified and optimized through use of oct-trees.

Does anyone have any pointers to techniques used for scene managment, culling, batching etc in state of the art modern graphics engines?

share|improve this question

closed as too broad by Josh Petrie Aug 25 at 15:17

There are either too many possible answers, or good answers would be too long for this format. Please add details to narrow the answer set or to isolate an issue that can be answered in a few paragraphs.If this question can be reworded to fit the rules in the help center, please edit the question.

4  
What I do to combine batching with culling is keep static vertex buffers and dynamic index buffers, and batch unculled objects into the index buffers. –  Darth Satan Jun 21 '13 at 12:11
    
That's a good idea. I wont have much time to fiddle around with the work this weekend, but I'll be checking inn and looking for more tips if anyone steps up :) Thanks for the reply though, mh01! –  Kristian Skarseth Jun 21 '13 at 20:50
    
I'm going to quote a reply i got on gamedev.net forums in case anyone else stumble upon this thread and have a similiar question: "Hi, I recently presented an article at the GRAPP 2013 conference that deals with exactly this stuff - high level of occlusion AND high level of component replication: link /Mikael" Link to the forum thread –  Kristian Skarseth Jun 24 '13 at 9:58

3 Answers 3

The way I see it, it can be difficult to combine renderbatching and culling in an optimal fashion. If you batch too many objects in the same VBO it's difficult to cull the objects on the CPU in order to skip rendering that batch. At the same time if you skip the culling on the cpu, a lot of objects will be processed by the GPU while they are not visible. If you skip batching copletely in order to more easily cull on the CPU, there will be an unwanted high amount of render calls.

You would usually cull objects first. Only then do you walk your potentially visible set and build batches for rendering.

If culling your objects proves to be slow you could try grouping them into bounding volume hierarchies and cull those first.

share|improve this answer
    
I think we have a good design for our solution put together now. We'll indeed be performing culling and then building batches from the potentially visible objects. –  Kristian Skarseth Jun 24 '13 at 17:47
    
The objects will also be grouped in BVH. After research we have settled with kd-tree. –  Kristian Skarseth Jun 24 '13 at 19:41

There's lots of information about frustum and occlusion culling on the internet. Most of it comes from game developers. Here's a list of some articles that will get you started:

My (pretty fast) renderer works similar to this:

  1. Collection: Send all props, which you want to render, to the renderer.
  2. Frustum culling: The renderer culls the invisible props from the list using multiple threads in parallel.
  3. Occlusion culling: Now you could do occlusion culling on the CPU (I haven't implemented it yet, because I don't need it now). Detailed information on how to do it efficiently can be found in the Killzone and Crysis slides. One solution would be to read back the depth buffer of the previous frame from the GPU and then rasterize the bounding boxes of the objects on top of it to check if the object is visible.
  4. Splitting: Since you now know which objects actually have to be rendered, because they are visible, you have to split them by mesh (you can also split them by texture instead), because each mesh has a different material or texture (otherwise the modelling software would have combined them into a single mesh).
  5. Batching: Now you have a list of meshes to render. You can sort them by:
    • depth (this can be done on the prop level instead of the mesh level), to save fillrate (I don't recommend doing this if your fragment shaders are very simple).
    • mesh (because there might be multiple instances of the same mesh and it would make it easy to add instancing).
    • texture, because texture switches are very costly.
  6. Rendering: Iterate through your partitioned meshes and render them.
share|improve this answer

Probably the best way to go with a modern DX11 level HW today is to:

  1. Do frustum culling using octree or similar on CPU
  2. Batch objects in a frustum per frame (i.e. build dynamic instance streams for each object type in the frustum)
  3. Perform occlusion culling purely on GPU (i.e. convert the FOV instance streams to renderable instance streams).

For the the last step you need DX11 level HW, i.e. use compute shader to build renderable instance stream and DrawIndexedInstancedIndirect(). Also for the occlusion culling I would go with bounding box test against hierarchical Z-buffer

share|improve this answer

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