Nanite Virtualized Geometry

Overview of Unreal Engine 5's virtualized geometry system to achieve pixel scale detail and high object counts.

Windows
MacOS
Linux

nanite-combo.png

Nanite is Unreal Engine 5's new virtualized geometry system which uses a new internal mesh format and rendering technology to render pixel scale detail and high object counts. It intelligently does work on only the detail that can be perceived and no more. Nanite's data format is also highly compressed, and supports fine-grained streaming with automatic level of detail.

Benefits of Nanite

  • Multiple orders of magnitude increase in geometry complexity, higher triangle and objects counts than has been possible before in real-time

  • Frame budgets are no longer constrained by polycounts, draw calls, and mesh memory usage

  • Now possible to directly import film-quality source arts, such as ZBrush sculpts and photogrammetry scans

  • Use high-poly detailing rather than baking detail into normal map textures

  • Level of Detail (LOD) is automatically handled and no longer requires manual setup for individual mesh's LODs

  • Loss of quality is rare or non-existent, especially with LOD transitions

Although the advantages can be game-changing, there are practical limits that still remain. For example, instance counts, triangles per mesh, material complexity, output resolution, and performance should be carefully measured for any combination of content and hardware. Nanite will continue to expand its capabilities and improve performance in future releases of Unreal Engine.

How a Nanite Mesh is different from a Static Mesh

A Nanite mesh is still essentially a triangle mesh at its core with a lot of level of detail and compression applied to its data. On top of that, Nanite uses an entirely new system for rendering that data format in an extremely efficient way.

All that is required for a Static Mesh to take advantage of Nanite is a flag to enable it. Authoring content for Nanite is no different than traditional meshes except that Nanite can handle orders of magnitude more triangles and instances than is possible for traditionally rendered geometry. Move the camera close enough and Nanite will draw the original source triangles that were imported.

Nanite meshes support multiple UVs and vertex colors. Materials are assigned to sections of the mesh such that those materials can use different shading models and dynamic effects which can be done in the shaders. Material assignment can be swapped dynamically, just like any other Static Mesh, and Nanite doesn't require any process to bake down materials.

Virtual Textures are not required to be used with Nanite, but they are highly recommended. Virtual Textures are an orthogonal Unreal Engine feature with similar goals for texture data that Nanite achieves with mesh data.

Working with Nanite should be familiar to workflows for Static Meshes, but there are many things not yet supported. See the Supported Features section of this page for more details.

How does Nanite work?

Nanite integrates as seamlessly as possible into existing engine workflows, while using a novel approach to storing and rendering mesh data.

  • During import: meshes are analyzed and broken down into hierarchical clusters of triangle groups.

  • During rendering: clusters are swapped on the fly at varying levels of detail based on the camera view, and connect perfectly without cracks to neighboring clusters within the same object. Data is streamed in on demand so that only visible detail needs to reside in memory. Nanite runs in its own rendering pass that completely bypasses traditional draw calls. Visualization modes can be used to inspect the Nanite pipeline.

Since Nanite relies on the ability to rapidly stream mesh data from disk on demand. Solid State Drives (or SSDs) are recommended for runtime storage.

What Types of Meshes Should Nanite Be Used For?

Nanite should generally be enabled wherever possible. Any Static Mesh that has it enabled will typically render faster, and take up less memory and disk space.

More specifically, a mesh is a good candidate for Nanite if it:

  • Contains many triangles, or has triangles that will be very small on screen

  • Has many instances in the scene

  • Acts as a major occluder of other Nanite geometry

An example of an exception to these rules is something like a sky sphere: its triangles will be large on screen, it doesn't occlude anything, and there is only one in the scene.

Some use cases are not supported by Nanite for Early Access. See the Supported Features section of this page for more details.

Enabling Nanite Support on Meshes

Nanite can be enabled on supported geometry in the following ways: on import; by opening the individual mesh editors; and through batch selection in the Content Browser.

Converting geometry to Nanite requires some processing time for each mesh. On large projects, use of a shared Derived Data Cache (DDC) is especially helpful if there are many Nanite assets. Please refer to the Shared DDC documentation for more information.

Importing a Static Mesh

When importing a mesh intended for Nanite, check the box for Build Nanite.

nanite-importoptions.png

It's recommended to disable Generate Lightmap UVs property when not using precomputed lighting with Lightmass.

