(this is a very old post, I no longer use any of this)
Recently I decided to try adding real occlusion system to my game. There are a bunch of different ways to accomplish this, here are some common ones.
1) GPU occlusion queries
2) Software rendering for occlusion testing
3) Manual artist created portals and other similar systems(like Quake)
#3 is a non-starter for me as I want a dynamic game world, and don't have artists to throw around.
#1 I have tried before, but found that the inherit latency of CPU->GPU->CPU too large. I tried cheating by issuing a query for each rendered object every frame, and simply not drawing in if it failed the query test from the previous frame, but this suffered from pop-in.
#2 has become rather popular of late, and it is the method I decided to try this time.
A software renderer could be implemented as either a rasterizer or a ray tracer, and since I already had support for ray casting into my scene, via Bullet, I decided to try that first.
I wrote a little program to generate depth map of the scene by casting rays through the physics system, it was trivial to parallelize it since each ray was independent of the others.
Unfortunately performance was not good , as it turned out Bullet just wasn't fast enough to be ray casting 20,000+ rays each frame. I believe part of this is the fault of my levels which have far more objects than a typical game.
So I went back on that idea and switched to rasterisation. I stumbled across this post on devmaster by Nick, which was very helpful in getting a basic triangle rasterizer up and running.
I am at the point now where I can rasterize the scene on the CPU and performance is overall much better than the previous ray tracing attempt. I haven't even parrallelized or SSE'd it yet and it performs quite well(rendering ~50,000 triangles).
For my terrain I am using convex hulls of each chunk, these typically use a small fraction of the actual number of triangles that the rendered terrain contains. Unfortunately the generated hulls aren't exactly conservative(meaning they sometimes extend beyond the bounds of the source mesh), so I am certain I will see situations where the occlusion system says something is occluded when it really isn't...
...more on this later.