Nanite Virtualized Geometry

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

Choose your operating system:

Windows

macOS

Linux

Nanite is Unreal Engine 5's 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.

Example Scenes with Nanite

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.

Differences Between a Nanite Mesh and Static Mesh

A Nanite mesh is a Static Mesh with Nanite enabled on it. 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 an especially 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

  • Casts shadows using Virtual Shadow Maps

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. Typically these exceptions are rare and performance loss for using Nanite with them is fairly minimal so the recommendation is to not be overly concerned about where Nanite shouldn't be enabled if Nanite supports the use case.

Some use cases are not supported by Nanite currently. 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:

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 us with Nanite, check the box for Build Nanite.

Nanite FBX Import Options

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

When this property is enabled, highly detailed geometry adds significant time to importing and building of Static Mesh data. The property also adds an additional UV channel, which includes a significant amount of data for very dense meshes. If your project doesn't require baked lighting, there's no need to incur either cost.

Enabling Nanite on 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.

Enabling Nanite on Meshes in Batches

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

Enable Nanite on Batches of Asset in the Content Browser

Enabling Nanite on Individual Meshes

Open the editor of any mesh that supports Nanite, such as Static Meshes and Geometry Collections (Chaos physics-driven fracture meshes) and enable Nanite through the Details panel.

In the Static Mesh Editor, locate the Nanite Settings and check the box for Enable Nanite Support.

Enable Nanite in the Static Mesh Editor

In the Geometry Collections Editor, locate the Nanite section and check the box for Enable Nanite.

Enable Nanite on Geometry Caches

Supported Features of Nanite

This section describes how best to work with Nanite in an Unreal Engine project with details on what is and is not supported and possible limitations.

Geometry

Nanite can be enabled on Static Meshes and Geometry Collections.

A Nanite-enabled mesh 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, which represent greater than 90% of the geometry in any typical scene. 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 is not supported, but not limited to, the following:

  • Skeletal animation

  • Morph Targets

  • World Position Offset in materials

  • Spline meshes

Nanite meshes 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 hard-locked to 16 million instances, which includes all instances that are streamed in, not just ones enabled for use with Nanite. Only instances streamed in are counted towards the total.

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. This difference in tangent space using this approach could cause discontinuities at edges. However, this particular issue has not shown to be significant, and there are plans to support vertex tangents in a future release.

Materials

Nanite supports materials which have their Blend Mode set to Opaque. Other material types are disallowed or will have no effect on Nanite meshes when used.

When an unsupported material is detected, a default material is assigned and a warning is placed in the Output Log with additional information.

The following is a sampling of unsupported Nanite Material features:

  • Blend Modes using Masked or Translucent

  • Deferred Decals

    • Using a Nanite mesh for a Mesh Decal.

    • Nanite supports having a decal projected onto its surface.

  • Wireframe

  • Two Sided

  • Pixel Depth Offset

  • World Position Offset

  • Custom Per-Instance Data

Using the following in a Material applied to a Nanite-enabled mesh will cause the mesh to appear visibly broken:

  • Vertex Interpolator node

  • Custom UVs

Rendering