Highly detailed geometry can add significant time to importing and building Static Mesh data when it is enabled. The property also adds an additional UV channel, which can be a significant amount of data for very dense meshes. There is no need for either cost if your project doesn't require baked lighting.

Batch Selection and Individual Assets

In cases where you already have your project populated with content that you want to enable Nanite on, you have two options: enabling assets in batches using the Content Browser, or enabling individual assets through their own editors.

For batches of Static Mesh Assets that you want to enable Nanite for, use the Content Browser to select them, right-click, and choose Nanite > Enable.

nanite-batchenable.png

Alternatively, you can open Static Mesh Assets and Geometry Collections (Chaos physics-driven fracture meshes) in their respective editors and enable Nanite through the Details panel.

For Static Meshes:

nanite-staticmesheditor-enablesetting.png

  1. Open the Static Mesh Asset.

  2. In the Details panel under Nanite Settings, place a check next to Enabled.

  3. Press Apply Changes.

For Geometry Collections:

nanite-geometrycollections-enablesetting.png

  1. Open the Geometry Collection Asset.

  2. In the Details panel under Nanite, place a check next to Enable Nanite.

Supported Features of Nanite

The following sections outline how best to work with Nanite in your project in Unreal Engine 5 Early Access.

Geometry

Nanite can be enabled on Static Meshes and Geometry Collections.

A mesh with Nanite enabled can be used with the following Component types:

  • Static Mesh

  • Instanced Static Mesh

  • Hierarchical Instanced Static Mesh

  • Geometry Collection

Nanite is currently limited to rigid meshes. These represent greater than 90% of the geometry in any typical scene for projects and is the initial focus of Nanite development. Nanite supports dynamic translation, rotation, and non-uniform scaling of rigid meshes, but does not support general mesh deformation, whether it is dynamic or static. This means any position of a Nanite mesh in a way that is more complex than can be expressed in a single 4x3 matrix multiply applied to the entire mesh.

Deformation not supported includes, but is not limited to:

  • Skeletal animation

  • Morph Targets

  • World Position Offset in materials

  • Spline meshes

Nanite meshes also do not currently support:

  • Custom depth or stencil

  • Vertex painting on instances

    • This specifically means per-instance painted colors using the editor's Mesh Paint mode.

    • Vertex colors imported on the original mesh are supported.

The maximum number of instances that can be present in the scene is capped to two million instances. This includes all instances that are streamed in and not just ones enabled for Nanite. Only instances streamed in are counted. This is being actively improved for future releases of Unreal Engine.

Per vertex tangents are not stored from the Static Mesh when it is enabled for Nanite. Instead, tangent space is implicitly derived in the pixel shader. Tangent data is not stored in order to reduce data size. There is a difference in tangent space using this approach that could cause discontinuities at edges. However, this hasn't been shown to be a significant issue and supporting vertex tangent sis planned for a future release of Unreal Engine.

Materials

The following materials, with the following settings cannot be assigned to Nanite meshes. They will either be disallowed or will have no effect on Nanite meshes if used.

Unsupported materials will use a default material and place a warning in the Output Log with additional details.

  • Any Blend Mode besides Opaque

    • This includes Masked and Translucent blend modes

  • Deferred Decal

    • For example, using a Nanite mesh for Mesh Decals

    • Decal meshes projected onto Nanite meshes is supported

  • Wireframe

  • Pixel Depth Offset

  • World Position Offset

  • Custom Per-Instance Data

  • Two Sided

Materials that use the following will not render correctly when applied to a Nanite mesh and may appear visibly broken.

  • Vertex Interpolator node

  • Custom UVs

Rendering

The following rendering features are not currently supported:

  • View-specific filtering of objects using:

    • Scene Capture with:

      • Hidden Components

      • Hidden Actors

      • Show Only Components

      • Show Only Actors

    • Minimum Screen Radius

    • Distance culling

    • Anything filtered by FPrimitiveSceneProxy::IsShown()

  • Forward Rendering

  • Stereo rendering for Virtual Reality

  • Split Screen

  • Multisampling Anti-Aliasing (MSAA)

  • Lighting Channels

  • Raytracing against the fully detailed Nanite mesh

    • Ray Tracing features are supported but rays intersect the coarse representation (called a proxy mesh) instead of the fully detailed Nanite mesh

  • Some visualization view modes do not yet support displaying Nanite meshes

    Use caution with some visualization modes in the Static Mesh Editor when viewing highly detailed geometry. Viewing Normals and UV can cause problems with editor performance.

