Software Occlusion Queries for Mobile

An overview of using Software Occlusion Queries for mobile platforms as a dynamic occlusion culling method.

Choose your operating system:

Windows

macOS

Linux

Software Occlusion Queries is an occlusion method that uses designated level of details (LOD) of an Actor to occlude ones behind it. This culling method rasterizes the scene on the CPU to cull Actors, where in comparison, Hardware Occlusion Queries perform visibility checks on the GPU. The conservative design of software occlusion means that it can be enabled and used on any mobile device. It should also be noted that software occlusion only has a single frame latency compared to hardware occlusion queries, which have two frame latency on mobile.

SOQ_Banner.png

Left: The scene view using Software Occlusion Debug Visualization that includes a set of assigned Static Meshes for occlusion. Right: The reverse scene view behind the house showing how the "occluder" Static Meshes have culled geometry.

Enabling Software Occlusion Queries

Enable software occlusion in the Project Settings > Rendering > Mobile and set Support Software Occlusion Culling .

Alternatively, you can use the following console variable: r.mobile.AllowSoftwareOcclusion 1

When targeting multiple devices, use the Device Profile manager to enable software occlusion.

Setting Occluder Meshes

Before occlusion culling can work, you must first specify a Static Mesh's LOD to be an occluder. The specified LOD will be used to block other Actors in the scene that are behind it when in the camera view.

In the Static Mesh Editor, use the Details panel to set the level of detail used for occlusion purposes. Enter a LOD value greater 0 but less than the number of LODs available on this Static Mesh into the LOD for Occluder Mesh text field.

Soq_SMEditorSettings.png

When choosing a LOD Occluder Mesh to use, any LOD value entered that is outside the range of available ones, will default to the next closest one. For example, If you're Static Mesh only has a single level of detail (LOD0), a value of 2 will use LOD0 because there is no LOD2 available. Conversely, if you have four LODs set up (LOD0 - LOD3) and give a value of 2, LOD2 will be used as the occluder mesh. Using a value of -1 means that no LOD is assigned as an occluder.

Ideally, only enable medium to large-sized meshes that make sense to be an occluder for other smaller objects. Using smaller meshes as occluders will have little to no significant impact to cull other objects.

Debugging Visualization for Software Occlusion

Once you've set the LODs to use as occluder meshes for your Static Mehes, you can enable the Software Occlusion Buffer Visualization in the level viewport. This view mode enables a small window in the top right of the screen when using the Mobile Previewer . The buffer only displays the selected occluder meshes and uses these to cull any meshes blocked from their view, similar to how Hardware Occlusion Queries cull objects blocked by others in the scene.

Follow the steps below to enable this visualization view mode:

  1. Set the Level Viewport to use the Mobile Previewer .
    soq_enablevisualization-1.png

  2. Use the console ( ` ) to enable software occlusion visualizer with r.SO.VisualizeBuffer 1 .

When enabled, any Static Mesh enabled as an occluder will be drawn to the buffer visualization displayed in the top-left of the Level Viewport.

Click image for full size.

You should now see any Static Mehses that have been enabled as the LOD for Occluded Mesh in the Static Mesh Editor. To better illustrate this, the example below shows highlighted Actors that have been enabled as occluder meshes for the buffer visualization view mode.

Scene View

Scene View with highlighted Occluder Meshes

Performance Statistics

Use the command stat softwareocclusion to get an idea of how effective software occlusion is in your levels.

Click image for full size.

Use the Cycle Counters to get an idea of what is being processed for the scene and how much render time it's taking. Counters are used to define which of the scene's triangles that are rasterized to the buffer, including the total number of occluders, occludees, and other objects that are occlusion culled.

Example Scene Stats

This exercise only used a single view and the stats data provided. For your final scene, you would want to test more than one view and add additional occluders as needed to improve occlusion culling.

Soq_SceneViewAndOcclusionBuffer-1.png

Scene view compared to the software occlusion buffer visualization.

SOStats1.png

There are a couple of things to note in this stat output:

  • In Cycle Counters , a lot of time is spent on Process Time , Process Occluder Time , and Rasterize Time . All of these can be improved reducing the number of triangles that need to be rasterized in the buffer, leading to the next point.

  • In Counters , we want to pay attention to the Rasterized occluder tris . These triangles represent the Static Mesh LOD that is specified as the occluder. There are 17 occluders currently being rasterized for a total of 3,055 triangles. Using lower LODs with fewer triangles will lower the processing time spent on them.

From these couple of stats, we've identified some areas where we can improve the performance of software occlusion by reducing the number of triangles that need to be processed. You can do this by using the Static Mesh Editor to generate your own LODs with fewer triangles. In this example scene, the majority of content is taken from the Infinity Blade: Grass Lands content pack, with the average occluder Static Mesh being around 2000 triangles. After setting up some new LODs and assigning them as the LOD for Occluder Mesh, we get the following stat results:

SOStats2.png

The last couple of stats you want to pay attention to are the Total occludees , Culled , and Total occluders . These stats tell us how well software occlusion is performing, by showing the number of objects culled, the total number of occluder objects, and the number of occludees currently visible. You can compare these to get an idea of where you can make improvements.

SOStats3.png

If we break it down, we have a total of 951 objects that can potentially be culled from this current view. Of those potential objects, 406 of them have been culled by the 17 occluders in this view. That means that those 17 occluders are occlusion culling approximately 43% of the objects that can be occlusion culled. Note that small occluders won't be much help in blocking other objects. Only use medium to large-sized meshes as occluders to keep performance reasonable while culling the most objects.

To improve the number of culled objects, set up additional occluders to block parts of the scene. Use the buffer visualizer to get a sense of what is being blocked from the current camera position while checking the stats in different locations in your level.

Help shape the future of Unreal Engine documentation! Tell us how we're doing so we can serve you better.
Take our survey
Dismiss