I actually disagree with a lot of people here.
Nanite can be much faster than traditional rendering, once your game reaches a certain complexity.
First, the comparisons people are doing here are not fair. Spawning 100.000 Nanite meshes vs a single DrawIndirect call with 100.000 low poly meshes will most certainly result in better performance on the low poly part. But try to spawn 100.000 different meshes with Nanite and without, and suddenly the performance looks much different!
Nanite has a base cost of 2.5ms to rasterize and 2ms for material evaluation.
This is consistent across our game scene, independent of vertex count or object count.
That means for us as the developers we can throw as many objects in the scene as we want and the performance will not degrade. It doesn’t matter if these objects are high or low poly.
We can also stop wasting development time on creating LODs. Even better, we get completely seamless LODs for free!
This enables us to do other advanced stuff. Detailed destruction for example where you have a lot of fractured independent meshes, which would usually result in a lot of draw calls.
What really kills performance is Lumen and (if handled incorrectly) Virtual Shadow Maps.
Lumen is not production ready in my opinion. We tried to optimize it for our game and it took half of our frame budget. Even if you reduce the distant field resolution and remove reflections, the budget is just too high.
For virtual shadow maps the resolution is just way to high by default. Unreal sets it to a 16k texture per light. You can decrease this indirectly by setting the VSM LOD Bias to a value larger than -1.5. for our game a value of 0 was perfect. While it removed the pixel perfect shadows and blurred them a little bit, (comparable to traditional lighting) it gave us seamless shadow LODs and a rendering time of 1.2ms.
Still high! But it scales infinitely with no additional cost.
Also if you have a lot of moving vegetation or objects in the scene, it is better for you to create a separate shading pass in the material where the geometry is static, to prevent cache invalidations.
With this our total rendering time was at 2+2.5+1.2=5.7ms.
Then we had post processing, skeletal meshes and the rest… resulting in 8ms frame time.
Now the cool thing about the Nanite pipeline is that it can run in parallel to the game thread. Our game logic was around 5ms, but because it ran in parallel we had a total frame time of around 10ms.
And that is the rendering time from now on. No matter how many objects we throw at the scene, it will not increase!
100FPS with infinite detail and objects in the scene, real time lighting, no LOD production or popping. Nanite is absolutely production ready.
And now comes the surprise: before we activated Nanite we had a frame time of around 50ms, with a rendering time of 45ms. (GPU bound)
So 20FPS. Yes we didn’t have custom tailored LODs (only the pregenerated in unreal), as our production time and budget was limited at that point. We also had a lot of fractured geometry in the scene, as our game heavily relied on destruction.
And now we can put as much destruction in the scene as the CPU can handle. The GPU is not a limiting factor anymore, which is exactly what Nanite promised.