Supported Platforms

Nanite is currently supported on PlayStation 5, Xbox Series S|X, and PCs with graphics cards meeting these specifications, using the latest drivers with DirectX 11 or 12:

  • NVIDIA: Maxwell-generation cards or newer

  • AMD: GCN-generation cards or newer

Nanite Proxy Mesh and Precision Settings

Static Meshes include additional properties that control the precision of the nanite representation, and the coarse representation generated from the highly detailed mesh called the Proxy Mesh.

These settings can be found in the Static Mesh Editor Details panel under the Nanite Settings.

nanite-staticmesheditor-enablesetting.png

Vertex Precision

Nanite quantizes mesh vertex positions to maximize memory density and minimize disk footprint. The quantization step size is a power of two that can be selected to match the requirements of individual meshes using the Position Precision property. The default selection, Auto, lets Nanite pick an appropriate precision based on the mesh size and triangle density. The precision can also be manually overridden to improve precision or optimize disk footprint.

nanite-staticmesheditor-positionprecision.png

There will likely always be something to be gained by fine-tuning the precision manually. However, the intention is that the heuristics for Auto will continue to improve, that it will be an appropriate compromise, or at least be a good starting point for most meshes when considered in isolation.

Quantization is a form of lossy compression, and lossy compression is particularly challenging when working with modular mesh pieces, or other meshes that have shared boundaries. Especially if those boundaries need to align perfectly to not introduce holes, or cracks, in the geometry. To ensure consistency, the quantization happens in unnormalized object coordinates centered around the mesh origin. This ensures that the quantization never causes cracks when the mesh uses the same precision setting, and the translation between the mesh centers is a multiple of that precision.

Proxy Mesh

Many parts of Unreal Engine need access to the traditional vertex buffer provided by traditionally rendered meshes. When Nanite is enabled for a Static Mesh, it generates a coarse representation that is accessible and used where the highly detailed Nanite data cannot be. In those cases, the Proxy Mesh is the generated representation used, like when complex collision is needed or when a platform doesn't support Nanite rendering. The proxy mesh is also used in Lightmass if the mesh has baked static lighting.

The Nanite setting Proxy Triangle Percent represents the percentage of triangles from the original highly detailed mesh that is used to generate the coarse representation. The text field accepts values from 0 to 100, where larger percentages keep more of the original mesh's detail. A value of 100 indicates that no decimation is performed. The proxy mesh will be clamped to a minimum of 2000 triangles, no matter how small the proxy percent.

nanite-staticmesheditor-proxypercent.png

In cases where Nanite is enabled on a mesh that has fewer than 2000 triangles, the original mesh will automatically be used as the Proxy Mesh since the coarse representation percentage range used a hardcoded minimum of 2000 triangles.

In the Static Mesh Editor, you can toggle between the fully detailed Nanite representation and the generated Nanite Proxy Mesh representation using Show > Nanite Proxy or the hotkey Ctrl + N.

nanite-proxymeshtoggle.png

The comparison below shows the highly detailed Nanite representation of the mesh compared to the generated proxy mesh used when Nanite rendering isn't supported. This is an example mesh taken from the Unreal Engine 5 Valley of the Ancient Sample.

In Early Access, the the Triangles and Vertex statistics displayed in the Static Mesh Editor refer only to the proxy mesh, whether or not Nanite is enabled. To see the original triangle count, Nanite must be temporarily disabled on the mesh.

High Poly Nanite Mesh

Nanite Generated Proxy Mesh

Increasing the Proxy Triangle Percent restores a percentage of the original mesh's detail for the Proxy Mesh representation, which may be needed when platforms or features don't support Nanite rendering. The example below shows the original generated proxy mesh compared to a proxy mesh with a larger percentage of detail restored, and has approximately twice the number of triangles.

Nanite Proxy Mesh using a lower Proxy Triangle Percent

Nanite Proxy Mesh using a higher Proxy Triangle Percent

Using Custom Proxy Mesh LODs for Nanite-enabled Meshes

