Occlusion culling w/o a Zbuffer

Started by
7 comments, last by MattSutherlin 8 years ago

I'm having trouble with visualizing this so I'm not sure if I'm completely off base any help would be greatly appreciated.

The idea is to do this in a compute shader using shared memory.

So lets say I create rectangular occlusion geometry for walls. Now I create a 5 plane frustums (no far plane) with the eye point as the apex for some of the visible occlusion geometry. Then I test bounding boxes of potential occludees against these frustums but instead of the basic frustum test I test for any section being in front of the near plane, completely out the frustum, partially in the frustum and completely in the frustum. If its completely in the frustum it doesn't get drawn. There is some more possibilities after that but thats just details. Logically am I right??? Will this work or am I picturing things wrong? Will the frustums generate proper occlusion? I know a zbuffer is easier more accurate and there are no corner cases with it but I am curious about this. So am I completely off base or is this feasible?

-potential energy is easily made kinetic-

Advertisement

That is correct. When bounding box/sphere is fully inside of all those 5 planes then it's fully occluded.

This is old school. Compute shaders, meet 1999 :)

http://www.gamasutra.com/view/feature/131388/rendering_the_great_outdoors_fast_.php?page=3

http://www.gamasutra.com/view/feature/131801/occlusion_culling_algorithms.php?page=4

Yep it works. As in that first article, you can have more than one "near plane" on your convex hulls (frustra) if you like.

Some engines will refer to these planes as anti-portals or simply, occluders.

The catch is that you need to find a reasonably small set of large occluders. If you have a large set of occluders, you've got to perform too many tests, and if your occluders only cover a small screen area, they're not likely to occlude anything.

The failure case is what you have an object which is actually hidden by many small occluders, but isn't completely hidden by any single occluder. This system cannot determine that such an object is occluded.

I know of some Xb360/PS3 games which actually used this as their main culling technique -- they got the level designers to place large quads inside walls/buildings/etc. The engine then frustrum culled these quads, selected five of them with the largest screen-space area, built the occlusion-frustrums from them, and then culled any objects that were entirely within these occlusion-frustra.

I know a zbuffer is easier more accurate and there are no corner cases with it but I am curious about this.

zbuffer ist actually less accurate (if lower resolution, which is the common case) and has more corner cases (e.g. you need water tight rendering, deal with z-fighting issues etc.)

the bad side of occlusion volumes is that these are disconnected, hence just fully occluded object will be removed, objects crossing several occlusion volumes will stay, although in reality invisible.
one solution to this is "occluder fusion", but that's where math become dirty. (actually, not the math, but dealing with all the float precision issues.)

What i do is: Use software rendering to render occluding polygons but mark only start and and points per scanline,

that way it's not necessary to check each pixel like with GPU occlusion culling.

Testing a bounding box just means testing all scanlines it touches.

This system is very work efficient, correctly rejects stuff occluded from multiple occluders, handles dynamic occluders and free frustum culling is a bonus.

The big downside (nowadays) is: It's impossible to parallelize without doing potential useless work. Doing on GPU seems a no-go :(

Even CPU multi threading does not make much sense.

But i still think it's a good method if you can support (handmade?) coarse occluder polys,

and accept the long CPU runtime (worst case 5ms for 16 family houses with full interior visible through windows)


That is correct. When bounding box/sphere is fully inside of all those 5 planes then it's fully occluded.

Thank You.


The catch is that you need to find a reasonably small set of large occluders. If you have a large set of occluders, you've got to perform too many tests, and if your occluders only cover a small screen area, they're not likely to occlude anything.

I have something in mind, hopefully it works out.


zbuffer ist actually less accurate (if lower resolution, which is the common case) and has more corner cases (e.g. you need water tight rendering, deal with z-fighting issues etc.)

Hadn't thought about z-fighting, and I was thinking full size gpu occlusion so I hadn't thought of that. What do you by "mean water tight rendering", I've heard the term before but don't remember what it means?


What i do is: Use software rendering to render occluding polygons but mark only start and and points per scanline,
that way it's not necessary to check each pixel like with GPU occlusion culling.
Testing a bounding box just means testing all scanlines it touches.

I think thats referred to as a span buffer. Also 5ms wow thats alot.

-potential energy is easily made kinetic-

zbuffer ist actually less accurate (if lower resolution, which is the common case) and has more corner cases (e.g. you need water tight rendering, deal with z-fighting issues etc.)

Hadn't thought about z-fighting, and I was thinking full size gpu occlusion so I hadn't thought of that. What do you by "mean water tight rendering", I've heard the term before but don't remember what it means?

z-fighting happens if you use e.g. lower LODs for occlusion culling (which makes sense if you think about it, as you just test, but you don't care about the visuals). The problem pops up if you e.g. have a picture on the wall (flat poly) and some LOD of the wall/room is used which is not 100% fitting the higher poly that is rendering close up.

water tight rendering is, when you don't have pixel-gaps between triangles of a mesh. Equally important is to not "over-draw" edges twice. you'd notice this on transparent triangles where edge-pixel blend twice.
this is especialyl important on occlusion culling, as one pixel-gap will "un-hide" everything behind and all occlusion culling was a waste of time. similar drawing too much will lead to occlusion in places you don't want to.

similar drawing too much will lead to occlusion in places you don't want to.

This is a big problem for any occluder rasterization approach, because it prevents you from doing it at much lower resolution.
I have tried to raster shared edges water tight, and open edges in a way only pixels entirely inside polygon get drawn (opposite of conservative rasterization).
But there remain problems and additional complexity slows down, so i gave up on this.

One solution would be to render non-occluding geometry instead (portals instead occluders), like Umbra does: http://www.gamasutra.com/view/feature/164660/sponsored_feature_next_generation_.php
But this requires precalculation so it's static.

Another solution would be to use polygon clipping instead rasterization.
I doupt that's faster but i might give it a try sometime...

I know of some Xb360/PS3 games which actually used this as their main culling technique -- they got the level designers to place large quads inside walls/buildings/etc. The engine then frustrum culled these quads, selected five of them with the largest screen-space area, built the occlusion-frustrums from them, and then culled any objects that were entirely within these occlusion-frustra.

For example, Fallout 3.

This topic is closed to new replies.

Advertisement