Unity Speedtree for Mobile?
Speedtree is the solution of choice for most developer when creating Trees, however, most don't realize why is it.
While Unity comes with a pretty cool Tree editor, compared with Speedtree, Unity's editor tree looks like a prototype. Even Unity docs mentioned Speedtree when talking about their own Tree editor.
There's also a dedicated page talking about Speedtree inside Unity docs, the reason for that is what we will see next.
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 Speedtree8 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, resulting in 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.
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 are a little 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.
Check Fourier Series to understand more about the math behind those curves.
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 he 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.
Based on that, we can come with some solution as the one below.