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);