Unity Shaders: Toon Tree

In this article, I’d like to talk about my toon tree shader that emulates the look of Studio Ghibli trees.
To get that hand-painted look, there’s a built-in shader you can test in your material under Nature/Tree Creator Leaves.
It is meant to be used with trees created using Unity Tree Editor, so it doesn’t apply motion.
Since I din’t want to use trees generated using the Unity Tree Editor, I had to create a custom shader that used the custom lighting model from Tree Creator Leaves and my own functions to add motion.
Apart from the shader, there are two other important things to get good lookig trees:

  • modeling the leaves the right way and export them with smoothed normals to get that hand painted look
  • a good texture for the leaves

There’s a great article on Habrador’s blog on modeling leaves.
I followed that article to model the leaves of my tree while for the trunk, I used Blender Mtree free plugin.
I took the texture from the Habrador’s article and painted white so I can then decide later, in my shader, the color of the leaves.

The Code

Shader "Mistwork/Tree Wind Tutorial" {
Properties {
[HDR]
_Color ("Main Color", Color) = (1,1,1,1)
_MainTex ("Leaves texture", 2D) = "white" {}
_Cutoff ("Alpha cutoff", Range(0,1)) = 0.3
_TurbulenceTex("Turbulence texture", 2D) = "black" {}
_TurbulenceAmount("Turbulence amount", Float) = 0
_TurbulenceSpeed("Turbulence speed", Float) = 0
[Header(Swaying)]
_WindSpeed("Wind speed", Range(0,50)) = 25
_SwayingRigidness("Swaying rigidness", Range(1,50)) = 25
_SwayMax("Sway Max", Range(0, 5)) = .05
_YOffset("Y offset", float) = 0.0
}
SubShader {
Tags { "IgnoreProjector"="True" "RenderType"="TreeLeaf" }
LOD 200
CGPROGRAM
#pragma surface surf TreeLeaf alphatest:_Cutoff vertex:vert addshadow nolightmap noforwardadd
#include "UnityBuiltin3xTreeLibrary.cginc"
sampler2D _MainTex;
float _WindSpeed;
float _SwayingRigidness;
float _SwayMax;
float _YOffset;
sampler2D _TurbulenceTex;
float _TurbulenceAmount;
float _TurbulenceSpeed;
struct Input {
float2 uv_MainTex;
float2 uv_TurbulenceTex;
};
void wind_force(inout appdata_full v, float3 v_world)
{
float x = sin(v_world.x / _SwayingRigidness + (_Time.x * _WindSpeed));
float z = sin(v_world.z / _SwayingRigidness + (_Time.x * _WindSpeed));
v.vertex.x += (step(0,v.vertex.y – _YOffset) * x * _SwayMax);
v.vertex.z += (step(0,v.vertex.y – _YOffset) * z * _SwayMax);
}
void vert(inout appdata_full v)
{
//Convert grass vertex position from object to world space
float3 vertex_world_pos = mul(unity_ObjectToWorld, v.vertex).xyz;
wind_force(v, v.vertex.xyz);
}
void surf (Input IN, inout LeafSurfaceOutput o) {
float2 turbulence = (tex2D(_TurbulenceTex, IN.uv_TurbulenceTex + _Time.y * _TurbulenceSpeed).xy * 2.01.0) * _TurbulenceAmount;
float4 leavesTex = tex2D(_MainTex, IN.uv_MainTex + turbulence);
o.Albedo = leavesTex * _Color;
o.Alpha = leavesTex.a;
}
ENDCG
}
Dependency "OptimizedShader" = "Hidden/Nature/Tree Creator Leaves Optimized"
FallBack "Diffuse"
}
view raw treewind.shader hosted with ❤ by GitHub

The code is pretty straight forward, it’s a surface shader that uses the built-in TreeLeaf custom lighting model as I’ve mentioned before.
To use it, you have to include UnityBuiltin3xTreeLibrary.cginc like I did at line 25 and add TreeLeaf in the pragma statement at line 24.

There are two types of motion I wanted to give to the tree:

  • Swaying of the leaves and the trunk of the tree
  • Some kind of turbulence to the leaves

The properties of the shader are the following:
_MainTex – texture of the leaves I took from Habrador’s article and then painted white.
_Cutoff – alpha threshold for the leaves texture. Lower values make the leaves volume thicker.
_TurbulenceTex – a noise texture we use to simulate turbulence on the leaves
_TurbulenceAmount – how much turbulence we want to apply to the leaves
_TurbulenceSpeed – the frequency at which the turbulence affects the leaves.
_WindSpeed – the speed of the swaying
_SwayingRigidness – at lower values, it gives the trees almost a “liquid” motion. It’s great to give subtle differences when you have multiple trees fairly close to each other.
_SwayMax – max amount of swaying to be applied to the tree
_YOffset – apply the swaying only on vertices above this threshold

Swaying motion

Line 42 – we declare a wind_force function that we will then use in the vertex shader
Lines 44, 45 – to make the leaves and the trunk swaying back and forth, we use the sin function.
We apply the rigidiness by dividing the vertex position in world space by the _SwayingRigidness property. Then we add the built-in variable _Time.x multiplied by the _WindSpeed property to make them swaying at the speed we want.
Line 47 – the step function basically returns 1 if the difference between v.vertex and _YOffset is > 0, otherwise it returns 0. This means that the swaying effect will be applied only on vertices that are above the _YOffset property.

Turbulence and leaves color

Line 62 – we sample the turbulence texture and convert its sampled values from range [0, 1] to range [-1, 1]. We also apply turbulence speed by adding _Time.y * _TurbulenceSpeed.
Line 63 – to make the leaves moving affected by the turbulence, we simply distort the leaves texture UVs using the turbulence values we have just computed.
Line 65 – because the leaves texture is pure white, we multiplied it by the _Color property to set the color of our leaves.

Textures

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s