Search Unity

Outline on Sprite Mask when switching from Discard to Alpha

Discussion in 'Shaders' started by HaileyHurt, Mar 3, 2017.

  1. HaileyHurt

    HaileyHurt

    Joined:
    Aug 6, 2016
    Posts:
    5
    I am using the following shaders to mask two sprites:
    Code (CSharp):
    1. Shader "Sprites/Stencil Mask"
    2. {
    3.     Properties
    4.     {
    5.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    6.         _Color ("Tint", Color) = (1,1,1,1)
    7.         [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    8.     }
    9.     SubShader
    10.     {
    11.         Tags
    12.         {
    13.             "Queue"="Transparent"
    14.             "IgnoreProjector"="True"
    15.             "RenderType"="Transparent"
    16.             "PreviewType"="Plane"
    17.             "CanUseSpriteAtlas"="True"
    18.         }
    19.         Cull Off
    20.         Lighting Off
    21.         ZWrite Off
    22.         Fog { Mode Off }
    23.         Blend SrcAlpha OneMinusSrcAlpha
    24.         Pass
    25.         {
    26.             Stencil
    27.             {
    28.                 Ref 1
    29.                 Comp always
    30.                 Pass replace
    31.             }
    32.    
    33.         CGPROGRAM
    34.             #pragma vertex vert
    35.             #pragma fragment frag
    36.             #pragma multi_compile DUMMY PIXELSNAP_ON
    37.             #include "UnityCG.cginc"
    38.    
    39.             struct appdata_t
    40.             {
    41.                 float4 vertex   : POSITION;
    42.                 float4 color    : COLOR;
    43.                 float2 texcoord : TEXCOORD0;
    44.             };
    45.             struct v2f
    46.             {
    47.                 float4 vertex   : SV_POSITION;
    48.                 fixed4 color    : COLOR;
    49.                 half2 texcoord  : TEXCOORD0;
    50.             };
    51.    
    52.             fixed4 _Color;
    53.             v2f vert(appdata_t IN)
    54.             {
    55.                 v2f OUT;
    56.                 OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
    57.                 OUT.texcoord = IN.texcoord;
    58.                 OUT.color = IN.color * _Color;
    59.                 #ifdef PIXELSNAP_ON
    60.                 OUT.vertex = UnityPixelSnap (OUT.vertex);
    61.                 #endif
    62.                 return OUT;
    63.             }
    64.             sampler2D _MainTex;
    65.             fixed4 frag(v2f IN) : SV_Target
    66.             {
    67.                 fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;
    68.                 if (c.a<0.1) discard;            //Most IMPORTANT working Code
    69.                 c.rgb *= c.a;
    70.                 return c;
    71.             }
    72.         ENDCG
    73.         }
    74.     }
    75. }
    76.  
    Code (CSharp):
    1. Shader "Sprites/Stencil Draw In Mask"
    2. {
    3.     Properties
    4.     {
    5.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    6.         _Color ("Tint", Color) = (1,1,1,1)
    7.         [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    8.     }
    9.     SubShader
    10.     {
    11.         Tags
    12.         {
    13.             "Queue"="Transparent+1"              //DON'T FORGET this must be drew later to catch Stencil Ref value.
    14.             "IgnoreProjector"="True"
    15.             "RenderType"="Transparent"
    16.             "PreviewType"="Plane"
    17.             "CanUseSpriteAtlas"="True"
    18.         }
    19.         Cull Off
    20.         Lighting Off
    21.         ZWrite Off
    22.         Fog { Mode Off }
    23.         Blend One One
    24.         Pass
    25.         {
    26.             Stencil
    27.             {
    28.                 Ref 1
    29.                 Comp Equal
    30.             }
    31.         CGPROGRAM
    32.             #pragma vertex vert
    33.             #pragma fragment frag
    34.             #pragma multi_compile DUMMY PIXELSNAP_ON
    35.             #include "UnityCG.cginc"
    36.    
    37.             struct appdata_t
    38.             {
    39.                 float4 vertex   : POSITION;
    40.                 float4 color    : COLOR;
    41.                 float2 texcoord : TEXCOORD0;
    42.             };
    43.             struct v2f
    44.             {
    45.                 float4 vertex   : SV_POSITION;
    46.                 fixed4 color    : COLOR;
    47.                 half2 texcoord  : TEXCOORD0;
    48.             };
    49.    
    50.             fixed4 _Color;
    51.             v2f vert(appdata_t IN)
    52.             {
    53.                 v2f OUT;
    54.                 OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
    55.                 OUT.texcoord = IN.texcoord;
    56.                 OUT.color = IN.color * _Color;
    57.                 #ifdef PIXELSNAP_ON
    58.                 OUT.vertex = UnityPixelSnap (OUT.vertex);
    59.                 #endif
    60.                 return OUT;
    61.             }
    62.             sampler2D _MainTex;
    63.             fixed4 frag(v2f IN) : SV_Target
    64.             {
    65.                 fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;
    66.                 c.rgb *= c.a;
    67.                 return c;
    68.             }
    69.         ENDCG
    70.         }
    71.     }
    72. }

    This worked fine on my iPhone 6S but not on older devices like my iPhone 5 running iOS 7. I read that this was because of the Discard statement and that I should instead set the alpha to zero.
    I did this, but then I get an outline around my object. I have tried to disable anti aliasing to troubleshoot, but that did not work.
    My new shader (only changed that one line from discard to c.a = 0)
    Code (CSharp):
    1. Shader "Sprites/Stencil Mask"
    2. {
    3.     Properties
    4.     {
    5.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    6.         _Color ("Tint", Color) = (1,1,1,1)
    7.         [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    8.     }
    9.     SubShader
    10.     {
    11.         Tags
    12.         {
    13.             "Queue"="Transparent"
    14.             "IgnoreProjector"="True"
    15.             "RenderType"="Transparent"
    16.             "PreviewType"="Plane"
    17.             "CanUseSpriteAtlas"="True"
    18.         }
    19.         Cull Off
    20.         Lighting Off
    21.         ZWrite Off
    22.         Fog { Mode Off }
    23.         Blend SrcAlpha OneMinusSrcAlpha
    24.         Pass
    25.         {
    26.             Stencil
    27.             {
    28.                 Ref 1
    29.                 Comp always
    30.                 Pass replace
    31.             }
    32.    
    33.         CGPROGRAM
    34.             #pragma vertex vert
    35.             #pragma fragment frag
    36.             #pragma multi_compile DUMMY PIXELSNAP_ON
    37.             #include "UnityCG.cginc"
    38.    
    39.             struct appdata_t
    40.             {
    41.                 float4 vertex   : POSITION;
    42.                 float4 color    : COLOR;
    43.                 float2 texcoord : TEXCOORD0;
    44.             };
    45.             struct v2f
    46.             {
    47.                 float4 vertex   : SV_POSITION;
    48.                 fixed4 color    : COLOR;
    49.                 half2 texcoord  : TEXCOORD0;
    50.             };
    51.    
    52.             fixed4 _Color;
    53.             v2f vert(appdata_t IN)
    54.             {
    55.                 v2f OUT;
    56.                 OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
    57.                 OUT.texcoord = IN.texcoord;
    58.                 OUT.color = IN.color * _Color;
    59.                 #ifdef PIXELSNAP_ON
    60.                 OUT.vertex = UnityPixelSnap (OUT.vertex);
    61.                 #endif
    62.                 return OUT;
    63.             }
    64.             sampler2D _MainTex;
    65.             fixed4 frag(v2f IN) : SV_Target
    66.             {
    67.                 fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;
    68.                 if (c.a<0.1) c.a = 0;            //Most IMPORTANT working Code
    69.                 c.rgb *= c.a;
    70.                 return c;
    71.             }
    72.         ENDCG
    73.         }
    74.     }
    75. }
    76.  
    results before (with discard):

    results after (with c.a=0):



    How can I get a clean sprite mask without using discard? And ideally avoiding Clip too since there are android issues with it

    Thank you :)
     
    Last edited: Mar 3, 2017
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    Alpha has no effect on the stencil, you must use clip() or discard() to prevent stencils from applying. There is no way to avoid that when using stencils.
     
  3. HaileyHurt

    HaileyHurt

    Joined:
    Aug 6, 2016
    Posts:
    5