How to (really) force forward rendering in shader?

Sorry in advance for the long post…

First some background:

I’ve been trying a lot with a Surface Shader that:

  • Moves its vertices.
  • Uses a custom lighting model for
    specularity.
  • Uses a first pass to draw color and
    write depth.
  • Uses a second pass to draw
    alpha-blended and depth-testing.
  • Is all forward rendered because of
    the alpha blended second pass.

Problem: when enabled Deferred mode in Unity, it seems the depth is being rendered with vertices in their original positions, so that when “real” vertices actually are behind those “imaginary” vertices, they are not being drawn (or at least it looks like this is the behaviour).

I haven’t written a _PrePass lighting model function because, if it doesn’t exist, it will just render in forward mode, which is what I want, according to the manual.

For narrowing the problem down, I’ve tried with example shaders from doc, which I think are proven enough to be reliable. Haven’t found any that moves vertices and also has a view dependant lighting model (specular), so I combined a couple into this one:

Shader "SimpleSpec" 
{
	Properties 
	{
		_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
		_SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 0)
	}
	
	SubShader
	{	
		Tags { "RenderType"="Opaque"}
		
		Cull Back
		ZWrite On
		
		CGPROGRAM
		    #pragma surface surf BlinnPhong2 vertex:vert
		    
		    // tried with exclude_path:prepass, it just ignores _PrePass function
		    //#pragma surface surf BlinnPhong2 vertex:vert exclude_path:prepass
			
		    struct Input
		    {
		        float2 uv_MainTex;
		    };
		    
			void vert(inout appdata_full v)
			{
				v.vertex.xyz += v.normal * sin(_Time.y * 2) * 0.005;
			}
			
		   inline fixed4 LightingBlinnPhong2 (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
			{
				half3 h = normalize (lightDir + viewDir);
				fixed diff = max (0, dot (s.Normal, lightDir));
				float nh = max (0, dot (s.Normal, h));
				float spec = pow (nh, s.Specular*128.0) * s.Gloss;
				fixed4 c;
				c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * _SpecColor.rgb * spec) * (atten * 2);
				c.a = s.Alpha + _LightColor0.a * _SpecColor.a * spec * atten;
				return c;
			}
			
			inline fixed4 LightingBlinnPhong2_PrePass (SurfaceOutput s, half4 light)
			{
				fixed spec = light.a * s.Gloss;
				fixed4 c;
				c.rgb = (s.Albedo * light.rgb + light.rgb * _SpecColor.rgb * spec);
				c.a = s.Alpha + spec * _SpecColor.a;
				return c;
			}
		    
		    sampler2D _MainTex;
		    
		    void surf (Input IN, inout SurfaceOutput o) {
		        o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
		        o.Gloss = 1;
		        o.Specular = _SpecColor;
		    }
	    ENDCG
	}
}

This shader looks ok while the _PrePass function exists, but presents the described problem otherwise.

So, my final question is: how should I force my vertex-moving-plus-specular shader to forward mode, while still being able to use deferred in the rest of my project?

PS: It works perfectly fine with forward mode under Windows, and with any render path under Mac OS X, so I suspect this is a bug, but I would like to know if anyone has encountered this problem before and/or your opinions.

Ok, it has been answered in the forums:

http://forum.unity3d.com/threads/how-to-really-force-forward-rendering-in-shader.270563/