Search Unity

Mask with custom UI shader does not work correctly

Discussion in 'General Graphics' started by mahdiii, Mar 15, 2020.

  1. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    Hi. I want to mask UI images with custom shader.
    Instead of using stencil buffer, I have sent min and max point (world position) of the intended mask into a custom shader and checked if it is inside the mask or not.
    It does not work correctly.
    Code (CSharp):
    1. Pass
    2.             {
    3.                 CGPROGRAM
    4.                 #pragma vertex vert
    5.                 #pragma fragment frag
    6.  
    7.                 #include "UnityCG.cginc"
    8.  
    9.                 #define PI 3.1415
    10.  
    11.  
    12.                 float2 Rotate(float2 data,float angle) {
    13.                    float2x2 mat = float2x2(cos(angle),-sin(angle),
    14.                                  sin(angle),cos(angle));
    15.                    data = mul(data,mat);
    16.                    return data;
    17.                 }
    18.  
    19.                 struct appdata
    20.                 {
    21.                     float4 vertex : POSITION;
    22.                     float2 uv : TEXCOORD0;
    23.  
    24.                 };
    25.  
    26.                 struct v2f
    27.                 {
    28.                     float2 uv : TEXCOORD0;
    29.                     float4 vertex : SV_POSITION;
    30.                     float3 worldPos:TEXCOORD1;
    31.  
    32.                 };
    33.  
    34.                 sampler2D _MainTex;
    35.                 sampler2D _GlowTex;
    36.                 float4 _MainTex_ST;
    37.                 float4 _Color;
    38.            
    39.                 float4 _MaskRect;
    40.  
    41.                 v2f vert(appdata v)
    42.                 {
    43.                     v2f o;
    44.                     o.vertex = UnityObjectToClipPos(v.vertex);
    45.                     o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    46.                     o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    47.                     return o;
    48.                 }
    49.                 bool isInsideMask(float2 pos) {
    50.                     return (pos.x >= _MaskRect.x && pos.x <= _MaskRect.z &&
    51.                         pos.y >= _MaskRect.y && pos.y <= _MaskRect.w);
    52.            
    53.                 }
    54.                 fixed4 frag(v2f i) : SV_Target
    55.                 {
    56.  
    57.                     fixed4 col = tex2D(_MainTex, i.uv)*_Color;
    58. //                    ...
    59.                     col.a *= float(isInsideMask(i.worldPos.xy));
    60.                     return col;
    61.                 }
    62.  
    63.                 ENDCG
    64.  
    65.             }

    Code (CSharp):
    1. button.GetComponent<HighlightShader>().Activate();
    2.          Vector3[] corners = new Vector3[4];
    3.           _maskImage.rectTransform.GetWorldCorners(corners);
    4.  
    5.          var mask = new Vector4(corners[0].x, corners[0].y, corners[2].x, corners[2].y);
    6.           button.GetComponent<Image>().material.SetVector("_MaskRect", mask);
    _MaskRect has value but shader does not work properly.
    The mask size is small and doesn't have the correct width and height.

    upload_2020-3-15_14-49-52.png
     
    Last edited: Mar 15, 2020