How can you add lights to Occlusion Culling

Hi there!

Hope this is the right channel to post this.

So I don’t seem to find a concisive answer to this online, what I can find is either vague, old, unanswered or all of the above! :smile: (or people complaining about having the very thing happening that I’m trying to achieve, lol)

I’m having an indoor scene with multiple rooms where I set up occlusion culling which works pretty well with the outline of the scene. However, the lights never get culled, which is a bummer, because that’s the main antagonist/performance hog here (stats with lights: 800k-1,4m polys, lights disabled: 100k - 400k) so I really REALLY would love to be able to do this!

(Due to the nature of the project those have to be RT lights, there is a webGL version with mixed lights which have better stats, but it would be also great to be able to occlude those)

So I’m wondering: is this even possible at all? Was I just too dumb to google?

One very old answer I found was activate dynamic occlusion, but that option doesn’t even exist with lights (it also said it is a pro feature, so it’s probably a very old answer)

I tried setting the lights to ocludee static, but no dice.

Is there a way to do this? There is a programmer I can annoy if this needs a code solution :slight_smile:

Thanks guys!

Bump! :slight_smile:

When you are using pixel shader, the lights only calculated on every pixel that visible on screen… So you don’t need culling… You can reduce resolution to recuse screen pixels to optimize lighting and post processing

Nope, Unity only does the basic frustum culling when it comes to lights. You could try using the CullingGroup API to manually register the lights’ bounding spheres and determine if they are visible, but I’m not sure it integrates with occlusion culling.

From the stats the OP posted they seem to be using built-in forward rendering, where lights are rendering by re-drawing the affected objects with additive blending.

It sounds like it could be real-time shadow map rendering that is causing the performance impact. Use the Frame Debugger to confirm this.
If it is, you can use shadow caching Shadows in the High Definition Render Pipeline | High Definition RP | 14.0.0 (unity3d.com) to for instance update the shadow maps in a round robin fashion or control shadow map updates manually by triggering a request for HDRP to update the Light’s shadow map only when needed. To do this, make sure the Light’s Update Mode is set to On Demand and call RequestShadowMapRendering.

Got this problem myself, the answer is light is occlusion culled in some freaking un-predictable way that even unity don’t know how it’s done - it’s a lost technology residing somewhere in a depths of source code.
I even reported some bugs regarding this issue unfortunately without satisfactory result.
Also static on Light object is completely ignored.

I was able to tame it a little programmatically and now I’m going to share with you my secrets ;).

What I’m doing is that I create mesh around my lights, for point light it is a sphere with radius equal to light radius. This mesh has semi transparent material around itself so I can see it and during play I swap it with invisible material (but I’m reconsidering just removing the material and leaving the renderer with null material). Than you set object to be occlude static but disable occluder static (might not be needed transparent objects are unfortunately considered not occluder static and you cannot change this behavior) .

Bake occlusion.

Than you use OnBecameVisible and OnBecameInvisible to get the visibility state of the light (this mesh object).
Now you are left with two problems:

  1. Light will still be visible through walls if mesh representing light is intersecting the wall. (I’m doing some hacky way to mitigate this problem)

  2. When you are completely inside this mesh but don’t see the surface of it, OnBecameInvisible might be called.
    I’m solving this by checking where is camera and if it is inside particular light I keep light enabled.

This is a simple way of explaining it, my system is much more complex.

2 Likes

Hi guys, thank you all so much for taking the time to respond and sorry for the late answer!

@aliyeredon2 Hi there!
as @Neto_Kokku has stated, Unity sadly doesn’t really occlude the lighting and in my case, unfortunately not even from frustrum culling! :frowning:
(if you go to the Visualization Tab from the Occlusion Window (which can be found under Window/Rendering/Occlusion Culling) you can then select any camera in the scene (also if its disabled) and move/rotate it around and you can see how the culling works. Sadly the Light Icons don’t disappear at all :()

@Neto_Kokku Hi there as well! :slight_smile:
So the Quality Settings are all set to Deferred (but the way I understood it, if it doesn’t work for some reason it switches to Forward automatically, e.g. if the platform/hardware doesn’t support deferred etc.)
Changing the Cam Setting to deferred doesn’t change anything either :frowning:

@KEngelstoft thanks for the reply!
I will check out the Frame Debugger you mentioned. We’re actually using the Built in Render Pipeline and don’t have plans to change that anytime soon because the project requires each scene to have a webGL version as well (Desktop Version using RT lights, WebGL using mixed lights, because of no RT GI in WebGL), and AFAIK the HDRP and also the URP amongst other things are not supported, therefore we use BIRP.
Is there also a solution for that? :slight_smile:

@koirat hey, thanks for the insight!
What a very depressing fact :frowning:
Although thanks for sharing those precious and probably hard earned secrets of yours!! :slight_smile:
I will definitely check this solution out :slight_smile: is this OnBecameVisible an already existing code thingy in Unity or something that has to be defined in the code? (See how well aware I am of things? haha)

Use this method on a sphere and enable/disable your lights using a script. You can use a transparent material for your sphere

1 Like