This is a simplified shader example (here I use colors instead of light/shadow effect and only 2 sides instead of 4):
Shader "Test/UnlitTest"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_TopColor ("TopColor", Color) = (1, 0, 0, 1)
_BottomColor ("_BottomColor", Color) = (0, 0, 1, 1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
ZTest Off
ZWrite Off
Lighting Off
Cull Off
Fog { Mode Off }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _MainTex_TexelSize;
fixed4 _TopColor, _BottomColor;
struct vertData
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct fragData
{
float2 uv : TEXCOORD0;
float2 uvW : TEXCOORD1;
float4 vertex : SV_POSITION;
};
fragData vert (vertData v)
{
fragData f;
f.vertex = UnityObjectToClipPos(v.vertex);
f.uv = TRANSFORM_TEX(v.uv, _MainTex);
f.uvW = mul(unity_ObjectToWorld, f.uv);
return f;
}
fixed isTransparentPixel(fixed2 uv)
{
return step(tex2D(_MainTex, uv).a, 0.0);
}
fixed isEdgePixel(fixed2 uv)
{
uv = mul(unity_WorldToObject, uv); // back to object space
return isTransparentPixel(uv);
}
fixed4 frag (fragData f) : SV_Target
{
fixed isTransparent = isTransparentPixel(f.uv);
clip(-isTransparent);
fixed4 c = tex2D(_MainTex, f.uv);
float2 borderSize = float2(3, 3); // border size in tex pixels
float dy = borderSize.y * _MainTex_TexelSize.y;
fixed3 borderColor = fixed3(0, 0, 0);
float borderColorsCount = 0;
float2 uvW = f.uvW; // UV in the world space
// Top edge:
fixed isEdge = isEdgePixel(uvW + float2(0, dy));
borderColor += isEdge * _TopColor.rgb;
borderColorsCount += isEdge;
// Bottom edge:
isEdge = isEdgePixel(uvW + float2(0, -dy));
borderColor += isEdge * _BottomColor.rgb;
borderColorsCount += isEdge;
fixed noBorderColor = step(length(borderColor), 0);
fixed hasBorderColor = 1 - noBorderColor;
c.rgb = c.rgb * noBorderColor + hasBorderColor * borderColor / max(borderColorsCount, 1);
return c;
}
ENDCG
}
}
}
It gets a semi-transparent image as a texture. The image is completely transparent at the edges and contains an opaque shape in the center.
The shader colors the top edges of the non-transparent shape in red and the bottom ones in yellow. It uses unity_WorldToObject & unity_ObjectToWorld to check the edges facing directions in the world space.


