Thursday, February 21, 2008

The grass is greener

Work on implementing a better foliage system has continued, and I'm getting more and more pleased with the results. Here are some recent screen shots.
As with all other functionality in Ember I've strived to make it as general and modifiable as possible. It should be trivial to both change the behaviour and to extend it. The way it's implemented is through the use of the terrain layers as a base. This is how the xml definition for the grass terrain layer looks like (I've removed some texture definitions):

<?xml version='1.0' encoding='UTF-8'?>
<terrain>
<layers>
<layer shadername="grass">
<foliage planttype="grass" populationtechnique="cluster" rendertechnique="grass">
<param key="minClusterRadius">2</param>
<param key="maxClusterRadius">10</param>
<param key="clusterDistance">25</param>
<param key="density">2</param>
<param key="falloff">0.3</param>
<param key="material">/global/plants/grass/bittergrass/single</param>
</foliage>
<foliage planttype="fern" populationtechnique="cluster" rendertechnique="shrubbery">
<param key="mesh">3d_objects/plants/shrubs/models/fern/fern.mesh</param>
<param key="minScale">0.7</param>
<param key="maxScale">2.0</param>

<param key="minClusterRadius">1</param>
<param key="maxClusterRadius">3</param>
<param key="clusterDistance">30</param>
<param key="density">2</param>
<param key="falloff">0.7</param>
</foliage>
<foliage planttype="camelia" populationtechnique="cluster" rendertechnique="shrubbery">
<param key="mesh">3d_objects/plants/flowers/models/camellia.mesh</param>
<param key="minScale">2</param>
<param key="maxScale">5</param>

<param key="minClusterRadius">2</param>
<param key="maxClusterRadius">5</param>
<param key="clusterDistance">40</param>
<param key="density">1</param>
<param key="falloff">0.7</param>
</foliage>
<foliage planttype="leaves" populationtechnique="cluster" rendertechnique="shrubbery">
<param key="mesh">3d_objects/plants/shrubs/models/leaf/leaves.mesh</param>
<param key="minScale">0.5</param>
<param key="maxScale">1.2</param>

<param key="minClusterRadius">2</param>
<param key="maxClusterRadius">5</param>
<param key="clusterDistance">35</param>
<param key="density">2</param>
<param key="falloff">0.7</param>
</foliage>
</layer>
</layers>
</terrain>
Every foliage type has both a population technique and a render technique. The first one determines where to put the vegetation and the latter determines how it should be rendered. Both of these share the same set of arbitrary parameters. We currently only support the cluster population technique. This creates a series of clusters of varying sizes randomly dispersed over the map. In most cases this looks quite nice, since plants tends to grow in clusters in the nature. All of the plants positions are calculated when the terrain is loaded, and not changed thereafter. However, every time a plant is placed we check all the layers that are above the current layer. If the combined value of all the layers above are above a threshold value we don't show the plant. This has the effect that roads, fields and other areas don't get vegetation, unless there's foliage defined for that particular layer. And since we've already determined the positions for the plants we can update foliage swaths as areas are added without having the positions of existing plants getting jumbled each time.

Regarding the render techniques we currently support two different: grass and shrubbery. The former autogenerates grass meshes, and animates it whereas the latter uses preexisting meshes. So far the latter haven't got support for animations, but that's something that we'll surely add.

The population techniques are implemented in Ember so far, but the idea is to put them in Mercator as they stabilize. That way it should be possible to specify foliage on the client, very much like we now specify Mercator shaders.

All in all it's looking mighty promising, even though as can be seen in the screen shots we need to fix up the colours a little.

No comments: