Sprite Masking with and without Stencil

I am trying to mask a sprite with a mask. It works if it is the only game object on screen, but if I create multiple copies of the same game object it doesn’t work if they overlap. Do I need a unique stencil ID for each game object? If so how do I set stencil ref through script? It also only lets me set 0-255. This should be fine but what if I have more than 255 unique refs?

So far I know of 2 ways to achieve sprite masking:

  1. Use stencil in shader but this requires having 2 separate sprite gameobjects (1 for mask, 1 for portrait)
  2. Use a mesh that is shaped for the desired sprite and then use UV map to cutoff the unwanted areas.
    Are there any other methods for sprite masking?

I am not upgrading Unity to 2017 as it is a subscription model and I want to keep perpetual Unity.

This is the issue:

Notice square.

Here is the code:

SpriteMask

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

Shader "Custom/SpriteMask" {
    Properties {
        [PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
        _Color("Tint", Color) = (1,1,1,1)
        [MaterialToggle] PixelSnap("Pixel snap", Float) = 0
        [HideInInspector] _RendererColor("RendererColor", Color) = (1,1,1,1)
        [HideInInspector] _Flip("Flip", Vector) = (1,1,1,1)
        [PerRendererData] _AlphaTex("External Alpha", 2D) = "white" {}
        [PerRendererData] _EnableExternalAlpha("Enable External Alpha", Float) = 0
    }
    SubShader {
        Pass {
            ZWrite Off
            Stencil {
                Ref 1
            Comp always
            Pass replace
            }
        }
    }
}

SpritePortrait

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

Shader "Custom/SpritePortrait" {
    Properties {
        [PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
        _Color("Tint", Color) = (1,1,1,1)
        [MaterialToggle] PixelSnap("Pixel snap", Float) = 0
        [HideInInspector] _RendererColor("RendererColor", Color) = (1,1,1,1)
        [HideInInspector] _Flip("Flip", Vector) = (1,1,1,1)
        [PerRendererData] _AlphaTex("External Alpha", 2D) = "white" {}
        [PerRendererData] _EnableExternalAlpha("Enable External Alpha", Float) = 0
    }

    SubShader {
        Tags {
            "Queue" = "Transparent"
            "IgnoreProjector" = "True"
            "RenderType" = "Transparent"
            "PreviewType" = "Plane"
            "CanUseSpriteAtlas" = "True"
        }

        Cull Off
        Lighting Off
        ZWrite Off
        Blend One OneMinusSrcAlpha

        Pass {
            Stencil {
                Ref 1
                Comp Equal
            }
            CGPROGRAM
            #pragma vertex SpriteVert
            #pragma fragment SpriteFrag
            #pragma target 2.0
            #pragma multi_compile_instancing
            #pragma multi_compile _ PIXELSNAP_ON
            #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
            #include "UnitySprites.cginc"
            ENDCG
        }
    }
}

Actually, the limit would be 8. The stencil buffer works like a binary mask, so you can only use the values 1, 2, 4, 8, 16, 32, 64 and 128.

thanks you so much I’m looking for this all day long.