The following rendering features are not currently supported:

  • View-specific filtering of objects using:

    • Minimum Screen Radius

    • Distance culling

  • 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 (fallback 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 12:

  • NVIDIA: Maxwell-generation cards or newer

  • AMD: GCN-generation cards or newer

  • All newer version of Windows 10 (newer than version 1909.1350) and Windows 11 with support for DirectX 12 Agility SDK are supported.

    • Windows 10 version 1909 — The revision number should exceed or be equal to .1350.

    • Windows 10 version 2004 and 20H2 — The revision number should exceed or be equal to .789.

    • DirectX 12 (with Shader Model 6.6 atomics), or Vulkan (VK_KHR_shader_atomic_int64)

  • Latest Graphics Drivers

PlayStation 4 and Xbox One also support Nanite, but support on these platforms is currently considered experimental. It is expected that the performance of Nanite on these platforms with very high fidelity content may not meet the requirements of a shippable game.

Nanite Fallback Mesh and Precision Settings

Static Meshes include additional properties that control the precision of the Nanite representation and the coarse representation generated from the full-detail mesh (called a Fallback Mesh).

These settings are located in the Static Mesh Editor Details panel under the Nanite Settings section.

Static Mesh Editor Nanite Settings

Nanite settings include the following properties:

Property

Description

Position Precision

Choose the precision this mesh should use when generating the Nanite mesh. Auto determines the appropriate precision based on the size of the mesh. The precision can be overridden to improve precision or optimize disk footprint.

Minimum Residency

Sets the memory byte size this mesh should always keep in memory, and has the rest streamed in. Higher values require more memory, but for some meshes, this can mitigate streaming pop-in issues from occurring.

Keep Triangle Percent

The percentage of triangles to keep from the source mesh. Reduce this percentage to optimize disk size.

Trim Relative Error

Sets the maximum amount of relative error that is allowed to be removed for the Nanite mesh. All detail in the source mesh with less visual impact than this relative error amount is removed. The relative error does not have a unit size and is relative to the size of the mesh. By default, Nanite stores all of the original source mesh's triangles.

Fallback Triangle Percent

Sets the percentage of triangles that remain when reducing the source mesh for Nanite. This becomes the coarse representation (or Fallback Mesh) used when the full detail Nanite data cannot be, such as platforms which do not support Nanite rendering, or when it is impractical to use Nanite data like with complex collision.

Fallback Relative Error

Sets the maximum amount of relative error that is allowed to be removed for the Fallback Mesh. All detail in the generated Fallback Mesh with less visual impact than this relative error amount is removed. The relative error does not have a unit size and is relative to the size of the mesh.

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. By default, Auto picks the appropriate precision based on the size of the mesh and its triangle density. You can manually override by selecting a precision size to improve precision or optimize disk footprint.

Static Mesh Editor Nanite Settings for Position Precision

Qantinization is a form of lossy compression. Lossy compression is particularly challenging when working with modular mesh pieces, or other meshes that have shared boundaries. Especially when those boundaries need to align perfectly to not introduce holes or cracks in the geometry.

To ensure consistency, 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 center is a multiple of that precision.

Trimming data

There are times when you'll need to reduce the amount of data Nanite stores to optimize for disk size. Nanite includes settings which allow you to trim the detail data from a stored Nanite mesh at any time during production, meaning that you can safely overshoot quality up front and adjust accordingly later on.

To trim the detail data, you will want to use the Keep Triangle Percent and Trim Relative Error properties. You can think of them like a pre-decimate option before being stored as a Nanite mesh. In Nanite's case, detail doesn't need to be uniform across the mesh. It removes the least significant data first and is more akin to lossy compression.

Use Keep Triangle Percent to set the percentage of triangles to keep from the source mesh.

Use Trim Relative Error to set the maximum amount of relative error that is allowed when trimming the data from the source mesh. Any triangle that if removed would incur a relative error less than this amount is removed. Or another way to think about this is all detail with less visual impact than this value is trimmed. Relative error does not have a unit size and is relative to the size of the mesh.

The defaults for both of these properties are such that nothing is trimmed by default, and Nanite stores all of the original source mesh's triangles.

Trimming data is important to reducing disk size (in other words, download size), not for improving performance. See Data Size section below for more on this topic.

Fallback 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 of the highly detailed mesh that is accessible and used where Nanite data cannot be. The Fallback Mesh is the generated mesh used when Nanite rendering is not supported. It is also used in situations where it wouldn't be ideal to use the full-detail mesh, like when complex collision is needed, using lightmaps for baked lighting is required, and for hardware ray tracing reflections with Lumen.

The Fallback Triangle Percent property represents the percentage of triangles from the original source mesh that are used to generate the coarse representation. You can specify the percentage of triangles to keep between 0 and 100 percent, where large percentages keep more of the original mesh's detail.

The Fallback Relative Error sets the maximum amount of relative error that is allowed when removing details from the source mesh. Any triangles that if removed would incur a relative error less than this amount are removed with detail of less visual impact being first to go. The relative error does not have a unit size and is relative to the size of the mesh.

For example, if you wanted your mesh to not have any decimation at all, you would use a Fallback Triangle Percentage of 100 and a Fallback Relative Error of 0.

In the comparison below, there is the highly detailed Nanite mesh created from the original source mesh which is compared with default settings of a generated Nanite Fallback Mesh.

High Poly Nanite Mesh

Nanite Generated Fallback Mesh | Default Settings

Use the Fallback Relative Error to specify how much of the original detail is retained from the original source mesh, and the Fallback Percentage to set how much of that detail is used.

In the comparison below, the Fallback Mesh keeps 100 percent of the Fallback Triangle Percent but adjusts the Fallback Relative Error to use more of the triangles from the original source mesh. When adjusting these values, you can use the Nanite details for Nanite Triangles in the viewport as an indicator when changing their values.

Nanite Generated Fallback Mesh | Default Settings

Nanite Generated Fallback Mesh | Adjusted Settings for Quality

Fallback Mesh Visualization

In the Static Mesh Editor, you can toggle between the fully detailed Nanite mesh and the Nanite Fallback Mesh using the viewports Nanite Fallback option in the Show dropdown menu. Alternatively, you can use the hotkey Ctrl + N to quickly toggle between the two visualization options.

Static Mesh Editor Nanite Fallback Mesh Toggle

Using Custom Fallback Mesh LODs for Nanite-enabled Meshes

The Fallback Mesh is used for engine features, such as complex per-poly collision, ray tracing, light baking, and so on. It is also used for platforms which do not support Nanite. When generating the Fallback Mesh, a Nanite-enabled mesh always uses the LOD0 slot of the source mesh for auto-generating the fallback mesh. However, there are times when it is desirable to use a manually specified fallback mesh, or a series of traditional LODs, rather than an auto-generated one.

This level of control would allow you to use Nanite in a project but also directly control the geometry seen in ray-traced reflections, or on platforms which do not support Nanite.

Follow the steps below to specify your own custom fallback mesh, or to use a series of LODs:

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

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

  3. Use the LOD Import dropdown to Import LOD Level 1 from the LOD Settings section.

  4. Set the Minimum LOD to 1 under the LOD Settings section. This causes the Nanite-generated Fallback Mesh to be ignored.

Complex Collision presents a special case. Use the LOD for Collision property under General Settings to specify which LOD should be used for collision. Any LOD can be used for collision, including LOD0.

This particular approach may not be feasible to make Nanite projects automatically compatible with non-Nanite-supporting platforms, and should be tested and evaluated for your project.

Nanite efficiently handles 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 this in your project for feasibility using the r.Nanite 0 to toggle Nanite support off and on.

See the Console Variables and Commands section of this page for more information.

Performance and Content Issues

In most cases, Nanite scales extremely well within screen resolution. It does so based on two techniques: fine-grained level of detail and occlusion culling. Typically this means, regardless of geometric complexity of the source data in the scene, the number of triangles Nanite attempts to actually draw to the screen is consistent 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.

However, there are some cases of content that breaks 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 will not render faster than the traditional rendering pipeline. It only means that for this type of content, scaling with pixels — and not scene complexity — no longer applies to them. Use the Profiling features provided by Unreal Engine to monitor these types of situations when they occur.

Aggregate Geometry

Aggregate geometry is geometry that has many disjointed parts that become a volume in the distance, such as hair, leaves on trees, and grass. This type of geometry breaks the level of detail and occlusion culling techniques of Nanite.

Nanite 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. For continuous surfaces, this works well, but not for aggregate geometry that from a distance appear more like a partial opaque cloud than a solid surface.

As such, Nanite is more likely to determine it cannot reduce aggregate geometry nearly as aggressively as it would typical solid surfaces, thus resulting in more triangles being drawn for the same number of pixels covered.

Another optimization that aggregate geometry breaks is Occlusion Culling. Although it 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 block 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. 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 causing problems with occlusion culling, but even then, it 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 will not run well, but using Nanite for the tree trunks and branches might. Although, if you had Ivy on the side of a building, it might work well because there is only one layer before that solid surface behind it.

It is good to experiment with different use cases and see what works well for your projects. Use profiling tools 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 limitations. The fine-grained nature of occlusion culling with Nanite makes it possible to use these types of workflows during development with less concern.

As is explained in the Aggregate Geometry section above, overdraw can come from hidden surfaces being very close to visible surfaces below them. 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 cost. However, when there is stacked geometry that is close together near the top-most surface, Nanite is not able to determine which is on top or bottom, causing both to be drawn simultaneously.

This particular issue with culling 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 look fine while close to the surface, farther distances away can cause the difference in distance to be smaller than a pixel, resulting in overdraw.

Game View

Many Nanite instances closely stacked together

In the example below, if the camera is moved to look downward on the area where the character is standing, the Nanite Overdraw visualization shows how these stacked surfaces are being rendered. Brighter areas indicate more overdraw is happening in those areas than others.

Nanite Overdraw Visualization

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

Faceted and Hard-edge Normals

One issue to be mindful of is when importing highly detailed meshes that have faceted normals, meaning that the normal between two different polygons was not smoothed. This issue is common and easy to miss and caution should be taken to avoid this particular issue 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 should be less than the number of triangles it has. If the ratio is 2:1 or higher, then there is likely a problem, especially if this results in a high triangle count. Having a ratio of 3:1 means the mesh is completely faceted where every triangle has its own three vertices, none of which are shared with another triangle. Most often, this is caused by the normals not being the same because they are not smoothed.

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

For example, In the two meshes below, the mesh on the left has faceted normals while the one on the right has smoothed normals. When comparing these using the Nanite Triangles visualization, there are noticeable differences in the number of triangles used by Nanite to draw them. The faceted one on the left draws significantly more triangles than the smoothed one on the right.

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 a 4k Normal Map

High Poly Static Mesh | with a 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

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.

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.

Nanite Visualization Menu in the Viewport

The Overview visualization displays the rendered scene in the center of the image with select Nanite visualizations around the screen for reference.

Nanite Overview Visualization

The following Nanite visualization modes are available to choose from:

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 visualizations mode that enables additional visualization options in the Nanite Visualization menu. These visualizations are useful for programmers who are debugging or profiling various low level aspects of Nanite.

Enable this advanced visualization mode with the console variable r.Nanite.Visualize.Advanced 1.

Auditing Nanite Content

Some features of Unreal Engine are not yet supported by Nanite, while some may never be supported. The Nanite Tool enables you to perform an audit of available Nanite-supported assets in a single window. You can audit assets in your Content Browser to find errors or opportunities to optimize them by disabling or enabling Nanite for them.

Open the Nanite Tools window from the main menu by selecting Tools > Nanite Tools.

Nanite Tool Window for Auditing Assets

The Nanite Tools window displaying Static Meshes that will cause errors with Nanite.

When you open the Nanite Tools window, there are two tabs:

  • The Errors tab displays any Nanite-enabled Assets that are known to currently cause an error with Nanite, such as ones that have materials applied which do not support Nanite.

  • The Optimize tab filters Nanite-supported Assets in your project by the number of triangles they have and whether to exclude Assets that are using unsupported materials.

To evaluate how Nanite should proceed with errors or optimization, you'll need to perform an audit for each.

Nanite Tools: Errors

The Errors tab is helpful to quickly identify unsupported material types that are applied on Nanite-enabled Assets. For projects that are converting their project to use Nanite, such as using the batch selection method, the Errors tab would display any unsupported Nanite Assets after performing an audit.

Nanite Tool Errors Tab

To start an audit of Nanite-enabled Assets in your project, click on the Perform Audit button.

Nanite Tools Perform Asset Audit

During the audit, any materials from the Material Errors that are enabled on Nanite Assets will generate an error that is captured in the list of assets.

Nanite Tool Errors Material Errors Filter

This Nanite Mesh Errors list displays the name of any offending asset, the number of triangles it has, the number of instances used in Levels, and the number of errors it is generating.

Nanite Tools Audited Assets Error List

With the compiled list, you can decide whether to leave it enabled with Nanite or batch disable any that are selected using the Disable Nanite button in the bottom-right of the window.

Nanite Tools Window disable Nanite on Selected Assets

Nanite Tools: Optimize

The Optimize tab is helpful to quickly identify Nanite-supported Assets beyond a specified triangle count that are not using one of the unsupported material types that do not currently have Nanite enabled for them.

Nanite Tools Window Optimize Tab

Before performing an audit, consider setting the Triangle Threshold under the Geometry Filters if you need to convert Assets with fewer triangles than the default amount.

Nanite Tools Optimization Triangle Threshold filter

Start an audit of the project for any Assets that do not have Nanite enabled by clicking on Perform Audit.

Nanite Tool Optimize tab Perform Asset Audit

Any non-Nanite Assets that fit the criteria of the filter is displayed in the Non-Nanite Meshes list.

Nanite Tool Optimize list of Non-Nanite Meshes

You can decide which Assets in this list you want to enable Nanite on by clicking Enable Nanite.

Nanite Tools Optimize Enable Nanite on Selected Meshes

Console Variables and Commands

The following stats and console variables are available for use in debugging and configuring Nanite.

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

Nanite Fallback Rendering Modes

Nanite provides fallback 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 fallback meshes, or screen space-driven LODs, if set. This includes the recognition of Min LOD in the Static Mesh Editor properties (described in the Fallback Mesh section above).

  • 1 disables all rendering of Nanite-enabled meshes.

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

The Fallback render modes 1 and 2 are useful for scenes that have far more instances than could possibly be supported without Nanite. They allow the scene to be opened in the editor on non-Nanite-supporting platforms.

For example, in the Unreal Engine 5 Valley of the Ancients sample project, disabling Nanite would cause there to be tens of thousands of regular draw calls happening, making it difficult to open the map on a non-supporting platform.

Nanite Stats Command

The command Nanitestats adds an overlay of Nanite culling statistics to the top-right of the viewport. Nanite on-screen statistical display

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

Use Nanitestats List to show all available views in the debug output:

  • Primary

  • VSM_Directional

  • VSM_Perspective

  • ShadowAtlas0

  • ShadowAtlas1

  • ShadowAtlas2

To select a view, enter the command followed by the argument you want to view. For example, enter Nanitestats VSM_Directional to display its stats.

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

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.

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

You can specify the maximum number of candidate and visible clusters used in a single pass with the console variable r.Nanite.MaxCandidateClusters and r.Nanite.MaxVisibleClusters. Their values are used for sizing intermediate buffers and their default values have been chosen to work for common rendering scenarios.

There is no mechanism for dynamically resizing either of these buffers, or automatically scaling down quality on overflow, which 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 conservative bounds for candidates and visible clusters. More specifically, 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.