Vertex Animation Shader Not Compatible with Android

I’ve kit-bashed the shader below in order to add some simple motion to background objects in my scene (trees, bushes, etc). I’m fairly happy with the results in the Editor and on PC builds, however it does not work at all when i build to Android devices (tested on Nexus 6 and Nexus 9).

Any ideas on what part of the code is making Android unhappy and any ways to make it work?
I’m very new to working with Shaderlab in Unity (or working shaders at all for that matter) and can’t seem to figure this one out.

Thanks (Sorry for the messy commenting)

// Unlit alpha-cutout shader.
// - no lighting
// - no lightmap support
// - no per-material color

Shader "Custom/Unlit/Transparent Cutout Wave" {
Properties {
	_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
	_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
	_WaveX ("Wave X", Vector) = (0.01, 0.01, 0.01, 0.01)
    _WaveZ ("Wave Z", Vector) = (0, 0, 0, 0)
    _WaveSpeed ("Wave Speed", Vector) = (1, 1.5, 1.1, .9)
    
}
SubShader {
	//Ztest Less
	Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
	LOD 100

	Lighting Off

	Pass {  
			CGPROGRAM
			// Upgrade NOTE: excluded shader from OpenGL ES 2.0 because it uses non-square matrices
			#pragma exclude_renderers gles
			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"  
            //#include "waves.cginc"      // Get in the helper wave functions

			struct appdata_t {
				float4 vertex : POSITION;
				float2 texcoord : TEXCOORD0;
			};

			struct v2f {
				float4 vertex : SV_POSITION;
				half2 texcoord : TEXCOORD0;
				//float4 pos : POSITION;
				//float fog : FOGC;
			};
			
			void FastSinCos (float4 val, out float4 s, out float4 c) 
			{ 
				val = (val * 1.02 - .5) * 6.28318530;   // scale to range: -pi to pi & make it cyclic
				// powers for taylor series 
				float4 r5 = val * val;               // wavevec ^ 2 
				float4 r1 = r5 * val;                  // wavevec ^ 3 
				float4 r6 = r1 * val;                  // wavevec ^ 4; 
				float4 r2 = r6 * val;                  // wavevec ^ 5; 
				float4 r7 = r2 * val;                  // wavevec ^ 6; 
				float4 r3 = r7 * val;                  // wavevec ^ 7; 
				float4 r8 = r3 * val;                  // wavevec ^ 8; 

				//Vectors for taylor's series expansion of sin and cos 

				float4 sin7 = {1, -0.16161616, 0.0083333, -0.00019841}; 

				float4 cos8  = {-0.5, 0.041666666, -0.0013888889, 0.000024801587}; 

				// sin 
				s = r1 * sin7.y + val + r2 * sin7.z + r3 * sin7.w; 

				// cos 
				c = 1 + r5 * cos8.x + r6 * cos8.y + r7 * cos8.z + r8 * cos8.w; 
			} 

			float4 DoCalcWave (float4 waveoffsets, inout float3 vertex, inout float3 normal, float4 waveHeights, float4 waveDirX, float4 waveDirY) 
			{ 
				float4 s, c; 
				FastSinCos (waveoffsets, s, c); 
				// wave height 
				float height = dot (s, waveHeights); 
				// offset vertex by normal 
				vertex.xyz += normal * height; 
				// offset normal by cos (wave) 
				float4 coswave = c * waveHeights; 
				//normal.xz += float2 (dot (coswave, waveDirX), dot (coswave, waveDirY)) * uvParams.z;
				//normal.xz += float2 (dot (coswave, waveDirX), dot (coswave, waveDirY)); 
				normal = normalize (normal); 
				return s; 
			} 

			sampler2D _MainTex;
			float4 _MainTex_ST;
			fixed _Cutoff;
			uniform float4 _WaveX, _WaveZ, _WaveSpeed;
            //uniform float3 _obstacle;
            //uniform float _affectDist, _bendAmount;

			v2f vert (appdata_t v)
			{
				v2f o;
				const float4 _waveXSize = _WaveX * 2;
                const float4 _waveZSize = _WaveZ * 2;
                const float4 waveSpeed = _WaveSpeed * 4;
               
                float4 _waveXmove = _waveXSize * waveSpeed * 25;
                float4 _waveZmove = _waveZSize * waveSpeed * 25;
               
                // Calculate the wind input to leaves from their vertex positions....
                float3 worldPos = mul ((float3x4)_Object2World, v.vertex);
                 
                // OBSTACLE AVOIDANCE CALC
                //float3 bendDir = normalize (float3(worldPos.x,worldPos.y,worldPos.z) - float3(_obstacle.x,_obstacle.y,_obstacle.z));//direction of obstacle bend
                //float distLimit = _affectDist;// how far away does obstacle reach
                //float distMulti = (distLimit-min(distLimit,distance(float3(worldPos.x,worldPos.y,worldPos.z),float3(_obstacle.x,_obstacle.y,_obstacle.z))))/distLimit; //distance falloff
                //OBSTACLE AVOIDANCE END
                 
                // This is the input to the sinusiodal warp
                float4 waves;
                waves = worldPos.x * _waveXSize;
                waves += worldPos.z * _waveZSize;
               
                // Add in time to model them over time
                waves += _Time.x * waveSpeed;
               
                float4 s, c;
                waves = frac (waves);
                FastSinCos (waves, s,c);
               
                float waveAmount = v.texcoord.y;
                s *= waveAmount;
               
                // Fast winds move the grass more than slow winds
                s *= normalize (waveSpeed);
               
                s = s * s;
                float fade = dot (v.texcoord.y * v.texcoord.y, 2);
                s = s * s;
                float3 waveMove = float3 (0,0,0);
                waveMove.x = dot (s, _waveXmove);
                waveMove.z = dot (s, _waveZmove);
                 
                v.vertex.xz -= mul ((float3x3)_World2Object, waveMove).xz;
                //v.vertex.xz += bendDir.xz * distMulti * v.texcoord.y * v.texcoord.y * _bendAmount; //ADD OBSTACLE BENDING
               
                //optional y bending
                //v.vertex.xyz += bendDir.xyz * distMulti * v.texcoord.y * v.texcoord.y * _bendAmount; //ADD OBSTACLE BENDING
               
                //o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                //o.fog = o.pos.w;
                //o.uv = v.texcoord;
                //o.color = lerp (_Color, _Color2, fade.xxxx);
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				fixed4 col = tex2D(_MainTex, i.texcoord);
				clip(col.a - _Cutoff);
				return col;
			}
		ENDCG
	}
}
Fallback "Unlit/Transparent Cutout"
}

