Performance hit of foliage


If I draw foliage on my terrain - a single mesh, and around 50k instances - performane takes a significant hit and my game ‘stutters’.

If I look at games like Horizon Zero Dawn or especially Red Dead Redemption 2, I can see what must surely (?) be more than 50k instances. RDR2 has fantastic landscapes of grass, some places as far as the eye can see. In contrast, in UE4 I get stuttering when I have painted a relatively small patch.

Am I doing something wrong with my foilage? Are there ‘best practices’ for increasing performance?

One thing that I do not quite understand is that I read that all instances of a foliage type will be drawn with a single draw call - that implies that the slowdown is not a rendering issue. So I have checked and in the foliage settings, it is set to static and not movable.

Any ideas?


The slowdown is generally on the GPU, based on the high amount of quad overdraw and/or pixel overdraw with transparency.

If you read pretty much any foliage article/workflow in the last 2 years, you’ll see the common workflow of trading transparency for more geo, or going full geo at the expense of more detailed shapes(i.e. single triangle grasses). However, none of them touch on another option, which Horizon uses. You can calculate your transparency in the pre-pass depth shader, which is a cheaper shader overall, and you negate all pixel cost in the Base Pass. A smaller version of the cost does shift over to the pre-pass, which if it’s too slow I believe will delay the rest of the frame that rely on it. The pre-pass can be bloated by triangle count, but in my own tests it seems like if you have the middle ground of transparency vs triangles, you’re fine.

You can enable it in the project settings, something like “masked materials in depth pass.” Anyone else more familiar with the pre-pass should correct me though :slight_smile:

You also have to consider the dynamic shadow cost as well. Most games disable shadows on grass because of the amount of triangles in the shadow map from grass alone. Horizon used custom shadow meshes for each LOD, which Unreal doesn’t support at the moment. BUT, you can use a single LOD for all shadows though. Contact Shadows work fairly well too, if you can ignore the noise.

Thanks for the suggestions, I will keep them in mind and see what I can tweak and how it affects the performance.

If you have access to GDC vault there is good video version of that also.

Thanks Kalle, I will give that a read.