The proxy mesh is used for engine features, such as complex per-poly collision, ray tracing, light baking, and others. It is also used for drawing directly when running on platforms where Nanite is unsupported. In some cases, it may be desirable to use a manually specified proxy mesh, or series of traditional LODs for these purposes, rather than an auto-generated one. For example, this would allow you to directly control the geometry seen when running on unsupported platforms, or in ray-traced reflections.

A Nanite-enabled mesh always uses the LOD0 slot for the auto-generated proxy. To use a custom proxy, or series of LODs, follow these steps:

  1. Set the Proxy Triangle Percent to 0 so that the proxy is as small as possible since it will be ignored when using this approach.

  2. Add one or more LODs to the mesh using traditional LOD setup.

  3. Set the Minimum LOD to 1 under the LOD Settings in the Static Mesh Editor Details panel. This causes the Nanite-generated proxy to be ignored.

  4. Complex collision is a special case that needs to be set. Use the LOD for Collision property to specify the LOD to use for collision, which can be any of the LODs, including LOD 0.

Using this approach to make Nanite projects automatically compatible with non-Nanite-supporting platforms might not be feasible in all cases. Nanite can efficiently handle very large numbers of instances, but if Nanite is disabled, there could be an overwhelming number of draw calls for the traditional render pipeline. You can test disabling Nanite globally using r.Nanite 0. See the Console Variables and Commands section of this page for more information.

This workflow is still being actively developed and will improve in future releases.

Performance and Content Issues

In most cases Nanite scales extremely well with screen resolution. It does so based on two key techniques: fine-grained level of detail and occlusion culling. Typically this means, regardless of the geometric complexity of the source data in the scene, the number of triangles Nanite attempts to actually draw to the screen is fairly constant and proportional to the number of pixels. Nanite follows the design principle that there is no use in drawing far more triangles than there are pixels.

There are some cases where there are types of content that break Nanite's techniques it uses to scale, but this doesn't mean it should not be used at all for this content, or that it might not still be far faster at rendering it than the traditional pipeline. For this type of content, this means that scaling with pixels, and not scene complexity, may no longer apply for them. Using Profiling features of Unreal Engine should be used to monitor these types of situations.

Aggregate Geometry

Aggregate geometry means many tiny disjointed things that become a volume in the distance, such as hair, leaves, and grass. This breaks both the level of detail and occlusion culling techniques.

First, Nanite mesh is inherently a hierarchical level of detail structure that relies on being able to simplify small triangles into larger triangles and choosing the coarser one when it determines the difference is smaller than can be perceived. This works very well on continuous surfaces but not well on aggregates, that from a distance appear more like a partial opaque cloud than solid surface. As such, Nanite is more likely to determine it cannot reduce aggregates nearly as aggressively as it would typical solid surfaces, which results in more triangles being drawn for the same number of pixels covered.

The second optimization that aggregates break is occlusion culling. Although occlusion culling is very fine-grained, its granularity is not per pixel. Geometry that is filled with holes — and worse yet layers upon layers of geometry filled with holes — causes excessive overdraw because many depth layers need to build up before that area on screen will black anything behind it. One way to think about this is to consider an 8x8 pixel region on screen and how many depth layers need to be drawn before every pixel is filled in. This excessive overdraw means that for the same number of pixels covered, Nanite attempts to draw more triangles causing it to render slower.

Foliage is the most obvious case for this problem, but even then this does not mean that Nanite should not be used on foliage-type meshes at all. Forests filled with tree canopies made up of individually modeled leaves almost certainly won't run well, but using Nanite for tree trunks and branches might. Ivy on the side of buildings also might work well because there is only one layer before a solid surface behind it, in ideal cases. It's good to experiment and see what works well for your projects, and use profiling to confirm good performance from Nanite with these types of meshes.

Closely Stacked Surfaces

Occlusion culling with traditional meshes makes kitbashing workflows nearly impossible on a large scale due to practical limits. Nanite's fine-grained nature of occlusion culling makes it possible to use these workflows in development with less concern.

As was explained in the Aggregate Geometry section, overdraw can come from hidden surfaces being very close below visible surfaces. If any geometry is buried well below the visible surface, Nanite detects and culls it fairly cheaply, such that it can mostly be considered free of costs. However, if there is stacked geometry that is close together near the top-most surface, Nanite won't be able to determine which is on top or bottom, causing both to be drawn. This particular issue is a worst case scenario where Nanite does not know which surface is on top, and just draws all the layers instead. Imprecision like this scales with screen size and distance, so while 10 centimeters may separate layers and looks fine up close, farther distances away can have the distance difference be smaller than a pixel, resulting in overdraw.

