Search Unity

Using mask to cut a hole in an image?

Discussion in 'UGUI & TextMesh Pro' started by andrew-fray, Dec 19, 2014.

  1. andrew-fray

    andrew-fray

    Joined:
    Jul 19, 2012
    Posts:
    157
    For my game's tutorial, I'd like to put a dark semi-transparent overlay across the whole screen, except for a hole around the UI element I'm currently talking about.

    I could do this using several semi-transparent rectangular images and a "hole" image arranged such that it looked like one overlay with a hole cut in it.

    |_____|
    |_|O|_|
    |_____|


    (forgive my programmer art)

    However, is it possible to reverse the Mask component somehow, so that I have a single rectangular overlay, and an inverted hole image that's used to cut out a hole? That would be a lot easier to reposition as I move around the UI.
     
  2. andrew-fray

    andrew-fray

    Joined:
    Jul 19, 2012
    Posts:
    157
    I ended up anchoring very large flaps to each side of my central hole image. Now I can reposition easily, but it's not as neat having a single full-screen graphic will a hole cut out!
     
  3. ibyte

    ibyte

    Joined:
    Aug 14, 2009
    Posts:
    1,048
    Andrew, can you just not invert your mask image? I tried it and I think that should do what you want. Make sure show mask graphic is checked.
     
    Last edited: Dec 19, 2014
  4. Senshi

    Senshi

    Joined:
    Oct 3, 2010
    Posts:
    557
    There is a sprite clipping script here that I personally use to achieve a "mask by children" effect. However, perhaps you could refit it for your purposes by changing which pixels to discard? I.e.: Change mask.cs, line 76 to:

    Code (csharp):
    1. if (c.a>0.1) discard; //or c.a>0.5 for smoother edges
     
    rakkarage likes this.
  5. PoL231

    PoL231

    Joined:
    Jun 27, 2014
    Posts:
    148
    Simplexws likes this.
  6. rakkarage

    rakkarage

    Joined:
    Feb 3, 2014
    Posts:
    683


    Mask.shader
    Code (CSharp):
    1. Shader "Custom/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.  
    10.     SubShader
    11.     {
    12.         Tags
    13.         {
    14.             "Queue"="Transparent-1"
    15.             "IgnoreProjector"="True"
    16.             "RenderType"="Transparent"
    17.             "PreviewType"="Plane"
    18.             "CanUseSpriteAtlas"="True"
    19.         }
    20.  
    21.         Cull Off
    22.         Lighting Off
    23.         ColorMask 0
    24.         ZWrite Off
    25.         Blend One OneMinusSrcAlpha
    26.  
    27.         Stencil
    28.         {
    29.             Ref 1
    30.             Comp always
    31.             Pass replace
    32.         }
    33.  
    34.         Pass
    35.         {
    36.         CGPROGRAM
    37.             #pragma vertex vert
    38.             #pragma fragment frag
    39.             #pragma multi_compile _ PIXELSNAP_ON
    40.             #include "UnityCG.cginc"
    41.  
    42.             struct appdata_t
    43.             {
    44.                 float4 vertex   : POSITION;
    45.                 float4 color    : COLOR;
    46.                 float2 texcoord : TEXCOORD0;
    47.             };
    48.  
    49.             struct v2f
    50.             {
    51.                 float4 vertex   : SV_POSITION;
    52.                 fixed4 color    : COLOR;
    53.                 half2 texcoord  : TEXCOORD0;
    54.             };
    55.  
    56.             fixed4 _Color;
    57.  
    58.             v2f vert(appdata_t IN)
    59.             {
    60.                 v2f OUT;
    61.                 OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
    62.                 OUT.texcoord = IN.texcoord;
    63.                 OUT.color = IN.color * _Color;
    64.                 #ifdef PIXELSNAP_ON
    65.                 OUT.vertex = UnityPixelSnap (OUT.vertex);
    66.                 #endif
    67.  
    68.                 return OUT;
    69.             }
    70.  
    71.             sampler2D _MainTex;
    72.  
    73.             fixed4 frag(v2f IN) : SV_Target
    74.             {
    75.                 fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;
    76.                 if (c.a < 0.1) discard;
    77.                 c.rgb *= c.a;
    78.                 return c;
    79.             }
    80.         ENDCG
    81.         }
    82.     }
    83. }
    84.  
    Masked.shader
    Code (CSharp):
    1. Shader "Custom/Masked"
    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.         Stencil
    27.         {
    28.             Ref 1
    29.             Comp notequal
    30.             Pass keep
    31.         }
    32.  
    33.         Pass
    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.                 c.rgb *= c.a;
    76.                 return c;
    77.             }
    78.         ENDCG
    79.         }
    80.     }
    81. }
    82.  
     
    Last edited: Jul 21, 2015
    munkiki7, April_Hu, Raseru and 17 others like this.
  7. hophoppoppop

    hophoppoppop

    Joined:
    Dec 27, 2014
    Posts:
    19
    I know this is really too late. But, really thank you very much. This very helpfull to my other project in future.
     
    rakkarage likes this.
  8. nmnsud

    nmnsud

    Joined:
    Apr 6, 2017
    Posts:
    6
    Hi @rakkarage! I tried it, but it is only working in Editor window not in Game window :(

    By the way, I'm using it for Android Game


    EDIT:

    Anyway, It worked. Just placed my Mask Image before Masked Image in Hierarchy! ;):)
     
    Last edited: Dec 7, 2017
    DayFall, Chichkan and rakkarage like this.
  9. mcaisw

    mcaisw

    Joined:
    Aug 15, 2017
    Posts:
    9
    Awesome! It's worked for me
     
    rakkarage likes this.
  10. Zdrenga

    Zdrenga

    Joined:
    Sep 6, 2018
    Posts:
    5
    Is there a way to allow clicks on the buttons that are inside "mask" and block clicks on the buttons that are outside?

    I disabled the raycast target on the "mask", but the raycast target from "masked" is blocking the button interaction.
     
  11. sytsew

    sytsew

    Joined:
    Jul 6, 2017
    Posts:
    4
    Did you find a remedy for this? Or an alternative? Thanks
     
  12. Renanmgs

    Renanmgs

    Joined:
    May 16, 2016
    Posts:
    31
    I cant use this shader in a Panel in UI, it only works with 3D
     
    Avalin likes this.
  13. LexaMV

    LexaMV

    Joined:
    Feb 20, 2018
    Posts:
    28
    How to block raycast for this mask?
     
  14. NocturnalWisp

    NocturnalWisp

    Joined:
    Oct 2, 2019
    Posts:
    62
    I needed this script for work and it helps a lot, but I noticed people may be having trouble with using raycasts with the shaders.

    As a possible solution for your future use, I am handling all UI events in script so I can check that the mouse clicked within the "Mask" image and isn't outside of the bounds of that canvas item.

    Hope this helps!

    Edit: I also found this useful script on GitHub that could be repurposed to accept all UI events. UnmaskForUGUI/UnmaskRaycastFilter.cs at main · mob-sakai/UnmaskForUGUI · GitHub
     
    Last edited: Jan 7, 2022
    ritesh_khokhani likes this.
  15. iShokko

    iShokko

    Joined:
    Dec 4, 2022
    Posts:
    1
    i know th
    is very late to reply but u can use shaders on anything