Tutorial

Optimizing performance for imported scenes in Unreal Engine

Importing an entire scene built in a DCC like 3dsMax or Rhino is a common step in the visualization/simulation workflow. In most cases, these 3D models were originally built for design, or engineering purposes, meaning that the 3D data will first need to be prepared and optimized for use in a real-time engine.

The same goes when downloading models from online warehouses - you'll need to prepare and optimize the data to ensure it looks good and performs well in your environment. Throughout this process, use the console command "stat unit" to check performance.

Examples of optimizations Palatial runs on scenes to improve performance

Importing 3D data

When starting a new project in Unreal Engine, it's typical to pick a template project designed for what you're trying to build as the important settings (eg. software vs hardware ray-tracing) will be set up already. Before importing your Datasmith files, check that virtual texture support is enabled and that auto virtual texturing size is set to 1024 so imported materials and textures come with this setup - more on this below.

Before importing your 3D data, go to project settings > search virtual textures, and ensure all the relevant boxes are checked

Reducing lighting complexity

To check lighting complexity in your scene, go to view mode > optimization viewmodes > light complexity

In a nutshell, more is less. Inefficiently lit scenes will dramatically power performance, something you can check with the lighting complexity shader mode. Some quick wins for simplifying lighting include adjusting light attenuation to reduce overlap, replace clusters of overlapping point lights with a single area light, and turning off cast shadows when not needed.

Certain types of Vray and Corona lights aren't supported by Unreal Engine, and we've found that imported lights from Vray don't update until you recompile the lighting blueprint.

Lowering draw calls

A draw call is basically a command from the CPU to the GPU telling it what to render and how - basically what to draw on the display. Draw calls are computationally expensive, so you should aim to only have as many as necessary, and as few as possible.

If you have a lot of unique objects or materials in your scene, you'll probably have high draw calls, which lowers the overall responsiveness. As a benchmark, keep draw calls under 2000-4000 for desktop, and a few hundred at most for mobile. Merge unique meshes, replace duplicate materials/meshes, and take advantage of instancing (ISM/HISM).

Textures

Use virtual textures on textures above 512x512 when possible, so that the engine only renders the part that you see instead of the whole texture. This saves you from running out of video memory displaying details that aren’t visible. This step is best done before importing, however if you’re already past that, each texture will need to be set to enable virtual texture and all materials that use those textures will need their texture sampler types updated, otherwise they will fail to compile.

Materials

As with lighting, less is more. Minimize the use of materials that have animated textures, translucency or textures over 4k in resolution, such as full quality Megascans materials as they will increase shader complexity and lower performance. If exporting textures from a DCC using Datasmith, we recommend limiting texture resolution to 4M - this can be controlled via the Datasmith toolbar.

See box 3 for options to limit texture resolution when exporting from 3dsMax. Credit: Unreal Docs

Reducing the number of unique materials in a scene will help lower draw calls. This can be done by merging clusters of meshes with many materials into a single material and mesh using the merge actors tool, or replacing duplicate copies of materials often generated by Datasmith.

Lowering triangle count

This is only a problem if you're not using Nanite. Simplify meshes with imperceptible details such as dense, smooth surfaces to remove unnecessary triangles. Using modeling mode to do this will preserve more detail compared to using Nanite triangle percentage simplification. It's critical to generate LODs for all meshes - using the built in LOD group presets generally yield great results.

Setting up Nanite

Nanite is Unreal's virtualized geometry system that allows you to have basically unlimited triangle counts in a scene. It's not supported for translucent objects, but make sure it's turned on for everything else. Nanite will display the low-poly fallback mesh where it's not supported. For objects with mixed translucencies, detach translucent parts and setup LODs instead. See here for a blueprint that you can copy directly into your project.

Use the linked blueprint above to detach translucencies from objects before enabling Nanite

Foliage

Most foliage materials will be imported as a mix of translucent and opaque shading modes. Change translucent foliage materials to masked, enable Nanite, and turn on preserve area to ensure they render correctly at long ranges. If imported materials use world position offset (WPO) materials, this can be disabled or set to turn off at a distance to reduce shader complexity.

Changing translucent foliage materials to masked

Scene optimization can be time consuming and tedious - it's required when importing entire scenes, and should be done continuously through the development process. Palatial automates most of these steps so that complex pre-built scenes can be setup and prepared for pre-visualization in a few hours.

References

Managing complex architectural projects

You might also like

Tutorial
How to Better Import, Optimize, and Set Up Complex Assets in Unreal Engine
Tutorial
De-mystifying how to setup your Unreal Engine project

You might also like

Tutorial
How to Better Import, Optimize, and Set Up Complex Assets in Unreal Engine

Do you build immersive experiences?

If you want to test Palatial, we want to hear your feedback. Let's find some time in the calendar and get this party started.