This example from the Unreal Engine 5 sample project Valley of the Ancients shows how closely stacked surfaces can lead to lots of overdraw. The character's foot is shown for scale of how small of an area on screen this could end up using when at farther distances.

Game View

Many Nanite instances closely stacked together

Moving the camera to look down on the area where the character is standing and these stacked surfaces are, the Overdraw visualization can show how these stacked surfaces are being rendered.

nanite-overdrawvis.png

This visualization is the most effective way to find issues like these. While some amount of overdraw is expected, excessive amounts of it will result in Nanite culling and rasterization costs becoming higher and Nanite's scaling independently of scene complexity to be less effective.

Faceted and Hard-edge Normals

Importing highly detailed polygon meshes that have faceted normals is easy to do without noticing. Caution should be taken to avoid faceted normals because low amounts of vertex sharing in a mesh can become significantly more expensive both in rendering performance and data size. Ideally, the number of vertices for a mesh is less than the number of triangles. If the ratio is 2:1 or higher, then there is likely a problem, especially if the triangle count is high. Having a ratio at 3:1 means the mesh is completely facet where every triangle has its own three vertices, none of which are shared with another triangle and most often this is because the normals are not the same because they are not smoothed.

With that in mind, more vertices means more data. It also means more vertex transform work and ratios higher than 2:1 fall down some slow paths.Intentional use in hard surface modeling shouldn't cause issues and there is no reason not to use them. However, accidental 100% faceted very dense meshes are far more expensive than intended. Also, imported normals on dense organic-type surfaces generated in other DCC packages with hard normal thresholds that might be sensible on lower polygon meshes can add unnecessary expense with Nanite.

Take for example the two meshes below in the image on the left. The mesh on the left has faceted normals while the one on the right has smooth normals. Nanite's Triangles visualization shows the noticeable difference in number of triangles used to draw each of them.

Nanite-enabled meshes with faceted (left) and smoothed (right) normals

Nanite Triangle Visualization of Nanite-enabled meshes with faceted (left) and smoothed (right) normals

Click image for full size.

Click image for full size.

Performance of Typical Content

For comparison purposes, the following GPU timings were taken from the PlayStation 5 Unreal Engine 5 technical demo Lumen in the Land of Nanite:

  • Average render resolution of 1400p temporally upsampled to 4K.

  • ~2.5 millisecond (ms) to cull and rasterize all Nanite meshes (which was nearly everything in this demo)

    • Nearly all geometry used was a Nanite mesh

    • Nearly no CPU cost since it is 100% GPU-driven

  • ~2ms to evaluate materials for all Nanite meshes

    • Small CPU cost with 1 draw call per material present in the scene.

When considering these GPU times together, it's approximately 4.5ms combined for what would be equivalent to Unreal Engine 4's depth prepass plus the base pass. This makes Nanite well-suited for game projects targeting 60 FPS.

Numbers like these should be expected from content that doesn't suffer from the aforementioned performance pitfalls in previous sections. Very high instance counts and large numbers of unique materials can also cause increased costs and is an area of Nanite development that is being actively worked on.

Data Size

Because of the micro detail that Nanite is able to achieve, it might be assumed that it means a large increase in geometry data resulting in larger game package sizes and downloads for players. However, the reality isn't that dire. In fact, Nanite's mesh format is significantly smaller than the standard Static Mesh format because of Nanite's specialized mesh encoding.

For example, using the Unreal Engine 5 sample Valley of the Ancients, Nanite meshes average 14.4 bytes per input triangle. This means an average one million triangle Nanite mesh will be ~13.8 megabytes (MB) on disk.

Comparing a traditional low poly mesh plus its Normal map to a high poly Nanite mesh, you would see something like:

Low Polygon Mesh

  • Triangles: 19,066

  • Vertices: 10,930

  • Num LODs: 4

  • Nanite: Disabled

Static Mesh Compressed Packaged Size: 1.34MB

Nanite Mesh

  • Triangles: 1,545,338

  • Vertices: 793,330

  • Num LODs: n/a

  • Nanite: Enabled

Static Mesh compressed package size: 19.64MB

Low Polygon Static Mesh | with 4k Normal Map