Here is the shader/scripts that ended up working for me. Its modified version of the shader found in the “Palm Trees Pack” which you can get for Free on the Asset Store.

Shader "Custom/WavingDoublePass" {
Properties {
	_MainTex ("Base (RGB) Alpha (A)", 2D) = "white" {}
	_WaveAndDistance ("Wave and distance", Vector) = (12, 3.6, 1, 1)
	_Cutoff ("Cutoff", float) = 0.5
}

SubShader
	{
		Tags{"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
		
		Lighting Off
					
		CGPROGRAM
		#pragma surface surf Lambert vertex:AtsWavingGrassVert addshadow
		#include "TerrainEngine.cginc"
		#include "wavingAlpha.cginc"
		
		
		
		struct Input 
		{
		  float2 uv_MainTex;
		};
		sampler2D _MainTex;
		fixed _Cutoff;
		
		
		void surf (Input IN, inout SurfaceOutput o) {
		  clip(tex2D (_MainTex, IN.uv_MainTex).a - _Cutoff);
		  o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgba;
		  o.Emission = 0;
		}
		ENDCG
	}

	Fallback "Unlit/Transparent Cutout"
}

wavingAlpha.cginc

void AtsWavingGrassVert (inout appdata_full v) {
	////////// start bending
	float4 _waveXSizeMove = float4(0.048, 0.06, 0.24, 0.096);
	float4 _waveZSizeMove = float4 (0.024, .08, 0.08, 0.2);
	float4 waveSpeed = float4 (1.2, 2, 1.6, 4.8);
	float4 waves;
	waves = v.vertex.x * _waveXSizeMove;
	waves += v.vertex.z * _waveZSizeMove;
	_waveXSizeMove = float4(0.024, 0.04, -0.12, 0.096);
	_waveZSizeMove = float4 (0.006, .02, -0.02, 0.1);
	
	// Add in time to model them over time
	waves += _WaveAndDistance.x * waveSpeed;
	float4 s, c;
	waves = frac (waves);
	FastSinCos (waves, s,c);
	float waveAmount = v.color.a * _WaveAndDistance.z;

	// Faster winds move the grass more than slow winds 
	s *= normalize (waveSpeed);
	s = s * s;
	
	float lighting = dot (s, normalize (float4 (1,1,.4,.2))) * .7;
	s *= waveAmount;
	
	fixed3 waveColor = lerp (fixed3(0.5,0.5,0.5), _WavingTint.rgb, lighting);
	
	v.color.rgb = v.color.rgb * waveColor * 2;
	
	float3 waveMove = float3 (0,0,0);
	waveMove.x = dot (s, _waveXSizeMove);
	waveMove.z = dot (s, _waveZSizeMove);
	v.vertex.xz -= mul ((float3x3)_World2Object, waveMove).xz * 8;
	////////// end bending
}

Waving Animation Script

using UnityEngine;
using System.Collections;

public class WavingAnimationScript : MonoBehaviour {

	public Shader shader;
	public Material mat;
	

	// Update is called once per frame
	void Update () {

		Vector4 waving = mat.GetVector("_WaveAndDistance");
		float wavingPower = waving.w;

		float wavingMod = Time.deltaTime*0.10f*wavingPower*Random.value;
		waving.x += wavingMod;
		waving.y -= wavingMod;

		mat.SetVector("_WaveAndDistance", new Vector4(waving.x,waving.y,waving.z,waving.w));	
	}
}

Maybe Shader error in ‘Custom/Unlit/Transparent Cutout Wave’: Program ‘frag’, unknown semantics “SV_Target” specified for “frag” at line 151?

BTW, too many float for a mobile! Use fixed and half, if you can