Multiple target platform lightmap shader

I have a shader with subShaders when lightmap is on and off:

Shader "Alpha Blending Light=Off, Cull=Off, ZWrite=Off" {
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
	}
	SubShader {
		Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }

		Pass {
			Tags { "LightMode"="Vertex"}		
			Lighting Off
			Cull Off
			ZWrite Off
			Blend SrcAlpha OneMinusSrcAlpha
			SetTexture [_MainTex] {}
		}
	}
	SubShader {
		Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }

		Pass {
			Tags { "LightMode"="VertexLMRGBM"}		
			Lighting Off
			Cull Off
			ZWrite Off
			Blend SrcAlpha OneMinusSrcAlpha
			SetTexture [_MainTex] {}
		}
	}	
	SubShader {
		Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }

		Pass {
			Tags { "LightMode"="VertexLM"}		
			Lighting Off
			Cull Off
			ZWrite Off
			Blend SrcAlpha OneMinusSrcAlpha
			SetTexture [_MainTex] {}
		}
	}	
}

When lightmap is on, it appears Unity picks up the first lightmap subshader, whether it is compatible or not with the current target platform. Here is what I have:

  • When the subshader with the pass tagged as “LightMode”=“VertexLMRGBM” is first in the shader, it works on Web player but not on iOS (objects on which the shader is applied to are disappearing both from the Editor and the build).

  • When the subshader with the pass tagged as LightMode"="VertexLM is first in the shader, it works on iOS but not on the Web player.

How to write properly the shader so that it is compatible both for Web player and iOS?

Why are you putting all these passes into separate subshaders? Put them into one subshader. Just like built-in VertexLit shaders do.

Of course! Thanks.

Hi there, I have the same problem: Unity picks the first subshader using lightmaps, no matter if it doesn’t work on the current platform.

But I’m using surface shaders, since my shader does some additional operations that are not possible with ShaderLab code. I read somewhere else that it’s not possible to make a multipass surface shader. So how do I solve this problem? I need the code to work both on PC and mobile… ATM it either does one or the other (depending on which subshader I put first: VerexLMRGB or VertexLM… ).

Here’s my code (The actual functionality of the shader is not so important, only the three subshaders and their LightMode):

Shader "CURE/Level Geometry Transp" {
Properties {
	_BlackNear ("_BlackNear", Float) = 0 
	_BlackDepth ("_BlackDepth", Float) = 10 
	_MainTex ("_MainTex", 2D) = "white" {}
	_BlackTex ("_BlackTex", 2D) = "white" {}
}

SubShader {
	Tags { "RenderType"="Transparent" "Queue"="Transparent" "LightMode"="Vertex" }
	Blend SrcAlpha OneMinusSrcAlpha
	ZWrite Off
	Offset -1, -1
	
	CGPROGRAM
	#pragma surface surf Unlit
	
	struct Input {
	  fixed2 uv_MainTex;
	  fixed3 worldPos;
	};
	
	sampler2D _MainTex;
	sampler2D _BlackTex;
	fixed _BlackNear;
	fixed _BlackDepth;
	
	void surf (Input IN, inout SurfaceOutput o) {
		fixed4 blackTex = tex2D (_BlackTex, half2(0, (IN.worldPos.z - _BlackNear) / _BlackDepth));
	 	fixed4 mainTex = tex2D (_MainTex, IN.uv_MainTex);
	 	o.Albedo = mainTex.rgb * blackTex.rgb;
	 	o.Alpha = mainTex.a;
	}
	 
	fixed4 LightingUnlit_PrePass (SurfaceOutput s, half atten) 
	{	
		return fixed4(s.Albedo,s.Alpha);
	}
	
	ENDCG 
}

SubShader {
	Tags { "RenderType"="Opaque" "LightMode"="VertexLM" }
	Blend SrcAlpha OneMinusSrcAlpha
	ZWrite Off
	Offset -1, -1
	
	CGPROGRAM
	#pragma surface surf Unlit
	
	struct Input {
	  fixed2 uv_MainTex;
	  fixed3 worldPos;
	};
	
	sampler2D _MainTex;
	sampler2D _BlackTex;
	fixed _BlackNear;
	fixed _BlackDepth;
	
	void surf (Input IN, inout SurfaceOutput o) {
		fixed4 blackTex = tex2D (_BlackTex, half2(0, (IN.worldPos.z - _BlackNear) / _BlackDepth));
	 	fixed4 mainTex = tex2D (_MainTex, IN.uv_MainTex);
	 	o.Albedo = mainTex.rgb * blackTex.rgb;
	 	o.Alpha = mainTex.a;
	}
	
	fixed4 LightingUnlit (SurfaceOutput s, half3 lightDir, half atten) 
	{	
		return fixed4(0,0,0,s.Alpha);
	}
	
	fixed4 LightingUnlit_SingleLightmap (SurfaceOutput s, fixed4 color) 
	{	
		fixed3 lm = DecodeLightmap(color);
		return fixed4(lm,s.Alpha);
	}
	
	ENDCG 
}

SubShader {
	Tags { "RenderType"="Opaque" "LightMode"="VertexLMRGBM" }
	Blend SrcAlpha OneMinusSrcAlpha
	ZWrite Off
	Offset -1, -1
	
	CGPROGRAM
	#pragma surface surf Unlit alpha
	
	struct Input {
	  fixed2 uv_MainTex;
	  fixed3 worldPos;
	};
	
	sampler2D _MainTex;
	sampler2D _BlackTex;
	fixed _BlackNear;
	fixed _BlackDepth;
	
	void surf (Input IN, inout SurfaceOutput o) {
		fixed4 blackTex = tex2D (_BlackTex, half2(0, (IN.worldPos.z - _BlackNear) / _BlackDepth));
	 	fixed4 mainTex = tex2D (_MainTex, IN.uv_MainTex);
	 	o.Albedo = mainTex.rgb * blackTex.rgb;
	 	o.Alpha = mainTex.a;
	}
	
	fixed4 LightingUnlit (SurfaceOutput s, half3 lightDir, half atten) 
	{	
		return fixed4(0,0,0,s.Alpha);
	}
	
	fixed4 LightingUnlit_SingleLightmap (SurfaceOutput s, fixed4 color) 
	{	
		fixed3 lm = DecodeLightmap(color);
		return fixed4(lm,s.Alpha);
	}
	
	ENDCG 
}
}