Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

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:
    155
    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:
    155
    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,047
    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:
    7
    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