How to reduce foliage performance cost in large open world levels (UE5)?

Hi everyone,

I’m currently working on a large open-world environment in Unreal Engine 5.3, and I’m using a lot of foliage (grass, bushes, trees). I’m starting to notice major FPS drops in areas with dense vegetation.

I’d like to ask:

  1. What are the best practices to reduce foliage rendering cost?
  2. Should I be using Hierarchical Instanced Static Meshes (HISM) or Nanite foliage, or both?
  3. Are there any settings I should tweak in the foliage tool or project settings?

Any tips, suggestions, or documentation links would be greatly appreciated.
Thanks in advance!

Hi @Sharma,

Yeah, foliage can be very difficult to optimize.

I’m going to start with the questions of Nanite vs HISMs. Most likely, you’ll want HISMs, but I’m going to break down the reasoning and explain how to optimize both.

Using Nanite
Nanite eats performance when there are areas with a lot of overdraw. This is what makes Nanite so bad with foliage, since every masked leaf adds to that overdraw, and a lot of small overlapping grass does too. If the rest of your level needs to be Nanite, however, then you should use Nanite. Not using Nanite there would be like ordering a $50 plate of food and only eating half of it. You’re already paying for the upfront cost of Nanite, and changing half of your assets to non-Nanite won’t help you at all. If you are going to use Nanite foliage, the best thing you can do is cut out as much alpha masked space as possible. This means closely matching the geometry to the leaf/grass planes and ideally turning off Masked altogether. With Nanite, more triangles can honestly be better, so you don’t have to worry about the added tris. Now, Nanite has the added problem of being limited with distance culling. Distance Cull Volumes don’t work with Nanite meshes, so you’ll need to make sure your foliage is using the foliage tool / instancing, as this allows them to be distance culled. For non-instanced meshes, you can convert them to packed level actors to give them access to distance culling. And that’s about it. The key with Nanite is to reduce as much overdraw as possible. So, the more accurate the geometry and the less small tris are close together, the better your performance will be. It’s important to note too that using WPO for things like wind effects can tank performance in Nanite. Make sure to set a “WPO Disable Distance” in your instances to turn off WPO at a distance to help with this.
Remember too that Nanite is meant to be used in conjunction with next-gen features such as Virtual Shadow Maps and Lumen- both of which have their own complex optimization problems. This is the biggest misconception with Nanite- it’s not a switch that magically makes your project more performant. It’s a completely new rendering method that requires the proper time and care to set it up properly. In general if you choose to use Nanite, make sure to use the debug visualization tools and learn what they visualize and how to optimize them. This video is a great aid in that.

Using HISMs
If the rest of the geometry in your world is relatively well game-optimized, then you’re going to have better luck using the traditional instances. This means disabling features like Nanite and Virtual Shadow Maps altogether. This video contains some great tricks to help performance with traditional rendering

Some general notes to help performance:
Shadows are a huge tank on performance, especially with foliage since there’s so many shadow calculations in such a small area. You should be able to disable shadows on your grass with little to no visual difference.

I dont know to much about Foliage and its settings, but i do know that i fixed my issues with foliage by turning of translusentcy for foliage in distance and using Nanite. With these settings i was able to make my High Poly grass good looking, reduce lags and Fps drops and still using an WorldPossitionOffset for Animation in thr textures.