Yves "Jack" Albuquerque
The Complete Guide to Create Trees for Games
Atualizado: 7 de dez. de 2021
What is a tree?
I'll not talk about the botanical definition of a tree here.
As a Game Developer, the important thing about a tree is that they use tricky systems for light/shadow, movements and performance so let's unfold that systems...
First, let's check the artistic aspects of a Tree.
Let's breakdown Tree art in order to find some terms of interest before look deeper into the technical parts. Let's focus here on different elements that compose a tree, specially Shape, Color, Lighting and Movement.
In the most basic scenario, a Tree have just a Trunk (usually with Branches and Root since a pure trunk without other elements is a Log). Most artist don't notice but a Tree without leaves actually have different meaning across the globe.
Sub-Tropical areas have well defined autumn with Trees without leaf so it looks somewhat natural, while tropical areas don't have a well defined autumn so usually, a Tree without leaves means that this Tree is dying or that is actually a Dead Tree.
In both cases, a Tree without a leaf is associated with the lack of life, however, a person who lives in a tropical area may be prone to create some intrinsic ecological narrative to that visual element in order to figure out a reason for that. Maybe the soil is infertile or contaminated? Maybe pollution made air or water somewhat toxic or acid? Maybe some plague infected that Tree? Maybe Something caused a shortage of water?
The Tree of Woe in Hellblade: Senua's Sacrifice from Ninja Theory shows a Tree without leaves with dead bodies and ritualistic decorations.
A Tree made by a Trunk and a Top is the most usual elements that blinks in our mind when we think about Tree. Those elements are enough to make you recall that something is a Tree.
The Tree from Crossy Road, from Hipster Whale, is a good example of a very simple Tree that fits perfectly to the cube-based game art style.
Roots are mostly unseen but their size is actually bigger than the part over the ground. You can check some root drawings here. Depending of hardness and nutrient concentration, roots might spread in different ways. Most South America Trees, for instance, have large roots spreading out close to the ground surface and sometimes even getting back from the ground to the ground surface, European Trees, on the other hand, usually have deeper thin roots.
Looking deeper into Trunk and Top, we may identify some core shape elements that compose a Tree as: Trunk(1), Branches(2), Fronds(3), Leafs(4), Root(5), Lump(6), Knots(7), Cap(8), Cavity(9), Gash(10), Covers(11) and Peeling Bark(12).
*Notice that Frond is usually a term used for bushes but here we use that term to express a behavior. In some cases, a Frond is a terminal composition between branches and leaves and reacts to wind in a hybrid way, in other cases, is actually the terminal composition encompassing the leaves itself, specially on bushes or simplified versions for low end devices.
Visual reference trees should have a different silhouette that looks differently depending from which side are you looking at. This helps player orientation and provides more interesting shapes.
Color and Value variations can be used to break the visual repetitiveness. Luckily, due the organic nature of a Tree and the seasonal color variation, we can explore and adapt it's color and variations in multiple ways.
The Witness from Jonathan Blow adopts this stylized trees with emphasized colors and values variations in order to, not only break repetitiveness, but also, to create colored visual anchors to the environment.
The light scattering at the Top of a Tree and the patterns of the shadows can create very interesting visual results.
Trunks are usually fully opaque, leafs, however, may presents a subsurface scattering, aka, SSS.
Uncharted 4 from Naughty Dog have several "roles" in their level design to let the light pass and also to give a sense of direction to the users. Vegetation is often used on that "roles" to break the designed silhouette with a more organic look and feel. We can see here how the SSS happens letting the light pass through the leaves on the top of this valley.
Additionally, the amount of light suffers a huge variation towards the center of the trunk passing through several layers of leafs. The result is the occlusion of the ambient light, or, Ambient Occlusion.
AO view generated in Speedtree
Areas with vegetation tends to have a lot of air particles due pollen production, flying insects, dust and all the motion produced by wind interaction. Light become visible when bouncing back and forth through air particles, creating an effect called Atmospheric Scattering. Light exposure may also highlight some of the results of that process. Next, I'll describe some topics that actually are related to the render itself, however, I couldn't let them out of this art direction overview due how these effects are aesthetic coupled with Vegetation.
Ghost Of Tsushima from Sucker Punch Productions reinforces wind and atmospheric scattering with post processing, clouds, smokes, polen and several other particles.
Light Shafts, aka God Rays, is probably one of artist's favorite lighting effect. The natural gaps and scattered nature of a tree contributes to the generation of light streaks that are so impressive.
Firewatch from Campo Santo highlights key moments with those spectacular Light Shafts formed by Trees
Along with Light Shafts, Bloom is often used.
The oneiric blurriness from Bloom in Bioshock Infinite from Irrational Games makes Light Shafts blend with the environment creating this nice atmospheric effect
As a side effect of the light passing through the gaps of the tree, casted shadows adds a organic variance to the surfaces around the shadow caster.
Notice the beautiful granularity of the casted shadow over the floor and the airplane into that scene from Fallout76 from Bethesda. 1
As a huge vertical element, Trees also helps to create layers into the composition. The resulting parallax combined with the fog brings a nice sense of depth.
Limbo from Playdead uses sunshafts, fog and layered trees creating this beautiful monochromatic depth art direction that becomes the main signature of that game
Trunks and Branches are usually very rigid but sometimes can present some Bending, specially long thin ones.
The Trail from 22 Cans presents that bend-like chunky lateral movement on their Trees but no leaf animation. Looks like those Trees are dancing bringing some life to the solid stylized environment.
Leafs adds texture and present Swaying or similar movements.
Owlboy from D-Pad Studio adds swaying animation to leafs. That element combined with clouds, grass and character cloth brings a constant wind presence though the entire game.
Hanging Vines, Fronds or block of leafs can also be used to add motion.
Dust: An Elysian Tail from Dean Dodrill, reinforces wind feedback adding hanging movements to vines and blocks of leafs. The result shows a very natural reactive environment.
Each vegetation will ask a different movement pattern. As we saw, art direction can strongly impact on what sort of movement is will better match the relevance and aesthetic expectation of our vegetation.
Reactivity like the ones added by Physics Systems can be used to add integrability, a game design concept that can be translated as: increase the feedback of user actions to make it more meaningful.
Crytek sometimes showcase CryEngine by showing a vegetation Reactivity integrated with the Physics System. That solution is features since the first Crysis.
Notice, that I'll not talk about visual feedback for Wind here but how the Wind affects a Tree so detached leafs, dust, pollen, grass, and several other elements that are related to the Wind System and Art Direction will not be covered by this post.
Ori and the Blind Forest from Moon Studios implements all concepts presented above with a strong art direction. The result is one of the most beautiful games ever.
Let's get technical...
Let's break it down our problems. 1
Number of Trees:
As mentioned, trees appears with other trees, sometimes, an entire forest. The real problem here is the number of Batches (and Drawcalls) required for each Tree. Usually Trees are too complex to be batched by a dynamic batch system and too numerous to be batched by a static batch (high memory consumption), however, That's not an issue here if we use GPU Instancing.
GPU Instancing implies that all trees of the same type shares the same materials and some per-renderer data is used instead.
(Add Image: Forest in single drawcall sample)
Number of Leafs:
A real tree may have a huge number of leafs. Games simplify that using bigger leafs in smaller numbers. That effect is even easier to be used when is far from the Tree since we don't perceive very clearly the individual elements of a Tree but, instead, perceive it as a single block of elements.
In general, in far distance the sense of depth is less accurate and parallax into a single tree is not very noticeable so it can be simplified.
This is far from be an art-exclusive topic thou. Tech Artists can also use that.
Multiple LOD levels can use this as a technique to reduce the number of leafs, fronds and branches by generating LODs with less, but bigger, elements while preserving the silhouette.
A step further on that is to use an LOD transition that allow to interpolate our LODs.
Speedtree transition interpolates LODs by scaling different parts of a tree. The branches a leafs that will be removed scales down while the others scale up. During the transition, looks like a parallax change to the user, but, when the transition is completed, several elements of the Tree have disappeared like magic.
Less common but an awesome solution for high-end devices is to use a distance based tessellation shader or different LODs using different tessellation coefficient. That solution may require more GPU effort on some circumstances but the blend is smooth and the result astonishing.
Sample from Unity's Book of the Dead. LOD0 and LOD1 uses the same mesh but LOD0 uses tessellation so the Tree gain a lot of details when close to camera.
Complex aerodynamics to simulate here. Trees usually have too much branches and leafs to use bones. Physical simulation based on motion equations that apply wind force to individual branches is also prohibitive. Additionally there's a in-between behavior that should be shared among different trees since a tree next to the other one may look weird if affected by a totally different wind. The solution for that is to move some vertices directly, using the vertex shader.
However, not all parts of a tree moves in the same way.
- Trunks sometimes bends in meaningful ways, sometimes don't. When some trees bends as palm Trees, that bend is higher on the top than close to the root.
- Branches have a similar bend effect starting with the bend effect being higher closer to the tip but also a huge variance depending of the stiffness and length of branches, the size and shape of leaf crowns, the conditions of the wind field, and turbulence inside the tree crown.
- Fronds bends as a whole while swaying at the tips.
- Leafs hangs and sway.
Tree leafs animated passing wind to create some vertex shader animation (in Speedtree)
Some hybrid solution involving bones for main Branches may be used in movies but is not common in games due the performance cost so we'll not see those ones here.
Similar to Lods, but less famous, sLods (Simulation Levels of Detail) is the perfect answer to apply movements to a tree. As closer is a tree, more accuracy is demanded. Trees far from camera may have the movement reduced to a very simple and general movement. On my experience, even the furthest tree demands some movement, otherwise, the sLod will pop and be very noticeable.
On top of that, branches, fronds and leaf can have different reactions to wind depending if they are facing the wind, on the back side of the parent structure of perpendicular to the wind direction.
Beside the difference on behavior, all wind reaction have a similar theoretical root. Check Fourier Series to understand more about the math behind the curves used to change each vertices. This bunch of curves have a layered complexity applied to each tree element being trunk the simplest and leafs more complex.
A Noise Function used for animating a Tree Trunk from GPU Gems 3. Segment is a tree leaning away from the strong wind. Segment B represents the combined effect of turbulence. A tree with greater mass and lower elasticity can be simulated by lowering the amplitude of the function and decreasing the frequency.
The dynamic nature of a Tree make it a bad fit to Static Lighting. Games that uses only static lighting may face some terrible trade offs on this cases. Trees in games using static lighting usually don't have wind or don't have shadows.
Link, for several titles, saved Hyrule travelling through forest with sparse giant trees without wind or dynamic shadows as we see in Legend of Zelda: Twilight Princess from Nintendo.
Light distribution might be improved by adding vertex color or doing some normal tweaks. A common technique is to "transfer" normal direction from a more simple and rounded geometry. This is especially useful when in stylized bushes or trees where a smooth surface might help silhouette perception and visual coherence.
Airborn from Still Not Sure is one example of the described technique but this become a very popular technique over the last decade. 1 2 3
Time to get deeper into that subject and see some real implementations.
We mentioned leafs and fronds here, the high profusion of instances and complex shapes of those elements make them perfect candidates for simple geometries with transparent textures. Transparent textures over transparent textures (aka: graphics programmer nightmare) is a very hard thing to deal with. While most can be tempted to use simple transparent shaders, that usually isn't a good idea. Transparent shader will force render pipeline to render the same pixel over and over, if we are talking about a forest here with a lot of leaves.... over and over and over and over...
The solution to avoid all that overdraw can come in two ways:
- Using Geometry: Not very practical since wil ramp up the number of polygons, however, can work on cases where the vegetation is stylized.
- Using Alpha Test Shader (aka: cutoff): Alpha test mitigates the issue since it write on z-buffer and discard occluded stuff. Alpha to Coverage can be used to improve contour and mipmap issue that is an additional issue when dealing with both transparent and alpha test shaders.
Last, but not least, billboards on far distance will also help here by reducing the number of overdraw. In other cases, simple cards are used in X-shape, *-shape or the arrow's fletching shape.
Unity Tree Editor
Unity comes with a pretty cool Tree editor so let's see that one first.
Tree editor stands by itself as a system, however, is impossible to not talk about Terrain System here. Terrain System deserves an entire post series but let's take a quick look over how Terrain System interacts with vegetation.
A huge part of the core system are in TerrainEngine.cginc. More specifically into AnimateVertex method. Relevant information are added into vertices and goes along with color and texcoord1 into vertex data. color.x and color.y represents "branch phase" and "edge flutter factor". texcoord1.xy related to factors used primary for bend.
When used with the Terrain system, additional features are added per instance as color variation (_TreeInstanceColor), scale variation (_TreeInstanceScale) and squash (_SquashAmount), a data that helps 3d models to match billboards by squashing the vertex into a planar projection when camera is far from object going towards the billboard LOD.
Leaves uses translucent lighting getting backlight from probes and main light of a mix using lambert for direct light and probes for indirect light. Grass uses a simple lambert per vertex.
Whatever is added as a grass, will use a grass Shader. The Shader Grass, called WavingGrass.shader implement the waving behaviour along with some color variance passed through a variable called _WavingTint. Wind speed, wave size, wind amount and max sqr distance call passed into a float4 called _WaveAndDistance. Color Channel into Mesh Grass are expected to uses the value of 1 on top vertices and 0 on bottom vertices.
Speedtree is the solution of choice for most developer when creating Trees, however, most don't realize why is it.
Most developers I know, think on Speedtree as a solution for some ready-to-use Trees that is affected by wind, indeed, Speedtree offers a nice library of ready-to-use trees but there's much more about that solution than use the library.
Additionally, some people think about Speedtree for movies and High-end productions, however, Speedtree is very flexible and allows you to generate meshes suitable even for low-end mobiles. If you have a good domain over Speedtree, you can easily adapt that fancy AAA tree to run in your old mobile device.
The current Speedtree 8 version are very different from the previous Speedtree versions.
-There's no Speedtree editor to be used inside Unity, UE4, Maya or 3ds Max, instead, there's some standalone versions to create Trees and some shader inside that solutions.
-All shaders are now much more optimized and instead of split trunk from the movable parts of the tree, using 2 materials, Speedtree now uses a single material.
-There's some cool options to create atlas and optimize Trees generated in Speedtree.
-You can mix PBR textures and models with your tree.
-Some mesh data was changed(so you may see issues if you try to use Speedtree8 shader in a Speedtree7 model). You can open your speedtree 7 using Standalone Software and export as speedtree 8, thou.
We'll not going deeper in how the Standalone version works here. You can use Speedtree youtube channel for tutorial about it.
As a general overview I just want to mention some checklist to use before export your Speedtree model from the Standalone version:
-Generate AO before export. That will update the vertex AO based on your Tree setup.
- Don't ignore wind setup. Each Speedtree node reacts differently to wind.
- Control segments and create clusters to adapt your polycount to your device.
- Don't overestimate the time needed to create or adapt a tree. Speedtree can generate results very quickly but, if you want to generate a really controlled result, that will demand some additional time, not very different from a 3d software (but with some additional features).
- Check LOD and leaf transitions carefully. Speedtree implements a very interest way to to fade between LODs. With some patience, you can achieve awesome tradeoffs from it.
- The exporting preferences may be slightly different between Indie, UE4 and Unity versions.
-You can export billboards only for Trees that will be very far from camera.
-Currently, there's no built-in Unity HDRP shader but Speedtree have a workaround for that. Follow this link carefully and you will be fine.
- Use Atlas to reduce the number of materials used by your tree. You can check "Allow V wrapping" to wrap your trunk texture and let it repeat on Y axis.
While Speedtree7 uses several .cginc files, Speedtree8 relies on top of only two .cginc files: SpeedTree8Common.cginc and SpeedTreeWind.cginc.
SpeedTreeWind have wind-related methods and the related property block. That property block have the cool wind curves and is set by the Tree component. Tree component is some sort of Black-Box in Unity but what it does is create some interesting curves to be used by the vertex of the tree and injects that into that property block.
Tree component is also used by built-in Tree but, deep into the C/C++ part, it implements a factory and create two different solutions for each tree system. (If you are using bundles and stripping things out, you may incur in some issues to use both systems. Both solutions, however, uses some similar structures so you may see some weird movements in your tree even if one of the solutions was stripped out the build).
SpeedTree8Common.cginc implements vertex and fragment core behaviors.
OffsetSpeedTreeVertex method is the one that do the wind simulation. Is called by the vertex function called SpeedTreeVert.
All other function inside SpeedTree8Common.cginc are the fragment/lighting/GI part. Speedtree uses the regular UnityPBSLighting with some tricks on top of it.
Depending of the wind quality, Speedtree uses different solutions. That also depends of the type of the tree part. That data is stored into texcoord3.w and classified between: GEOM_TYPE_BRANCH, GEOM_TYPE_FROND, GEOM_TYPE_LEAF, GEOM_TYPE_FACINGLEAF.
Billboards uses the exact same shader but with the keyword: EFFECT_BILLBOARD. Billboard code is distributed all over the shader. The most interesting part is how normal are normalized to create an uniform lighting across the different planes of the billboard solution.
Transparency uses Alpha clip and speedtree optimization includes support for GPU Instancing.
Adapting Speedtree shader to mobile can require some different solutions.
- First, we probably want to use Vertex and Fragment only and not Surface shader since it can be an overkill of supported features for our case.
- PBR can be expensive for some old mobiles, so maybe some blinn-phong based solution fits better for that. Additionally the several maps required for that can demand too much memory space and we probably don't have resource to pay for that.
- AO in Speedtree comes in two different ways, vertex and texture. We can achieve a pretty decent result by doubling the vertex result instead of use the texture.
- Don't worry too much about all the "ifs" into Speedtree, most of them don't generate divergent code. We can probably reduce that a little bit but, so far as I could check, the benefit is not as big as most think.
Nature Manufacture as Unity Built-In and SpeedTree 7 uses, at least, 2 materials per tree (Trunk and Leaves)
Nature Manufacture don't have an authoring tool as Unity Built-In or Speedtree restricting your options to their packages.
Nature Manufacture actually implements several Tree/Vegetation solutions. Lighting are usually based on Unity's standard BRDF with color variation using noise from vertex position. All solutions shares some wind barebones handled by libs as NMWind.cginc. Touch reactivity is supported by a lib called NMWindTouchRect.cginc but only enabled when using additional Nature Manufacture solution. Lod transition uses Unity's crossfade.
Nature Manufacture shaders don't use the same unity built-in wind system demanding other values to be set by an external script (included). The same applies to touch reactivity.
Nature Manufacture tree are not as easy as speedtree to be used on mobiles. You may simplify lighting solution to reduce the amount of maps used, however, simplify the mesh is not that simple and you will still be using 2 materials per tree.
I've no good reason to add this forest on this post but here it goes. (Maybe a good example of exception thou)
Wonderful Satorl Marshfrom Xenoblade Chronicles (Wii) from Monolith Soft.
Also, I can't finish that post without a link to polycount page about Foliage.