Is it possible to do proper Occlusion Culling at an angle?

I’ve been messing around with occlusion for hours now and I can’t get it to behave the way I want.

Essentially the issue is the visibility lines pass slightly through an occluder if the camera is facing it at most angles other than head-on.

For example, in the image below, I’ve even added a solid cube (set to static) to try to fix this. As you can see, the visibility lines seem to go an arbitrary amount through the solid wall (as well as the actual walls im trying to use)

(occlusion example - Album on Imgur)

The goal is to get that crystal to occlude successfully, as I have game logic that will depend on discovering it for the first time, and I want the player to see what it is that’s being discovered!

I’ve tried using very small values when baking the occlusion map (this SS was from an attempt using 0.5 for the smallest occluder.)

Would really appreciate help here.

With Unity, Occlusion Culling has shot itself in the foot. Many posts about it over the years. I love Unity, but OC is a non-reliable system. At an angle?, Save yourself the headache, dont use OC…

Trying to drive game logic via occlusion culling sounds like a minefield. Not sure if its behaviour is consistent accross al platforms or even dererministic, and it’s not specced. Occlusion culling is for performance.

If you really want to implement it based on what the player sees… so the easiest way would be raycasts. See if a ray from the camera intersects the bounding box of the crystal. If so (and crystal is close enough), cast a grid of rays (maybe 4x4 or something) at points from the camera’s FOV, and see what they intersect. If any of them hit the cystal, the player has seen it. That’s not completely robust, but it’s maybe good enough.

If you want to be more thorough or not all the occluders have colliders, then…

  1. Downsample depth buffer to a MUCH lower resolution. Example I wrote a few months ago which does that.
  2. Draw the object (or just its bounding box) to a new render target with the downsampled depth buffer (offset slightly so it doesn’t intersect itself). Use a replacement shader that just draws a solid red color or something; keep it super simple. Use conservative raster on platforms that support it.
  3. Run a compute shader over this small render target to see if any of the pixels are red.
  4. Use AsyncGPUReadback and on the next frame, you’ll find out if the player has seen it.

… BTW,

1 Like

Thanks for the replies. After seeing a bunch of the other forum threads I was beginning to think OC was hopeless.

I wanted to avoid the raycasting solution cause I wasn’t sure immediately how to do it without trying to raycast every possible ray in the frustum which seems like it would make my pc explode. I think I’ll try the grid of rays method.