Occlusion culling is not working on point lights? UE5 bug?

I recently realized my game has terrible performance due to a lack of point light culling.

Here is a point light and a cube.

I have turned on occlusion culling visualization with the command “r.VisualizeOccludedPrimitives 1”

Now see what happens when I occlude the two objects, with a large box:

The cube is occluded, while the point light is not. Does anyone know why this is?

Note: to reproduce this, you have to be in play mode.

Maybe not a perfect solution but it might help performance

Culling a light is more complex as you have to check if it’s shadow is visible even if the light is off screen.

You could probably attach it to an actor and have that drive it’s visibility via “Use Attach Parent Bounds”

hmm, well if the last comment in that thread is true, that could be the issue:

It would result in many light not being culled in my particular project.

The other thing is that actors are only culled if they have a mesh component. Having just a point light in an actor did not trigger the culling process.

Stat LightRendering does show that lights are at least frustum culled.

It is complicated to explain why, but i have to use instanced static meshes for most things, and they do not support perinstance culling. I expect this results in alot of unculled objects and that is why the lights cannot be properly culled - The lights often have an object to affect, even when they are totally obscured from view.

Have you tried attaching the lights to their respecting rooms? Then maybe once the room gets culled the light will be disabled?

Edit:
Further testing: “Was Actor Recently Rendered” doesn’t check for occlusion :confused:

when a light becomes occluded it seems to change from a “shadowed” light to a “batched” light. so the systems understands when a light is occluded, but for some reason rather than disabling rendering on it, it just disables shadows on it.

I tried tying light to an array inside of an actor and testing against its render status, setting lights intensity to 0 and reverting back to normal values if visible. It semi worked. Though it’s probably not optimal.

1 Like

thats a neat idea actually, thanks! il see if i can make it work.

I’ve done a test where I link a line test function to the room and do a line trace by channel every 0,2 from the camera manager position to the actor and if it hits then I turn on the lights, if it misses then I turn them off. It works, though you would need to activate / deactivate the timers with a sphere trace overlap from your character to keep it optimized. The lights then physically turn off :slight_smile:

you were pretty bang on with your previous suggestion tbh. I didnt need to do line traces.
I added a sphere mesh component to my lights that represents the light bounds. I turned off render in main pass, and render in depth pass, and use the “WasRecentlyRendered” function to check if it is occluded. If it is occluded, i set the light to be hidden.

To save on performance remember to reduce the tick rate of the AActor_Light. No need to check every frame for it :wink:

Glad you were able to find a workable solution.