Spec only Shader, Again.

I already asked that question and I got a good awnser using GrabPass and it lead to a great looking water shader but, the big problem is that I am using Unity Free and it seems that GrabPass is not working in executables created by Unity Free.

What I am looking for is a shader that uses 2 bumps and a specular, without any diffuse. The problem is when I put the alpha of the diffuse to 0, it removes the specular as well, thats what I don’t want. So I was asking myself, is there any way to use the specular output as an alpha or some other trick like this that will not require Unity Pro? I don’t really care about the refraction in the water since I know that I will need Unity Pro for that.

And also, if there is no way of getting a spec only map, is there a way to blur the edges between the ground and the water, in Unity Free once again?

Unfortunately, simply setting c.a = spec (or similar) in the lighting model of a surface shader won’t work (in fact, making any change to alpha in the lighting function has no effect, as noted here and here) because the surface shader output always seems to override whatever alpha was set in the lighting function with an additional c.a = o.Alpha; placed at the end of the fragment function.

Instead, you can still write a surface shader that handles only the specular component together with the alpha, something like this:

half4 LightingSpecularOnly (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) {
  half3 h = normalize (lightDir + viewDir);
  half diff = max (0, dot (s.Normal, lightDir));
  float nh = max (0, dot (s.Normal, h));
  float spec = pow (nh, s.Specular*128.0);
  half4 c;
  c.rgb = (_LightColor0.rgb * spec) * (atten * 2);
  c.a = spec;
  return c;

}

But then also add #pragma debug to generate the underlying vertex/fragment shaders from your code. Then simply copy and paste the generated code and remove the offending final c.a = o.Alpha; and you should be good to go. Here’s a quick test:

EDIT as suggested by @Professor Snake below, you can override the c.a = o.Alpha; by using a finalcolor function. Like this:

Shader "Custom/SpecOnly" {
	Properties {
	}
	SubShader {
		Tags { "RenderType"="Transparent" "Queue" = "Transparent"}
		LOD 200
		
		CGPROGRAM
		#pragma surface surf SpecularOnly finalcolor:alphaFix alpha 

		struct Input {
		  half Specular;			
		};

		half4 LightingSpecularOnly (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) {
          half3 h = normalize (lightDir + viewDir);
          half diff = max (0, dot (s.Normal, lightDir));
          float nh = max (0, dot (s.Normal, h));
          float spec = pow (nh, s.Specular*128.0);
          half4 c;
          c.rgb = (_LightColor0.rgb * spec) * (atten * 2);
          c.a = spec;
          return c;
      	}

		void alphaFix (Input IN, SurfaceOutput o, inout fixed4 color) {
    	  color.a = color.rgb;
  		}

		void surf (Input IN, inout SurfaceOutput o) {
			o.Specular = 1;
		}
		ENDCG
	} 
}