Vegetation Generation in Ghost Recon Wildlands

Technical artist Maximilien Cleda showed how the team at Ubisoft approached the procedural vegetation in Ghost Recon Wildlands.

Technical artist Maximilien Cleda showed how the team at Ubisoft approached the procedural vegetation in Ghost Recon Wildlands. You can find the previous articles about landscape and city generation on Please share if you found this post useful.


I’m Maximilien Cleda, I have been technical artist on Ghost Recon Wildlands since the beginning of the project, 5 years ago. I first started at Ubisoft 8 years ago. It was my first job after my graduate studies. I’ve worked on several games such as Assassin’s Creed multiplayer, Red Steel 2 and Ghost Recon Future Soldier.

On this production I was in charge of the vegetation in the game, from the asset production to the world building and performances on all platforms.

In parallel to that, I’ve worked on other natural parts of the game such as farm fields, lakes, rivers, terraforming and helped the world building team on camps and villages.


We have 2 systems working together. The grass system that spawns different patterns depending of the terrain splatting and a Houdini tool that gives us a lot of possibilities to spread bushes and trees on top of it.

It’s a pretty simple concept to spread trees and bushes. It’s basically a “cascade” of vegetation: big trees (red) spawn medium trees (green), which spawn small trees and bushes (blue).

To add complexity, we first tweak density, scale, slope, space between assets etc. Then we add another layer to the rules with sun direction, which species on which material splatting, material inclusion/exclusion such as flow maps, river beds, cliffs etc. And finally we can combine several rules with a delete threshold between them. Roads, railway, water area and footpath are removed automatically.

We worked closely with the terrain/rock artists to match material repartition rules and vegetation rules. This created another layer of complexity. This way, the amount of “vegetation friendly” material, rocks and flow maps directly affected the way a forest would look at the end.

On the asset side we tried to have different “steps” of the same species, and avoid having too many different species per rule. It was more natural and memory friendly. The more species you use, the more difficult it becomes to have something realistic and natural.

On the performance side, density was an issue. The solution we came with was: instead of having a fixed LOD distance per asset, we decided to be more organic and modulate those values depending of vegetation density.

So the same asset may have different LOD values depending of its position in the world. More density means more aggressive values and a quicker switch to the last LOD, which is the Imposter.

Imposters are the last important part to build such big forests, visible from long distances. It’s a dynamic billboard system that allows different side views of a tree depending of the camera angle.

It’s generated inside the engine so we don’t have any mismatch between the 3D model and the imposter. And it contains different channels to allow complex shading, such as keeping light direction, fake shadowing and translucency.

1 of 2

Looking for an inspiring team, challenges & new perspectives?

Maximilien Cleda, a Technical Artist

Interview conducted by Kirill Tokarev

Follow on Facebook, Twitter and Instagram


Join discussion

Comments 3

  • John

    Hello Max,

    Thanks for the answer, it gives very incredibly useful details, and in my opinion it adds a lot to the article!

    The article's density based LOD/Imposter choosing along with the answer, gave me some ideas that I'll implement in some vegetation system I am currently working on.

    However on the rendering side I would still have a question, if it is not asking for too deep details of course. Are the grass instances generated on the CPU drawn on the GPU with the standard instancing (like dx11 SV_InstanceID) or maybe you are using SRV's with vertex instancing? Basically i'm asking for some details related to the batching of the grass draw commands sent to the GPU.

    I know that this is maybe not a question for the technical art department, it's more like a graphic programming question so there's no requirement to answer it, you already provided a ton of details.

    Again, thanks a lot for the ideas, looking at how AAA studios do their stuff is really inspiring! Keep up the good work!



    ·6 years ago·
  • MaxShifty

    Hi John,
    The grass is a 100% real time procedural system with an in-house Slicing/Caching system on the CPU. Every calculations is done on the CPU.
    There’s a lot of constraints to be simple and cheap (CPU and GPU). No matrices are stored, we only choose Type/density/scale etc… and each preset is used to generate the grass in real time. 
    Imposters are also used on grass with really aggressive distances (High rez LOD only around the player, few meters), so at the end, 90% of the grass models are imposters. (GPU friendly, only quads). 
    On the rendering side, no shadows on most types, simple shader, optimized temporal fading between LODs, scale fading on the last LOD, and we use the lighting pass to color the grass to match the terrain color.
    I hope this answers your question a little.



    ·6 years ago·
  • John

    Hello! Reiterating the question from the 'city generation' at:

    I couldn't find the answer in the article (or am I missing it? If I do, don't hesitate to point it out).

    How did you managed to render all the grass vegetation? I am talking about the grass and small ground clutter and not the trees witch which you use the quite standard imposter technique.

    Standard SV_InstanceID instancing? Soft instancing (merge instancing) like: ? Old-school DX9 per-vertex instancing data? Any other technique for the small grasses / ground clutter?

    Thanks a lot, for the article, and looking forward for your response!



    ·6 years ago·

You might also like

We need your consent

We use cookies on this website to make your browsing experience better. By using the site you agree to our use of cookies.Learn more