Procedural Vegetation System

I designed and developed a robust GPU-based vegetation system capable of handling thousands of plants efficiently in real-time.


Description

In small environments, the decoration is typically handled by artists or designers, enabling precise control and aesthetically pleasing results. Nevertheless, as the environment size grows, this approach becomes increasingly time-consuming and impractical. To address this challenge, procedural solutions are often used, offering significant time savings. In this context, I have developed a solution that implements best practices for efficiently distributing and rendering thousands of trees and small plants in real-time.

Features:

  • Procedural distribution: enabling plant placement and rendering in expansive scenarios exceeding 500x500km.
    • On-demand distribution just for visible areas;
    • Deterministic plant redistribution for revisited areas;
  • Global control for plant species: You can control the distribution of different plant species (oak tree, palm tree, cactus, grass) based on:
    • Pre-defined polygons that describe forests;
    • Placement near pre-defined lines like rivers;
    • Exclusion of undesirable zones such as lakes and roads;
    • Integration with manually designated placement zones within the pre-defined polygons;
    • Heightmap characteristics (slope, height) through adaptability curves;
    • Weather-related aspects (temperature, precipitation) using 2D input maps and adaptability curves;
  • LOD management and efficient rendering:
    • Individual LOD settings for each plant species to finely balance performance and visual quality;
    • LOD selection for each plant is efficiently computed compute-shaders;
    • Frustum culling for each plant is efficiently computed using compute shaders;
    • Maximum view range defined for each species;
    • GPU-instancing to reduces drastically the draw-calls (just 2*№_LODs draw-calls per specie);
  • Resource optimization:
    • Minimum CPU usage;
    • Minimum RAM<->VRAM data transfers;
    • No continuous memory allocation;
  • Physics integration:
    • On-demand spawn of colliders for plants close to characters;

Little or not explored:

  • Advanced lighting (subsurface scattering, GI, lighting bake);
  • Advanced quality assets (used trees have 8-12K triangles in LOD0);
  • Cross-fading for smooth LOD transitions.


Below we have some visual results.




Below it is possible to see the rendering of several plants in a long-distance view.


Below we have a short performance demonstration (Ryzen 3, GTX 1070, 16GB RAM, Full HD). In this demonstration, the terrain spans 80km on its larger side, while trees are visible at distances of up to 8km.





High-level details about the solution

The solution distributes vegetation procedurally on-demand in regions delimited by quadtree’s nodes. Nodes outside the camera’s frustum are destroyed as well as the plants of it. The plants remain in memory as long as the nodes are visible. If needed, the plants are deterministically redistributed as the nodes are recreated.

For distribution, the solution considers the influence of different aspects, such as terrain (e.g., slope and moisture), environmental (e.g., forest, lakes, and rivers zones), and human (e.g., villages and roads) aspects. These aspects must be normalizable values into [0, 1] for any scenario’s portion, encoded in 2D maps and/or vector data. Any other information discretized into [0-1] can be integrated.

Plants are grouped using the concept of presets, characterized by a set of plants that share the same needs, considering distribution aspects and other fields used to exist in some scenario’s position. For example, a presets of plants that exist in 1) forest zones, 2) not in steep regions, and 3) in higher altitude regions. The system analyzes many presets in real-time and defines which preset best fits a particular scenario’s position. After determining the best presets for the analyzed position, any plant from that can be randomly selected to be placed.

For efficiency purposes, plants are analyzed frame-by-frame to establish a LOD to balance performance and visuals. The LOD is defined from the distance of each plant to the camera –artists have control over it. Also, plants outside the frustum are discarded before rendering. Finally, the plant data is organized properly for use of GPU-instancing to speed up rendering.

Even though vegetation processing takes place mainly on the GPU, other processes on the CPU can still interact with plants. Objects can deform grass and small bushes, keeping them bent for long periods with acceptable memory demands (see more details here). Plants' colliders are instanced on-demand based on physics objects' positions to allow collisions with large and medium-sized trees using the physics engine.

As a result, A scalable GPU-based solution was developed to deal with any type of plant (e.g., trees, bushes, and grass) in real-time. It is possible to save different configurations –equivalent to biomes– and use them in different scenarios. Artists can intuitively edit these configurations to get different layouts for plant placement, previewing the result immediately. In addition, artists can edit LOD parameters to get a trade-off between visuals and performance. The solution also extracts maximum parallelism and processing from modern GPUs.




Nifty tech tag lists from Wouter Beeftink