High Poly Static Mesh | with 4k Normal Map

The compressed package size isn't the entire size of the asset though. There are also unique textures only used by this mesh that have to be accounted for. Many of the materials used by meshes have their own unique textures made up of different Normal, BaseColor, Metallic, Specular, Roughness, and Mask textures.

This particular asset only uses two textures (BaseColor and Normal) and thus is not as costly on disk space as one with many other unique textures. For example, note the size of the of the Nanite mesh with ~1.5 million triangles is smaller in size (at 19.64MB) than a 4k normal map texture is.

Texture Type

Texture Size

Size on Disk

BaseColor

4k x 4k

8.2MB

Normal

4k x 4k

21.85MB

The total compressed package size for this mesh and its textures is:

  • Low Poly Mesh: 31.04MB

  • High Poly Mesh: 49.69MB

Because the Nanite mesh is very detailed already we can try replacing the unique normal map with a tiling detail normal that is shared with other assets. Although this results in some loss in quality in this case, it is fairly small and certainly much smaller than the difference in quality between the low and high poly version. So a 1.5M triangle Nanite mesh can both look better and be smaller than a low poly mesh with 4k normal map.

Total compressed package size for the Nanite-enabled mesh and textures: 27.83MB

High Poly Static Mesh | with 4k Normal Map

Nanite Mesh | with 4k Detail Normal Map

There are plenty of experiments that can be done with texture resolution and detail normal maps, but this particular comparison is to demonstrate that the data sizes of Nanite meshes are not too dissimilar from data that artists are already familiar with.

Lastly, we can compare the Nanite compression to the standard Static Mesh format using the high poly, where both are identical at LOD0.

High Poly Static Mesh

  • Triangles: 1,545,338

  • Vertices: 793,330

  • Num LODs: 4

  • Nanite: Disabled

Static Mesh Compressed Packaged Size: 148.95MB

Nanite Mesh

  • Triangles: 1,545,338

  • Vertices: 793,330

  • Num LODs: n/a

  • Nanite: Enabled

Static Mesh compressed package size: 19.64MB

Comparing the Nanite compression from earlier with a size of 19.64MB is 7.6x smaller than the standard Static Mesh compression with 4 LODs.

Nanite compression and data sizes are a key area that will be improved in future releases of Unreal Engine.

General Advice on Data Size and a Look to the Future

Nanite and Virtual Texturing systems, coupled with fast SSDs, have lessened concern over runtime budgets of geometry and textures. The biggest bottleneck now is how to deliver this data to the user.

Data size on disk is an important factor when considering how content is delivered — on physical media or downloaded over the internet — and compression technology can only do so much. Average end user's internet bandwidth, optical media sizes, and hard drive sizes have not scaled at the same rate as hard drive bandwidth and access latency, GPU compute power, and software technology like Nanite. Pushing that data to users is proving challenging.

Rendering highly detailed meshes efficiently is less of a concern with Nanite, but storage of its data on disk is now the key area that must be kept in check. Outside of compression, future releases of Unreal Engine should see tools to support more aggressive reuse of repeated detail, and tools to enable trimming data late in production to get package size in line, allowing art to safely overshoot their quality bar instead of undershoot it.

Looking to the future development of Nanite, many parallels can be drawn to how texture data is managed that has had decades more industry experience to build, such as:

  • Texture tiling

  • UV stacking and mirroring

  • Detail textures

  • Texture memory reports

  • Dropping mip levels for final packaged data

Similar strategies are being explored and developed for geometry in Unreal Engine 5.

Visualization Modes

Nanite includes a number of visualization modes to inspect its data in the current scene.

In the Level viewport under the View Modes dropdown, hover over Nanite Visualization and choose from the selection.

Click image for full size.

For example, the Overview visualization displays the rendered scene in the center of the image and the individual visualization views around the screen for reference.

nanite-vis-overview.png

Other visualization modes include:

Nanite Visualization

Description

Mask

Visualization that marks Nanite (green) and Non-Nanite (red) geometry.

Triangles

Displays all triangles of the Nanite meshes in the current scene.

Clusters

Displays colored representations of all grouping of triangles being rendered in the current scene view.

Primitives

Visualization that colors components all the same color for all instances in an Instance Static Mesh (ISM).

Instances

Visualization that applies a different color for each instance in the scene.

Overdraw

