Precomputed Visibility simply not working

Hello,

I have had trouble figuring out whether precomputed visibility works on a per instance, per primitive component or per actor basis, as well as what the exact conditions necessary for any instance/primitive comp/actor to function as an occluder or occludable in precomputed visibility.

As such I have done a test, with a map containing a StaticMeshActor floor with its mobility set to static, a StaticMeshActor wall higher than the PlayAreaHeight also set to static, and several StaticMeshActor cubes hidden behind the wall, set to static as well.

They all have BasicShapeMaterial as their material, and there is both a LightmassImportanceVolume and PrecomputedVisibilityVolume covering the entire map. Static Lighting is allowed, and r.AllowPrecomputedVisibility is set to 1. I have baked lighting and precomputed visibility.

And yet when placing the camera behind the wall, well inside a precomputed visibility cell, no primitive is statically occluded. In fact, disabling occlusion queries shows the cubes behind the wall as unoccluded (provided they are not frustrum culled).

I’ve looked at the doc and everywhere else online and have no idea what I’m doing wrong, if anything. I know precomputed visibility used to be broken for a few UE5 versions but that was supposed to be fixed. Am I missing something or is precomputed visibility broken again?

UnrealEditor_HJLbwy4jLw.mp4(4.17 MB)

Steps to Reproduce
Create a level

Place a StaticMeshActor floor, mobility to static

Place a StaticMeshActor wall, mobility to static

Place multiple StaticMeshActor cubes behind the wall, mobility to static

Place LightmassImportanceVolume and PrecomputedVisibilityVolume covering the area

Build Lighting

Build Precomputed Visibility

enter “stat initviews” into the console

place the camera behind the wall so as to hide the cubes

Hi there,

Thanks for the information and video.

Precomputed Visibility in Unreal Engine is evaluated per primitive component, not per actor or per instance. Actors are simply containers, what actually gets marked as visible or hidden are individual UPrimitiveComponents. Instanced Static Meshes are a special case, all instances share a single visibility state.

A common misunderstanding is that Precomputed Visibility performs static occlusion, which it does not. Instead, Precomputed Visibility is essentially a precomputed data set that divides the world into discrete regions (cells) and records which primitives may be visible from each region before the game runs. It is not camera-based. Each cell stores a list of potentially visible primitives.

Occlusion culling is what actually uses this data. Rather than performing expensive occlusion tests on every primitive, the system first uses Precomputed Visibility to narrow down the set of candidates. Occlusion culling then operates only on the primitives associated with the relevant cells, significantly reducing the workload.

For example,

as the cells shown in the image, occlusion culling first filters the relevant cells, retrieves the list of potentially visible primitives, and then performs occlusion tests only on those primitives.

Hope this helps clarify the issue. Let me know if you have any further questions.

Best regards,

Henry Liu

Thank you, while there was confusion over whether cells stored a list of actor or a list of primitive, I did understand that each cell stored a list of which actor/primitive might be visible while the camera overlaps it.

This however does not explain why precomputed visibility does not result in any primitive being shown as statically occluded as explained in the InitViews portion of this documentation page https://dev.epicgames.com/documentation/en\-us/unreal\-engine/precomputed\-visibility\-volumes\-in\-unreal\-engine

Do you know why that might be the case?

Hi,

Sometimes the documentation on the webpage can be a bit outdated.

You can try using r.VisualizeOccludedPrimitives 1 to inspect occluded primitives.

Cheers,

Henry Liu

Hi there,

I will close this case now, but feel free to respond here if you have any follow-up questions.

Cheers,

Henry Liu