Sunday, May 27, 2012

Procedural grass rendering

Grass distance 45m; 400k+ blades of grass

Procedural grass in Outerra is rendered in two stages. The first stage generates just a grass canopy, a height mask that produces the overall shape that the grass forms on the terrain. It generates dry grass-less areas as well as grass of varying height using fractal patterns. Output of this stage is also directly used when rendering the terrain in the distance; what you see out there is not the ground level but a procedurally textured envelope of low vegetation. This also means that objects that are hidden in the 3D grass will be hidden under the distant canopy as well.

The second stage generates grass blades dynamically using the canopy data: terrain elevation, grass height and color. Canopy data have resolution roughly 30cm, and the amount of grass blades varies depending on the level of detail, that in turn depends on the distance from the camera.

Levels of detail highlighted

Original image

The algorithm generates each blade via a geometry shader as a triangle strip with 7 vertices and 5 triangles, making a blade with 3 segments. For short blades the 3 segments would be a waste, so in that case the blade is folded into a V-shape between the first and the second segment. This doubles the apparent density for the shorter grass, which is desirable since it doesn't cover the ground as well as the longer one.

Triangle strips for long and short grass blades

At the most detailed level there are 4 blades generated from a single point in the canopy texture. Each detail level halves the amount of blades, while also doubling the width of the remaining ones.
Grass density geometry reduction with distance, from 0, 8 and 16 meters, respectively
Original patch of grass from which the blades above were extracted.

Since the blades are generated individually, they can be also easily animated. Here's a short video where the texture normally used for ocean waves was used to animate the blades. Obviously it will need different parameters, but conceptually it works quite well.

And finally, a longer video showing the grass rendering in motion.