Search Unity

2D Graphics - How can I clip a Sprite that's positioned above a Mesh?

Discussion in 'General Graphics' started by kbm, Aug 9, 2015.

  1. kbm

    kbm

    Joined:
    Aug 7, 2014
    Posts:
    84
    I posted this on Unity Answers but nobody could help me, maybe I'll have better luck here:

    I have a character that's animated in Spine (3rd party animation software) and exported to Unity, meaning that the output is a textured, meshed object (no sprite renderer).

    I now have another GameObject that I want to clip inside the character, meaning it SHOULD draw whenever overlapping parts of the character but NOT when outside the character mesh.

    Picture 1 shows what's currently happening:

    51698-patients1.jpg

    Picture 2 shows what I need happening (part of the round object not to show):

    51699-patients2.jpg

    Does anyone have any experience with this and can maybe help? I have thought about buying "Sprite Mask" (from the asset store) but I'm not sure if it would even work for what I need.
     
  2. kuchaku

    kuchaku

    Joined:
    Oct 14, 2014
    Posts:
    37
    The way I'm aware of is having it write to stencil buffer with one shader and read from stencil buffer with the other. I think this would only work in forward rendering though. So an example I use in my project the first would have a shader to set the stencil:

    Code (CSharp):
    1. Shader "Sprites/SpritesUnlitStencilSet"
    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.  
    10.     SubShader
    11.     {
    12.         Tags
    13.         {
    14.             "Queue"="Transparent"
    15.             "IgnoreProjector"="True"
    16.             "RenderType"="Transparent"
    17.             "PreviewType"="Plane"
    18.             "CanUseSpriteAtlas"="True"
    19.         }
    20.  
    21.         Cull Off
    22.         Lighting Off
    23.         ZWrite Off
    24.         Blend One OneMinusSrcAlpha
    25.  
    26.         Pass
    27.         {
    28.          Stencil {
    29.             Ref 254
    30.             Comp always
    31.             Pass replace
    32.         }
    33.        
    34.        
    35.         CGPROGRAM
    36.             #pragma vertex vert
    37.             #pragma fragment frag
    38.             #pragma multi_compile _ PIXELSNAP_ON
    39.             #include "UnityCG.cginc"
    40.            
    41.             struct appdata_t
    42.             {
    43.                 float4 vertex   : POSITION;
    44.                 float4 color    : COLOR;
    45.                 float2 texcoord : TEXCOORD0;
    46.             };
    47.  
    48.             struct v2f
    49.             {
    50.                 float4 vertex   : SV_POSITION;
    51.                 fixed4 color    : COLOR;
    52.                 half2 texcoord  : TEXCOORD0;
    53.             };
    54.            
    55.             fixed4 _Color;
    56.  
    57.             v2f vert(appdata_t IN)
    58.             {
    59.                 v2f OUT;
    60.                 OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
    61.                 OUT.texcoord = IN.texcoord;
    62.                 OUT.color = IN.color * _Color;
    63.                 #ifdef PIXELSNAP_ON
    64.                 OUT.vertex = UnityPixelSnap (OUT.vertex);
    65.                 #endif
    66.  
    67.                 return OUT;
    68.             }
    69.  
    70.             sampler2D _MainTex;
    71.  
    72.             fixed4 frag(v2f IN) : SV_Target
    73.             {
    74.                  fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;
    75.                 if (c.a<0.1) discard;      //Comment out this line if the mesh doesn't also include transparency  
    76.                 c.rgb *= c.a;
    77.                 return c;
    78.             }
    79.         ENDCG
    80.         }
    81.     }
    82. }
    83.  
    ^ Make sure if there is not a transparency in your mesh as is shown above, comment out discard pixels. That is for alpha blending and is slow. If your mesh doesn't have transparent pixels it is unnecessary.

    Once something has set the stencil, you can check the stencil with something like this example:

    Code (CSharp):
    1. Shader "Sprites/SpritesUnlitStencilCheckFor1"
    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.  
    10.     SubShader
    11.     {
    12.         Tags
    13.         {
    14.             "Queue"="Overlay"
    15.             "IgnoreProjector"="True"
    16.             "RenderType"="Transparent"
    17.             "PreviewType"="Plane"
    18.             "CanUseSpriteAtlas"="True"
    19.         }
    20.  
    21.         Cull Off
    22.         Lighting Off
    23.         ZWrite Off
    24.         Blend One OneMinusSrcAlpha
    25.  
    26.         Pass
    27.         {
    28.        
    29.    Stencil  {
    30.             Ref 254
    31.             Comp LEqual
    32.             Fail keep
    33.             }      
    34.        
    35.         CGPROGRAM
    36.             #pragma vertex vert
    37.             #pragma fragment frag
    38.             #pragma multi_compile _ PIXELSNAP_ON
    39.             #include "UnityCG.cginc"
    40.            
    41.             struct appdata_t
    42.             {
    43.                 float4 vertex   : POSITION;
    44.                 float4 color    : COLOR;
    45.                 float2 texcoord : TEXCOORD0;
    46.             };
    47.  
    48.             struct v2f
    49.             {
    50.                 float4 vertex   : SV_POSITION;
    51.                 fixed4 color    : COLOR;
    52.                 half2 texcoord  : TEXCOORD0;
    53.             };
    54.            
    55.             fixed4 _Color;
    56.  
    57.             v2f vert(appdata_t IN)
    58.             {
    59.                 v2f OUT;
    60.                 OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
    61.                 OUT.texcoord = IN.texcoord;
    62.                 OUT.color = IN.color * _Color;
    63.                 #ifdef PIXELSNAP_ON
    64.                 OUT.vertex = UnityPixelSnap (OUT.vertex);
    65.                 #endif
    66.  
    67.                 return OUT;
    68.             }
    69.  
    70.             sampler2D _MainTex;
    71.        
    72.             fixed4 frag(v2f IN) : SV_Target
    73.             {          
    74.                 fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;
    75.                
    76.                 c.rgb *= c.a;          
    77.                 return c;
    78.             }
    79.         ENDCG
    80.         }
    81.     }
    82. }
    83.  
    Unity has built in masking coming in the meantime, which is probably better/faster which I am looking forward to trying, but that would work in the meantime.
     
  3. Ted-Chirvasiu

    Ted-Chirvasiu

    Joined:
    Sep 7, 2010
    Posts:
    381
    Are you aiming for mobile devices? If so, you will have problems with stencil buffers because they are not supported on all graphic chips...
     
  4. kbm

    kbm

    Joined:
    Aug 7, 2014
    Posts:
    84
    Hey, thanks so much for your replies. I am not aiming for mobile devices, PC & Mac only.
    I decided to go with "Sprite Mask", a software from the asset store that basically does what I need out of the box (with stencil buffers). I can only recommend it, it worked like a charm.

    Thanks again, guys! Much appreciated!