Shader HLSL | Outline Pixel Art Shader


This shader was made for Zeoland, a 2D retro style tactics game, still in development. I’m in charge of all the programming and effects. Raul, the game’s artist, wanted each character when selected to have a white outline, this both has a unique look and allows for a clearer visual effect for the player.

The problem was the outline was going to be done by hand and an additional animation would need to be provided for every character. This would cost a lot of resources, I decided that a shader would be necessary to reduce the extra asset load.

As I started thinking about solving the problem with a shader, I realized it would be fairly simple to create this effect. I just needed all the frames of the animation to have a 1-pixel alpha border. This would allow me to return a color (white) in the frag function instead of the alpha.

Here you can see the finished product of the outline shader.


Here’s the simple shader, to use it in Unity create a material called “SpriteOutline”, then apply the material to any sprite you wish to have an outline.

Shader "Sprite/Outline" 
	  	_MainTex ("Texture", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)

        _Outline ("Outline", Float) = 0
        _OutlineColor ("Outline Color", Color ) = (1,1,1,1)

        	"RenderType" = "Transparent" 

        Cull Off
        Lighting Off
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 2.0
            #include "UnityCG.cginc"

             sampler2D _MainTex;
             float4 _MainTex_ST;
             float4 _MainTex_TexelSize;
             float4 _Color;

             float _Outline;
             float4 _OutlineColor;

			struct v2f 
                float4  pos : SV_POSITION;
                float2  uv : TEXCOORD0;

            v2f vert (appdata_base IN)
                v2f OUT;

                OUT.pos = mul (UNITY_MATRIX_MVP, IN.vertex);
                OUT.uv = TRANSFORM_TEX(IN.texcoord, _MainTex);

                return OUT;

            fixed4 frag(v2f IN) : SV_Target
            	fixed4 col = tex2D(_MainTex, IN.uv) * _Color;

            	if ( _Outline > 0 && col.a == 0)
            		fixed4 pixelUp = tex2D( _MainTex, IN.uv + fixed2(0,_MainTex_TexelSize.y));
                	fixed4 pixelDown = tex2D( _MainTex, IN.uv - fixed2(0,_MainTex_TexelSize.y));
                	fixed4 pixelRight = tex2D( _MainTex, IN.uv + fixed2(_MainTex_TexelSize.x,0));
                	fixed4 pixelLeft = tex2D( _MainTex, IN.uv - fixed2(_MainTex_TexelSize.x,0));
                	if ( pixelUp.a != 0 || pixelDown.a != 0  || pixelRight.a != 0  || pixelLeft.a != 0)
                		col.rgba = _OutlineColor;

            	return col;
	FallBack "Diffuse"


To add and remove the outline from your sprite you need to modify the “_Outline” property of the shader.

Here’s a simple script that will allow you to turn on and off the sprite outline.