Occlusion Culling + Octree

Started by
16 comments, last by duhroach 21 years, 6 months ago
Hey all, was wondering if anyone had any references to some good Occlusion tutorials. I''m useing Octree for my rendering, along with frustum culling, and backface culling, But i''m still getting like 13fps when rendering a 20k poly scene. Anyhow, any links to some good Occlusion tutorials would be helpful. thanks all! ~Main == Colt "MainRoach" McAnlis Programmer www.badheat.com/sinewave
==Colt "MainRoach" McAnlisGraphics Engineer - http://mainroach.blogspot.com
Advertisement
i''m working on that but since its a commercial project i can''t talk about my algorithm , anyway when the application will ship i plan to release the source code of it.

There are lots of different approaches to occlusion culling, but generally you can divide them into two distinct categories: geometric methods and image space methods. The former ones work directly on the geometry of your scene, they are very precise but prone to accuracy problems and can''t take advantage of 3D hardware. The later ones can be hardware accelerated, can easily handle occluder fusion, are stable but less precise.

For a general purpose game engine, I''d recommend an image space method. I''m not aware of any tutorial, but there are quite a few research papers out there (for example this one).

The basic steps are very simple:

1) render potential occluders (the geometry that potentially hides the most objects) into a zbuffer. That''s the occlusion map.

2) use depth tests to determine if an objects bounding box is fully hidden behind the occluders. That''s normally done by rasterizing the bounding box into the occlusion map and comparing depths.

3) repeat (2) for all objects.

Step 2 can either be performed on the CPU alone, or can be HW accelerated on newer 3D cards.

/ Yann
Doesn''t image space comparisons cause you to actually render the scene multiple times per chosen occluer? Or is it just one pass for close Z occluers in the frustum, and then the rest is rendered or not based on it''s inclusion in the zbuffer? Also, in that doesn''t it require multiple passes?

I''ve read over the HOM & IOM methods, and wasn''t quite sure if image based rendering was reliable for sceen occlusion, mainly because, isn''t their a great amount of cards that don''t have any hardware support for the occlusion process? Which would cause me to just do plane image rendering? Which would just kinda defeat the purpose?

Ultimatly i was thinking of useing the Heirchial ZBuffering algo (RealTimeRendering v2 pg 383) because it''s made specificly for octrees. Combined with a occlusion horizion method, would produce some rather good results. And i''m useing ShadowMaps, so i''m having to render the scene from the light''s view anyhow, was trying to cut down on renderings.

So is the image based occlusion is what everyone''s useing now adays?

~Main



==
Colt "MainRoach" McAnlis
Programmer
www.badheat.com/sinewave
==Colt "MainRoach" McAnlisGraphics Engineer - http://mainroach.blogspot.com
Hmm, i''ve been thinking about ocllusion methods for a while. Multiple rendering of the scene is bad, having to read back from the display/z buffer is evil on most hardware.

So How about this:-

cull the scene using normal bsp/octree etc methods, each object of any significance ( 500+ polys/ large peices of buildings/terrain) have a *very* simple polys defining the "ocludded" area it contains. Render all these ocludders first to the z buffer, but not the display buffer.

Then when you draw you normal geometry ( front to back order ) there will be big areas (hopefully) that are rejected in the z compare. As a lot of modern gfx cards have a quick get out if the z test fails.

ie. inside a house with a single window, the occluder would be a box the shape of the house, with the square for the window cut out.

