Table of Contents

Grass and undergrowth

Grass models are defined in .stsdk files, exactly as tree models are. This means that they are defined and edited in the SpeedTree Modeler as if they were any other tree model (often as individual tufts of grass), subject to the same geometry, lighting, and wind definitions. The only restriction is that they must have a single level of detail (LOD). Grass models also do not use billboards for the lowest LOD since there is no LOD in the grass system.

The grass system can be used to populate the scene with any ground cover like rocks, twigs, or leaves. If the Modeler can load it, it'll go through the pipeline and can be used as a grass model.

Note: Be sure to use the grass vertex packer when exporting grass from the Modeler.

Overview

The SDK lets the client application stream in those grass instances that are visible and automatically flushes those instances that are no longer visible.

The SDK organizes the world as a series of cells. As the camera moves, cells go in and out of visibility. As cells become visible, the SDK provides a list of the cells that need to have their populations streamed in. Hence, the SDK will perform most efficiently when the client has the grass instances already organized by cells so that the data might be passed into the SDK without further on-the-fly processing.

In the reference application, grass cells are populated using a procedural approach, but any population procedure will work.

Getting started

There are several classes and structures you'll need to get started:

These data structures are detailed in Culling and Population Structures.

Streaming and culling

As shown in CMyPopulate::StreamGrass(), the general procedure followed for each frame where the camera has moved is outlined below:

Additional considerations

Cell size

You can pick different cell sizes per grass type and it can impact both CPU and GPU performance a great deal. Each grass model is culled in a separate call, so separate sizes are easily accommodated. In contrast to tree instances, grass instances are not individually culled. If the cell is in the frustum, then every instance in it will be rendered. This cuts down on CPU usage greatly, but can be hard on the GPU for higher grass densities. To strike a balance, smaller cell sizes can be used. We recommend smaller cell sizes for high-density grass, and larger sizes for sparse models like rocks or boulders.

By way of example, the reference application's example forest (modeled in feet) uses cell sizes of 20 for the high-density grass, and up to 100 for the sparsely populated models.

Heap fragmentation control

The organization of multiple types of grass into an arbitrary collection of cells can easily lead to a great number of heap allocations. We leave it to the user to implement their own population approach that doesn't cause undue heap fragmentation if that's a requirement for your title or project.

To control the SDK's heap behavior, be sure to read about the Reserves System.