Tim Hobson

Precomputed VIsibility Volumes

​The primary benefits of precomputed visibiliity volumes is that it will store the visibility of Actors based on their location in the world. This is extremely usefule for mobile platforms which do not support hardware occlusion queries, and to save rendering thread time in rendering thread bottlenecked scenarios like split screen on consoles. Precomputed visibility decreases rendering thread time in game at the cost of increasing runtime memory and lighting build time. It saves rendering thread time by reducing the number of primitives that have to be handled by the dynamic occlusion system (hardware occlusion queries) and because it works immediately, while the dynamic occlusion system needs time to converge, which often means poor performance coming around a corner or rotating the view quickly. This technique is only useful for medium sized levels or smaller, as the memory and computation requirements grow with the level size. It is also only useful for games with mostly static environments, restricted player movement and somewhat 2d play areas.

Setting up a game to use Precomputed visibility

Since scale is game-dependent, parameters for visibility calculation need to be tweaked for each game. These are located in the DevOptions.PrecomputedVisibility section of BaseLightmass.ini in the Engine/Config folder. If you would like this to be default for your game project specifically you can add a DefaultLightmass.ini file to your project Config's folder with the DevOptions.PrecomputedVisibility section and edited values.

The primary setting to tweak is:
Property Description
PlayAreaHeight This is the height above a surface that the camera can be. This is usually your tallest players eye height plus their jump height. The default value is 220.
You do not need to restart the editor in order to make changes to the config file. You simply need to make the edit and save the config .ini file for it to take effect.
​In the example below the character is 192 units in height. Since the template characters can jump higher than the PlayAreaHeight it would be advisible to adjust this to a greater height in this instance. Once your rebuild lighting the visibility cell (blue box) will adjust to the height in the config file.
PlayAreaHeight: 220 (Default) PlayAreaHeight: 500

Setting up a level to use precomputed visibility 

​First, place one or more Precomputed Visibility Volumes around the play areas of your level by dragging it in from the Modes panel. These do not have to be rectangles or axis aligned, any brush shape will work. They should bound the play areas as tightly as possible for optimal memory usage and build times.
Next, you can enable Precomputed Visibility in the World Settings Precomputed Visibility section and then hit the Build button in the Main Toolbar to build lighting for your level.

Now when your camera is inside the a visibility cell the renderer will cull any objects that were determined to be occluded.

visibility cells

Visibility cells are placed just above shadow casting geometry inside the Precomputed Visibility Volumes you have placed, and along Matinee camera movement tracks even if they are outside of a visibility volume. Precomputed visibility can only work if the viewer is inside one of these cells, so most of the time when you are flying around in the editor it will not be active.

This image shows blue visibility cells placed on surfaces inside the green visibility volume in the Infinity Blades: Grass Lands pack that is freely available in the Epic Games Marketplace.
This image shows blue visibility cells placed along a matinee camera movement track:
In order for precomputed visibility to work you will need to build the scene. You can use the drop-down arrow next to the Build icon and select Precompute Static Visibility.

Visualize precomputed visibility cells

​To visualize the visibility cell placement within the Precomputed Visibility Volume simply use the Show Visualize > Precomputed Visibility Cells option in the viewport to enable this view.
​If you have not yet enabled Precomputed Visibility in the World Settings or built lighting for the level the visibility cells will not be visible. Also, if you have adjust the volumes placement or settings you must also rebuild lighting in order for this to take effect.

settings

Visibility Settings

Property Description
Precompute Visibility Whether to place visibility cells inside Precomputed Visibility Volumes and along camera tracks for this level. Precomputing visibility reduces rendering thread time at the cost of some runtime memory and somewhat increased lighting build times.
Place Cells Only Along Camera Tracks When this is enabled visibility cells will only be placed along the camera track.
Visibility Cells World space size of precomputed visibility cells in the x and y. Smaller sizes produce more effective occlusion culling at the cost of increased runtime memory usage and lighting build times.
Visibility Agressiveness Determines how aggressive precomputed visibility should be. More aggressive settings cull more objects, but also cause more visibility errors like popping.

Relevant Stats

There are some relevant stats that can be helpful in seeing how effective precomputed visibility is. You can bring up the console window and entered the console command Stat InitViews.

In the image below you will want to look at the stats for Statically occluded primitives and Occluded primitives when determining how well the precomputed visibility is working for your scene.
These stats are most reliable in game or PIE, and not in the editor, due to all the debug stuff that gets drawn in the editor.
Stat Description
Statically Occluded Primitives This shows how many primitives were determined invisible by precomputed visibility after frustum culling took place. This will only be visible when the camera view is inside a visibility cell.
Occluded Primitives This shows how many primitives were determined invisible by both precomputed visibility and the dynamic occlusion system.
Decompress Occlusion This shows how much time was spent decompressing precomputed visibility. Large volumes or smaller cell sizes can increase the memory usesd which will affect the time it takes to decompress.
The difference between these two stats is how many primitives the dynamic occlusion system culled that precomputed visibility missed. When precomputed visibility is working well, Statically occluded primitives should be within 50-80% of Occluded primitives. Precomputed visibility culls less objects because it stores information for large cells and does not handle dynamic or masked occluders (see the Limitations section).

Another stat view that you can bring up is the Stat Memory while in game. This will display where memory usage is being allocated for your game. You can see how much memory is being used by precomputed visibility by taking note of the stat for Precomputed Visibility Memory.
This stat is not reliable in PIE. Instead, check it in the Editor or in game, since it is counting both PIE and the Editor memory when in PIE.
Stat Description
Precomputed Visibility Memory Shows how much runtime memory is used by precomputed visibility.

precomputed visibility override volume

​Precomputed Visibility Override Volumes let you manually override the visibility of Actors/levels for their location in the world if the auto-generated result of PrecomputedVisibilityVolume is undesired.
Property Description
Precomputed Visibility Override Volume
Override Visibile Actors This is an array of actors that will always be considered visible by Precomputed Visibiliey when viewed inside this volume.
Override Invisible Actors This is an array of actors that will always be considered invisible by Precomputed Visiblity when viewed from inside this volume.
Override Invisible Levels This is an array of level names whose actors will always be considered invisible by Precomputed Visibility when viewed inside this volume.

Limitations

The current implementation of precomputed visibility has these limitations:
  • Does not handle movable objects or movable occluders
  • Does not handle non-opaque occluders, because masked occluders often have small holes that are difficult to detect.
  • Only places cells above surfaces, so games with flying modes won't get much benefit
  • Does not handle streaming levels efficiently, all data is stored in the persistent level instead of streamed in and out with the streaming levels
  • Only static shadow casting triangles will occlude. This means that a lightmapped interpactor will occlude when it should not, and a non-movable object that does not cast shadows will also not occlude when it should.

Debugging Visibility Issues

​There are a few console commands that can be helpful when debugging precomputed visibility issues:
Property Description
r.AllowPrecomputedVisibility If 0, precomputed visibility will not be used to cull primitives.
r.ShowPrecomputedVisibilityCells If not 0, this will draw all precomputed visibility cells within the Precomputed Visibility Volume.
r.ShowReleveantPrecomputedVisibilityCells
If not 0, this will draw only relevant precomputed visibility cells that visible from the camera position.
If you have objects disappearing and set r.AllowPrecomputedVisibility to 0 causes them to be displayed, then precomputed visibility is causing the issue and you will need to adjust the existing volume or add new ones to make sure the area is fully covered. You can also use a Precomputed Computed Override Volume to override any unnecessary occlusion.