So what do you think? ( I''ll have to get around to trying it soon!
With image space occlusion culling, you don't need to render the whole scene multiple times. If you look at a typical 3D scene, you'll notice that only about 10% (or even less) of the faces contribute significantly to occlusion.

So the idea is to select a fixed maximum number of occlusion faces per frame, out of the set of those 10%. Say you have a scene with 100k faces, with around 10k showing a large contribution to occlusion. Each frame, you'd select about 100 to 500 faces as occluders. The performance impact will be minimal.

Depending on the type of your scene, you can even create special 'occlusion geometry'. That's what Mark Duffill had in mind in the previous post. This is esp. interesting in scenes with lots of large buildings, eg. a city model. You create a very simple and coarse 3D skin of your models, modelling occlusion. This skin is then rendered to the occlusion map instead of the (complexer) main geometry. Using this method, you can get away with 50-100 faces per frame, and still get decent occlusion behaviour.

Another very important point of image space methods is the excellent handling of occluder fusion. Lots of small occluders that overlap will automatically form a big unified occluder with those methods. That's a lot harder to achieve with geometric methods.

It's true that most 3D cards do not support HW occlusion queries yet. But this feature will be supported by every new 3D card, so it's worth including in any engine at this point. A fallback function for older 3D cards is important, of course. The zbuffer readback is typically not that slow, considering that your occlusion map can be pretty low resolution (128*128 is more than enough for most scenes). If you want to completely avoid the readback, then get out your old software 3D rasterizer. It can be pretty fast to do a small 128*128 depth only rendering on the CPU alone. No lighting, no colours, no texture, and only around 100 faces - a well optimized SW rasterizer can do that in less time than a zbuffer readback would require.

/ Yann

[edited by - Yann L on October 1, 2002 12:58:29 PM]
Hum..
So, we:
a) Determine nodes of octree in view frustum (list: VIEWABLE)
b) Z-Order the OBJECTS in VIEWABLE from front to back(list: Z-VIEW)
c) In Z-VIEW, determine qualifying OCCULERS (items closest to the camera in Z-VIEW? What's the best way to do this?)
d) Disable alpha, texture, lighting
e) Render our qualifying OCCULERS to the ZBUFFER
f) Test all other items in Z-VIEW against the ZBUFFER, if it returns true (viewable) Set flag in object to RENDER
g) cycle through Z-VIEW, all OBJECTS with flag RENDER, we draw to the rendering screen.

Is that about right?

And if it is, can we just not render to the zbuffer? instead to the screen and do a depth test there?

~Main



==
Colt "MainRoach" McAnlis
Programmer
www.badheat.com/sinewave

[edited by - duhroach on October 1, 2002 6:55:02 PM]
==Colt "MainRoach" McAnlisGraphics Engineer - http://mainroach.blogspot.com
Basically correct.

"b) Z-Order the OBJECTS in VIEWABLE from front to back(list: Z-VIEW)"

You can do that, but it''s not mandatory. It might give you the benefits of early z rejection, but make sure to check if the overhead of sorting is worth it or not.

"c) In Z-VIEW, determine qualifying OCCULERS (items closest to the camera in Z-VIEW? What''s the best way to do this?)"

Different heuristics are possible. The best occluders are the objects with the biggest projected area WRT the camera. Ie, take the perspective projected size (bounding boxes) and relative orientation to the camera into account. If you use the dedicated occlusion geometry approach, then selection is even easier: just take the nearest ones, until your maximum facecount has been reached.

quote:
And if it is, can we just not render to the zbuffer? instead to the screen and do a depth test there?

Hmm, don''t understand what you mean here. You can only do a depth test using a depth buffer. What do you mean by making a depth test on the screen ?

/ Yann
Yann, Good call on getting rid of step B in figuring out occulers.

As for doing a "depth" test on the screen, i mean do we have to render to the depth buffer to determine what''s viewable? IE can we just render to the screen, and use that?
Or do we have to render to depth buffer, then render to screen?

thanks for the help yann

~Main

==
Colt "MainRoach" McAnlis
Programmer
www.badheat.com/sinewave
==Colt "MainRoach" McAnlisGraphics Engineer - http://mainroach.blogspot.com
Hi,

What Yann is saying about rendering to a small z buffer surface and using it to reject objects that are hidden is what I tried intitally. However I found that a lot of cards wont give you access to the z buffer surface unless you only run in 16 bit modes. (DX8) And if they do you can get a bad frame rate hit.

AFAIK only some HP gfx cards support ocllusion querying so far, and so modified my process to render the oclluding polys to a small render target texture. Reslulting in a black/white image which could then be read back and tested.

However even that is a big performance hit, since on most modern gfx doing any sort of reading back data generates stalls in the gfx card due to syncronisation issues.

So I could render in software the ~100 oclluder polys, and test that, but gfx cards (Geforce+) are so fast you probably could render several thousand polys in the same time, making it a waste of time.

So the thats why I though of the idea of rendering the oclluders to the z buffer first then the scene front to back and thus take advantage of the early z buffer reject.

btw drawning front to back instead of back to front resulted in a 30% speed up on a project which has just finnished. This was for GeForce 3 equivilant cards. So it may be worth profiling in your case what effect it has.

Anyhow roll on cards that support ocllusion testings!

This topic is closed to new replies.

Advertisement