Last week we looked at what Lumen costs you. Nanite is the other headline feature, and the advice around it is worse — because "just turn it on" sounds like it should be true.

Nanite is not free performance. It's a shift in where your performance goes. Understanding that one sentence tells you when to use it.

What it actually does

Nanite streams and renders geometry at roughly one triangle per pixel, so triangle count stops mattering. It uses a visibility buffer that records only triangle IDs first, and shades materials per-pixel only for visible geometry — which eliminates overdraw from the material cost. It also does two-pass occlusion culling: draw what was visible last frame, build a depth buffer, test the previously-occluded geometry against it.

The result: a 30-million-triangle rock costs about what a 30,000-triangle rock costs, and you never author an LOD.

The trade, stated plainly

Nanite shifts your bottleneck from geometry to materials and memory.

In traditional rendering, material complexity is one cost among several. Under Nanite, material cost becomes the primary concern. People report very large gains — in the range of 200–300% — simply from simplifying materials on distant foliage in big Nanite scenes.

So the question "should I enable Nanite?" is really "is geometry my bottleneck, or is it materials?" If you're a solo dev with modest meshes and expensive layered materials, Nanite gives you little and takes something.

Where Nanite clearly wins

  • High-poly meshes that would otherwise need aggressive LODs. Megascans rocks, cliffs, sculpted architecture, kitbash sets. This is the case the whole system was built for.
  • Landscape. Nanite can be enabled for landscape terrain, and it pairs well with Virtual Shadow Maps.
  • Anything where you'd otherwise spend a day authoring LOD chains. Your time is a resource too.

Where it clearly doesn't

  • Skeletal meshes, vertex-animated meshes, morph targets — historically not supported. Nanite Skeletal Mesh with animation LODs and animation banks has been arriving in newer versions, so check your engine version rather than a 2022 blog post.
  • Masked materials. Nanite was designed for opaque geometry. Support for masked blend modes came in 5.1+, but it must be enabled in Project Settings and configured correctly — and masked foliage still costs clusters at any distance.
  • World Position Offset. Limited WPO support arrived in 5.4+, opt-in, with restrictions on displacement magnitude. Artists have to set Max WPO Displacement for the worst case to pad culling bounds — and overly conservative bounds contribute to high overdraw cost. WPO also changes vertex shader logic, so each material bins into separate dispatches; many materials means many programmable raster bins, which is its own performance issue.
  • Ordinary game assets. Many developers report better performance without Nanite for typical, already-optimised meshes. The docs' claim that Nanite meshes render faster is specifically true for high-poly assets that would otherwise suffer.

Dense forests: the honest version

Nanite plus foliage is where the biggest disappointments live. Each leaf card still costs a cluster even at distance, and a dense forest blows through a reasonable cluster budget quickly. Nanite trees also compress worse than solid meshes with the same triangle count, so memory goes up.

stat Nanite shows your cluster counts. If it's high in a forest, the answer is fewer, better meshes — not a cvar.

If you're on 5.7+, Nanite Foliage is the real answer to this: voxelised distant foliage instead of alpha cards (zero overdraw at distance), Nanite Skinning for wind (per-bone, more accurate bounds, fixed-function rasteriser instead of programmable bins), and Nanite Assemblies to instance modular parts without duplicating geometry. It was experimental in 5.7 preview — check its status before betting a forest on it.

The debug views that answer the question

  • Overdraw — shows overdraw including masked-out pixels. Critical for foliage. It accounts for masked materials properly now.
  • Evaluate WPO — green means WPO is being used, which is expensive. Red means it isn't.
  • Raster Bins — reveals material batching. Many bins means overhead.
  • stat Nanite — cluster counts.

One rule of thumb worth borrowing from someone shipping foliage: keep Nanite cost under about 4 ms at any point in the game, measured at native 1080p / 60 FPS on an RTX 3060-class card. It's a rule of thumb, not a law — but it's a budget, and a budget beats a vibe.

Common pitfalls

  • Enabling Nanite on everything and not measuring. You moved your bottleneck without checking where it landed.
  • Complex materials on Nanite meshes. That's where your frames went now.
  • Profiling in the editor. Performance differs significantly from a packaged build.
  • Nanite mesh not rendering at all? Usually: Nanite not enabled on the asset, an unsupported mesh type (skeletal, morph targets), or a material blend mode Nanite doesn't take. Check those three before anything else.
  • Applying cull distance thinking to Nanite foliage. It doesn't respond to it — different system, as covered in the foliage post.
  • Reading a 2022 article as current. Masked support, WPO support, skeletal support and foliage have all moved. Check your version.

30-second recap

  • Nanite makes triangle count irrelevant. It does not make cost irrelevant.
  • The trade is geometry cost → material and memory cost. That's the whole decision.
  • Great for high-poly meshes, kitbash, landscape. Poor for typical optimised game assets.
  • Skeletal, morph targets, masked and WPO all have version-specific caveats. Check your engine, not a blog.
  • Dense Nanite forests eat clusters and memory. 5.7's Nanite Foliage is the real fix — verify its stability first.
  • stat Nanite, Overdraw, Evaluate WPO, Raster Bins. Packaged build.
  • Give yourself a millisecond budget and hold to it.

That's the Performance run done. Next Sunday we'll look at packaging your first shipping build — Development vs Shipping, cooked content, and the asset audit worth doing before you press the button.

— Marco