We need some help, by creating a double sided mobile shader, with a normal and specular map. That is our current shader, it works in general, but not on all mobile devices. On some devices, the shader doesnt work and the mesh is just black. We use directional light in our scenes. If someone could help us out there, it would be great Shader "DoubleSiderShader" { Properties { _DiffuseBase ("Diffuse Base", 2D) = "white" {} _NormalMap ("Normal Map", 2D) = "bump" {} _Specular ("Specular", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } Pass { Name "FORWARD" Tags { "LightMode"="ForwardBase" } Cull Off CGPROGRAM #pragma vertex vert #pragma fragment frag #define UNITY_PASS_FORWARDBASE #include "UnityCG.cginc" #include "AutoLight.cginc" #pragma multi_compile_fwdbase_fullshadows #pragma exclude_renderers xbox360 xboxone ps3 ps4 psp2 #pragma target 2.0 uniform float4 _LightColor0; uniform sampler2D _DiffuseBase; uniform float4 _DiffuseBase_ST; uniform sampler2D _NormalMap; uniform float4 _NormalMap_ST; uniform sampler2D _Specular; uniform float4 _Specular_ST; struct VertexInput { float4 vertex : POSITION; float3 normal : NORMAL; float4 tangent : TANGENT; float2 texcoord0 : TEXCOORD0; }; struct VertexOutput { float4 pos : SV_POSITION; float2 uv0 : TEXCOORD0; float4 posWorld : TEXCOORD1; float3 normalDir : TEXCOORD2; float3 tangentDir : TEXCOORD3; float3 bitangentDir : TEXCOORD4; LIGHTING_COORDS(5,6) }; VertexOutput vert (VertexInput v) { VertexOutput o = (VertexOutput)0; o.uv0 = v.texcoord0; o.normalDir = UnityObjectToWorldNormal(v.normal); o.tangentDir = normalize( mul( _Object2World, float4( v.tangent.xyz, 0.0 ) ).xyz ); o.bitangentDir = normalize(cross(o.normalDir, o.tangentDir) * v.tangent.w); o.posWorld = mul(_Object2World, v.vertex); float3 lightColor = _LightColor0.rgb; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); TRANSFER_VERTEX_TO_FRAGMENT(o) return o; } float4 frag(VertexOutput i) : COLOR { i.normalDir = normalize(i.normalDir); float3x3 tangentTransform = float3x3( i.tangentDir, i.bitangentDir, i.normalDir); /////// Vectors: float3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz); float3 _NormalMap_var = UnpackNormal(tex2D(_NormalMap,TRANSFORM_TEX(i.uv0, _NormalMap))); float3 normalLocal = _NormalMap_var.rgb; float3 normalDirection = normalize(mul( normalLocal, tangentTransform )); // Perturbed normals float nSign = sign( dot( viewDirection, i.normalDir ) ); // Reverse normal if this is a backface i.normalDir *= nSign; normalDirection *= nSign; float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz); float3 lightColor = _LightColor0.rgb; float3 halfDirection = normalize(viewDirection+lightDirection); ////// Lighting: float attenuation = LIGHT_ATTENUATION(i); float3 attenColor = attenuation * _LightColor0.xyz; ///////// Gloss: float gloss = 0.5; float specPow = exp2( gloss * 10.0+1.0); ////// Specular: float NdotL = max(0, dot( normalDirection, lightDirection )); float4 _Specular_var = tex2D(_Specular,TRANSFORM_TEX(i.uv0, _Specular)); float3 specularColor = _Specular_var.rgb; float3 directSpecular = attenColor * pow(max(0,dot(halfDirection,normalDirection)),specPow)*specularColor; float3 specular = directSpecular; /////// Diffuse: NdotL = max(0.0,dot( normalDirection, lightDirection )); float3 directDiffuse = max( 0.0, NdotL) * attenColor; float3 indirectDiffuse = float3(0,0,0); indirectDiffuse += UNITY_LIGHTMODEL_AMBIENT.rgb; // Ambient Light float4 _DiffuseBase_var = tex2D(_DiffuseBase,TRANSFORM_TEX(i.uv0, _DiffuseBase)); float3 diffuseColor = _DiffuseBase_var.rgb; float3 diffuse = (directDiffuse + indirectDiffuse) * diffuseColor; /// Final Color: float3 finalColor = diffuse + specular; return fixed4(finalColor,1); } ENDCG } Pass { Name "FORWARD_DELTA" Tags { "LightMode"="ForwardAdd" } Blend One One Cull Off CGPROGRAM #pragma vertex vert #pragma fragment frag #define UNITY_PASS_FORWARDADD #include "UnityCG.cginc" #include "AutoLight.cginc" #pragma multi_compile_fwdadd_fullshadows #pragma exclude_renderers xbox360 xboxone ps3 ps4 psp2 #pragma target 2.0 uniform float4 _LightColor0; uniform sampler2D _DiffuseBase; uniform float4 _DiffuseBase_ST; uniform sampler2D _NormalMap; uniform float4 _NormalMap_ST; uniform sampler2D _Specular; uniform float4 _Specular_ST; struct VertexInput { float4 vertex : POSITION; float3 normal : NORMAL; float4 tangent : TANGENT; float2 texcoord0 : TEXCOORD0; }; struct VertexOutput { float4 pos : SV_POSITION; float2 uv0 : TEXCOORD0; float4 posWorld : TEXCOORD1; float3 normalDir : TEXCOORD2; float3 tangentDir : TEXCOORD3; float3 bitangentDir : TEXCOORD4; LIGHTING_COORDS(5,6) }; VertexOutput vert (VertexInput v) { VertexOutput o = (VertexOutput)0; o.uv0 = v.texcoord0; o.normalDir = UnityObjectToWorldNormal(v.normal); o.tangentDir = normalize( mul( _Object2World, float4( v.tangent.xyz, 0.0 ) ).xyz ); o.bitangentDir = normalize(cross(o.normalDir, o.tangentDir) * v.tangent.w); o.posWorld = mul(_Object2World, v.vertex); float3 lightColor = _LightColor0.rgb; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); TRANSFER_VERTEX_TO_FRAGMENT(o) return o; } float4 frag(VertexOutput i) : COLOR { i.normalDir = normalize(i.normalDir); float3x3 tangentTransform = float3x3( i.tangentDir, i.bitangentDir, i.normalDir); /////// Vectors: float3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz); float3 _NormalMap_var = UnpackNormal(tex2D(_NormalMap,TRANSFORM_TEX(i.uv0, _NormalMap))); float3 normalLocal = _NormalMap_var.rgb; float3 normalDirection = normalize(mul( normalLocal, tangentTransform )); // Perturbed normals float nSign = sign( dot( viewDirection, i.normalDir ) ); // Reverse normal if this is a backface i.normalDir *= nSign; normalDirection *= nSign; float3 lightDirection = normalize(lerp(_WorldSpaceLightPos0.xyz, _WorldSpaceLightPos0.xyz - i.posWorld.xyz,_WorldSpaceLightPos0.w)); float3 lightColor = _LightColor0.rgb; float3 halfDirection = normalize(viewDirection+lightDirection); ////// Lighting: float attenuation = LIGHT_ATTENUATION(i); float3 attenColor = attenuation * _LightColor0.xyz; ///////// Gloss: float gloss = 0.5; float specPow = exp2( gloss * 10.0+1.0); ////// Specular: float NdotL = max(0, dot( normalDirection, lightDirection )); float4 _Specular_var = tex2D(_Specular,TRANSFORM_TEX(i.uv0, _Specular)); float3 specularColor = _Specular_var.rgb; float3 directSpecular = attenColor * pow(max(0,dot(halfDirection,normalDirection)),specPow)*specularColor; float3 specular = directSpecular; /////// Diffuse: NdotL = max(0.0,dot( normalDirection, lightDirection )); float3 directDiffuse = max( 0.0, NdotL) * attenColor; float4 _DiffuseBase_var = tex2D(_DiffuseBase,TRANSFORM_TEX(i.uv0, _DiffuseBase)); float3 diffuseColor = _DiffuseBase_var.rgb; float3 diffuse = directDiffuse * diffuseColor; /// Final Color: float3 finalColor = diffuse + specular; return fixed4(finalColor * 1,0); } ENDCG } } FallBack "Diffuse" CustomEditor "ShaderForgeMaterialInspector" }