Rendering plants efficiently has always been a challenge in computer graphics, a relatively new technique to address this is Pixar's stochastic pruning algorithm. Originally developed for rendering the desert scenes in Cars, Weta also claim to have used the same technique on Avatar.
Although designed with offline rendering in mind it maps very naturally to the GPU and real-time rendering. The basic algorithm is this:
- Build your mesh of N elements (in the case of a tree the elements would be leaves, usually represented by quads)
- Sort the elements in random order (a robust way of doing this is to use the Fisher-Yates shuffle)
- Calculate the proportion U of elements to render based on distance to the object.
- Draw N*U unpruned elements with area scaled by 1/U
So putting this onto the GPU is straightforward, pre-shuffle your index buffer (element wise), when you come to draw you can calculate the unpruned element count using something like:
// calculate scaled distance to viewer float z = max(1.0f, Length(viewerPos-objectPos)/pruneStartDistance); // distance at which half the leaves will be pruned float h = 2.0f; // proportion of elements unpruned float u = powf(z, -Log(h, 2)); // actual element count int m = ceil(numElements * u); // scale factor float s = 1.0f / u;
Then just submit a modified draw call for m quads:
glDrawElements(GL_QUADS, m*4, GL_UNSIGNED_SHORT, 0);
The scale factor computed above preserves the total global surface area of all elements, this ensures consistent pixel coverage at any distance. The scaling by area can be performed efficiently in the vertex shader meaning no CPU involvement is necessary (aside from setting up the parameters of course). In a basic implementation you would see elements pop in and out as you change distance but this can be helped by having a transition window that scales elements down before they become pruned (discussed in the original paper).
Billboards still have their place but it seems like this kind of technique could have applications for many effects, grass and particle systems being obvious ones.
I've updated my previous tree demo with an implementation of stochastic pruning and a few other changes:
- Fixed some bugs with ATI driver compatability
- Preetham based sky-dome
- Optimised shadow map generation
- Some new example plants
- Tweaked leaf and branch shaders
You can download the demo here
While I was researching I also came across Physically Guided Animation of Trees from Eurographics 2009, they have some great videos of real-time animated trees.
I've also posted my collection of plant modelling papers onto Mendeley (great tool for organising pdfs!).