Vertex Color, Alpha and Shadow

Surface shader is actually a vertex and fragment shader too, so theoretically the vertex data is accessible in surface shader too by using SEMANTICS or common state vert

struct v2f
{
	half4 color : COLOR;
};

As for the Alpha Texture, we can decide the color based on the UV mapping in vertex function

fixed4 frag (v2f i) : COLOR0 
{
	...

	fixed alpha = tex2D (_AlphaTex, i.uv).r;
	tex.a = alpha;
	
	...
}

Surface shader does not generate a shadow-cast pass, so the pass in the fallback is used. To add shadow, we can use addshadow and another SubSahder tagged "ShadowCaster".

Cull Off makes sure the plane will show both side.

_CutOff is a property.

SubShader
{
	Tags
	{
		"LightMode" = "ShadowCaster"
	}

	Cull Off
	
	Pass 
	{
		CGPROGRAM

		#pragma vertex vert
		#pragma fragment frag

		...

		fixed4 frag (v2f i) : COLOR0
		{
			fixed4 tex = tex2D (_MainTex, i.uv);
			fixed alpha = tex2D (_AlphaTex, i.uv).r;
			tex.a = alpha;
			clip(tex.a - _Cutoff);

			return(alpha);
		}
		
		...
		
		ENDCG
	}
}

This is actually a clumsy solution, because it violates the DRY principle by repeating the same calculation in the shadow part, but I haven’t learned enough yet to find a better solution.

Wind

Vertex function can update the vertex data and change the placement. We use the _Time variable to add animation by calculating the displacement based on the all wind parameters.

However, I didn’t find a good enough mathematical or physical model for the wind. The code will get improved if I can find solution to reduce the cluster of calculation.

Properties 
{
		_wind_dir ("Wind Direction", Vector) = (0.5,0.05,0.5,0)
    _wind_size ("Wind Wave Size", range(1,50)) = 15

    _tree_sway_stutter_influence("Tree Sway Stutter Influence", range(0,1)) = 0.2
    _tree_sway_stutter ("Tree Sway Stutter", range(0,10)) = 1.5
    _tree_sway_speed ("Tree Sway Speed", range(0,10)) = 1
    _tree_sway_disp ("Tree Sway Displacement", range(0,1)) = 0.3
}
//Gets the vertex's World Position 
float3 worldPos = mul (unity_ObjectToWorld, v.vertex).xyz;

//Tree Movement and Wiggle
v.vertex.x += (cos(_Time.z * _tree_sway_speed + (worldPos.x/_wind_size) + (sin(_Time.z * _tree_sway_stutter * _tree_sway_speed + (worldPos.x/_wind_size)) * _tree_sway_stutter_influence) ) + 1)/2 * _tree_sway_disp * _wind_dir.x * (v.vertex.y / 10) + 
cos(_Time.w * v.vertex.x * 0.01 + (worldPos.x/_wind_size)) * 0.07 * _wind_dir.x * v.color.b;

v.vertex.z += (cos(_Time.z * _tree_sway_speed + (worldPos.z/_wind_size) + (sin(_Time.z * _tree_sway_stutter * _tree_sway_speed + (worldPos.z/_wind_size)) * _tree_sway_stutter_influence) ) + 1)/2 * _tree_sway_disp * _wind_dir.z * (v.vertex.y / 10) + 
cos(_Time.w * v.vertex.z * 0.01 + (worldPos.x/_wind_size)) * 0.07 * _wind_dir.z * v.color.b;

v.vertex.y += cos(_Time.z * _tree_sway_speed + (worldPos.z/_wind_size)) * _tree_sway_disp * _wind_dir.y * (v.vertex.y / 10);