User:Sneftel/OCWork

In large, complex scenes, visibility culling is possibly the most important means in existence of obtaining reasonable framerates. Modern graphics cards laugh at T&L'ing ten million triangle scenes, and have enough texture memory to store your entire world's atlases; and when they do have to pull data from RAM, they do so at a sustained transfer rates well into the gigabytes per second. But as we get more fragment processing performance we use it as fast as we can, with higher antialiasing levels and ever more complicated fragment programs, and that DOES cost. So while modelling our character's hands as 256x256 hand-colored mitten blocks is no longer required, minimizing overdraw, and in general minimizing the time to render things you can't see, is as crucial as it ever was.

Unity3D has support for several types of visibility culling. In grand Unity3D fashion, these are documented through vague pronouncements sprinkled throughout the manual and the reference manual and the script reference, and bolstered by a sort of oral tradition of what people tried and what worked. When visibility culling fails in Unity3D, it does so mysteriously and inscrutably. And as of 3.4, it does this very, very often. So there's a lot of well-intentioned superstition about how to get culling to work well in Unity3D. Most of it is wrong.

In this document, I will present some hard-won information about how visibility culling, and occlusion culling in particular, works on the inside. I will assume you have read this page several times.

Grids
First, let's talk about grid areas. At runtime, OC uses two main grid areas: the view grid, and the target grid. It has exactly ONE grid area for each of these, even if you have multiple view areas and multiple target areas! The grid area for each expands to bound all view areas.

There are two reasons this is important. First of all, it means that the edges of an occlusion area are not necessarily aligned with grid cell borders. An occlusion area is only used for viewpoints and/or objects which intersect it; but the grid cells that comprise it may not be fully contained within it.

Here's why that's important: Suppose your level is composed of several rooms, with thin walls between them. You create one occlusion area per room, inset slightly from the walls. You set the resolution of the areas quite low, reasoning that most things in a room will be visible anyway. To your surprise, this doesn't work well at all: Objects are often rendered on the other side of a wall, even one without a doorway in it. What's happening is, your view and target cells are overlapping the wall. Even though this occlusion area doesn't pass through the wall, viewpoints on the other side of that wall are being used to determine visibility, and objects in the other room are intersecting the target cells.

The other reason this is important is that grid size is limited. Each grid area may not contain more than 65536 grid cells. If you try to make areas with more cells than this, or multiple areas, the resolution will be cut down during the bake, even if it shows the higher resolution grids in the editor before baking.