How to allow an overlapping object's edge to show in front of another object with the same shader.

This is what it looks like currently, but I want the black outline to outline the whole sphere when in front of the other object in the scene.

172289-unity-answers-pic.jpg


Here is my shader coder:

Shader "test/shader"
{
    Properties
	{
		_Color("Color", Color) = (1,1,1,1)
		_LightPosition("Light Position", Vector) = (0,0,0,0)
		_OutLineColor("Outline Color", Color) = (0,0,0,1)
		_OutlineThickness("Outline Thickness", Range(1,1.5)) = 1.1
	}

	SubShader
	{
		Pass //Outline
		{
			ZWrite Off

			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
				float3 normal : NORMAL;
			};
			struct v2f
			{
				float4 position : SV_POSITION;
				float2 uv : TEXCOORD0;
				float3 normal : NORMAL;
			};

			fixed4 _OutLineColor;
			fixed4 _OutlineThickness;

			v2f vert(appdata IN)
			{
				v2f OUT;
				OUT.normal = IN.normal;
				OUT.position = UnityObjectToClipPos(IN.vertex * 1.1);
				OUT.uv = IN.uv;

				return OUT;
			}

			fixed4 frag(v2f IN) : SV_Target
			{
				float3 outlineColor = _OutLineColor.rgb;
				return float4(outlineColor, 1);
			}

			ENDCG
		}

		Pass //Main
		{
			CGPROGRAM

			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
				float3 normal : NORMAL;
			};

			struct v2f 
			{
				float4 position : SV_POSITION;
				float2 uv : TEXCOORD0;
				float3 normal : NORMAL;
			};

			fixed4 _Color;
			float4 _LightPosition;
			
			v2f vert(appdata IN)
			{
				v2f OUT;
				OUT.normal = IN.normal;
				OUT.position = UnityObjectToClipPos(IN.vertex);
				OUT.uv = IN.uv;

				return OUT;
			}

			fixed4 frag(v2f IN) : SV_Target
			{
				//Direct Light
				float3 lightDir = _WorldSpaceLightPos0.xyz;
				float3 color = _Color.rgb;
				fixed3 lightFalloff = saturate(dot(lightDir, IN.normal));
				lightFalloff = step(0.1, lightFalloff);
				float3 directDiffuseLight = color * lightFalloff;

				//Ambient light
				float3 ambientLight = float3(0.1,0.1,0.1);

				//Composite
				float3 diffuseLight = ambientLight + directDiffuseLight;
				float3 finalSurfaceColor = diffuseLight * color;
				float1 zero = 0;
				return float4(finalSurfaceColor, zero);
			}

			ENDCG
		}
	}
}

I believe the problem lies at the beginning of the first pass, the “ZWrite Off” specifically. But the thing is that I believe that is necessary in order for the upscaled mesh to appear behind the main mesh, and maybe that is why the upscaled/outline mesh appears behind other objects with the same shader.

Is there a simple fix to this?

I figured it out for anyone having the same problem. I flipped the passes around so that the second pass was the outline. Then I replaced “Zwrite Off” with “Cull Front”.


Even though that solved that specific problem, don’t use my shader script, as the way it is written requires objects that have equal height, width, and depth. If the dimensions are different then the outline thickness will also be different.