Displays the amount of overdraw happening for scene geometry. Smaller objects that are closely stacked together create more overdraw than larger ones.

Material Complexity

Displays the complexity of the materials on Nanite geometry.

Material ID

Displays separate colors for each Material ID of individual Nanite meshes.

Lightmap UV

Visualization that displays the UV coordinates of Nanite mesh surfaces.

Nanite includes an Advanced mode that includes all available visualizations from the Level viewport's Show > Visualize menu. These additional visualizations are useful for programmers debugging or profiling various low level aspects of Nanite. This mode can be enabled using the console variable r.Nanite.Visualize.Advanced 1.

Console Variables and Commands

Debug and configure Nanite using the following stats and console variables.

Nanite rendering can enabled and disabled globally, at runtime, using the console variable r.Nanite 0. Disabling Nanite is a good way to emulate platforms where Nanite is unsupported.

Nanite Proxy Rendering Modes

Nanite provides proxy mesh rendering modes for when Nanite is either disabled or unsupported by a platform. You can control which mode is used with the console variable r.Nanite.ProxyRenderMode.

  • 0 is the default mode and falls back to rendering proxy meshes, or screen-space-driven LODs, if set. This includes the recognition of Min LOD in the Static Mesh Editor properties (described in the Proxy Mesh section above).

  • 1 disables all rendering of Nanite-enabled meshes.

  • 2 works similarly to mode 1 but allows the Show > Nanite Proxy visualization in the Static Mesh Editor to render a Nanite proxy.

Proxy render modes 1 and 2 are useful for scenes that have far more instances than could possibly be normally supported without Nanite, allowing the scene to be opened in the editor on non-Nanite-supporting platforms. For example, in the Unreal Engine 5 sample project Valley of the Ancients, disabling Nanite would cause there to be tens of thousands of regular draw calls, making it difficult to even open the map on a non-supporting platform.

Nanite Stats Command

The Nanitestats command, when entered into the console, overlays Nanite culling statistics on the right side of the screen for the current view.

nanite-nanitestats.png

Command arguments are used to specify what stats Nanite displays on screen. When no argument is provided, the primary view is used.

Nanitestats List produces a list of available views in the debug output:

  • Primary

  • VSM_Directional

  • VSM_Perspective

  • ShadowAtlas0

  • ShadowAtlas1

  • ShadowAtlas2

When selecting a view, enter the Nanitestats followed by the argument you want to use. For example, Nanitestats VSM_Directional.

For views that use two-pass occlusion culling, the statistics are split into separate buckets for Main and Post pass.

Statistic Name

Description

PRE-CULL

The number of instances before the culling pass.

POST-CULL

The number of instances surviving visibility tests.

NODEVISITS

Total number of hierarchy nodes visited during culling.

CANDIDATES

The number of clusters found during hierarchy traversal that need to be visibility tested.

CLUSTERSSW

The number of visible clusters rendered using software rasterization.

CLUSTERSHW

The number of visible clusters rendered using hardware rasterization.

Controlling Nanite Streaming Pool Size

Control the amount of memory dedicated to holding Nanite streaming data with the console variable r.Nanite.Streaming.StreamingPoolSize. Using larger pools reduces IO and decompression work when moving around the scene but at the cost of a larger memory footprint.

For Early Access, if the pool is not large enough to fit all the data needed for a view, cache thrashing can occur where streaming never settles even for a static view.

This console variable cannot be changed at runtime and must be specified in a configuration (.ini) file.

Setting Maximum Clusters in a Single Pass

Specify the maximum number of candidate and visible clusters used in a single pass with the console variables r.Nanite.MaxCandidateClusters and r.Nanite.MaxVisibleClusters. Their values are used for sizing intermediate buffers and their default values (8388608 and 2097152, respectively) have been chosen to work for common game rendering scenarios.

In Early Access, there is no mechanism for dynamically resizing either of these buffers, or automatically scaling down quality on overflow. This can result in rendering artifacts from them being too small for scene complexity, and typically manifesting as missing or blinking geometry. When these types of artifacts occur, use Nanitestats to determine a conservative bounds for candidates and visible clusters (look at the stats for CLUSTERSSW and CLUSTERSHW). The memory cost of a candidate cluster is currently 12 bytes and a visible cluster is 16 bytes.

This console variable cannot be changed at runtime and must be specified in a configuration (.ini) file.