2D circle hole with antialiasing inside object
I'd like to add a hole inside an empty object with sprites inside. This hole has a circle shape.
To achieve that, I added a shader to a material and the material to a Sprite Renderer component to the empty object.
Here is my Shader :
 Shader "Sprite/Hole Effect"
 {
     Properties 
     {
         _MainTex ("Base (RGB)", 2D) = "white" {}
         _ObjPos ("Object Position", Vector) = (1,1,1,1)
         _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
         _Radius ("Hole Radius", Range(0.1,10)) = 2
     }
 
     SubShader
     {
         Pass
         {
             Cull Off 
 
             CGPROGRAM
 
             #pragma vertex vert  
             #pragma fragment frag 
 
             uniform sampler2D _MainTex;
             float _Radius;
             float4 _ObjPos;
 
             struct vertexInput {
                 float4 vertex : POSITION;
                 float4 texcoord : TEXCOORD0;
             };
             struct vertexOutput {
                 float4 pos : SV_POSITION;
                 float4 worldPos : POSITION1;
                 float4 tex : TEXCOORD0;
             };
 
             vertexOutput vert(vertexInput input)
             {
                 vertexOutput output;
 
                 output.tex = input.texcoord;
                 output.pos = UnityObjectToClipPos(input.vertex);
                 output.worldPos = mul(input.vertex, unity_ObjectToWorld);
                 return output;
             }
 
             float4 frag(vertexOutput input) : COLOR
             {
                 float4 textureColor = tex2D(_MainTex, input.tex.xy);
                 float dis = distance(input.worldPos.xyz, _ObjPos);
 
                 if (dis > _Radius)
                 {
                     discard;
                 }
 
                 return textureColor;
             }
 
             ENDCG
         }
     }
     
     FallBack "Diffuse"
 }
 
               The problem with this method is that there is no antialiasing for the circle...
So I tried to add a Sprite mask to the empty object instead, but there is no antialiasing nether...
I think the shader is the good solution to achieve that but really don't know how!
Any help would be perfect!!!
Answer by JuZ-index · Mar 26, 2021 at 06:45 AM
Finally I found it!!
I applied a material with a shader to the sprites of the object where I want to see the circle.
Here is my shader:
 Shader "Sprites/XRay Effect"
 {
     Properties
     {
         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
         
         _PlayerPos ("Player Position", Vector) = (0,0,0,0)
         _Radius ("Hole Radius", Range(0.1,100)) = 2
         _Border ("Border", Range(0.001,1)) = 0.05
     }
 
     SubShader
     {
         Tags
         { 
             "Queue"="Transparent" 
             "IgnoreProjector"="True" 
             "RenderType"="Transparent" 
             "PreviewType"="Plane"
             "CanUseSpriteAtlas"="True"
         }
         
         Cull Off
         Lighting Off
         ZWrite Off
         ZTest [unity_GUIZTestMode]
         Blend SrcAlpha OneMinusSrcAlpha
 
         Pass
         {
             CGPROGRAM
 
             #pragma vertex vert
             #pragma fragment frag
 
             #include "UnityCG.cginc"
             #include "UnityUI.cginc"
             
             struct vertexInput
             {
                 float4 vertex   : POSITION;
                 float4 color    : COLOR;
                 float2 texCoord : TEXCOORD0;
             };
 
             struct vertexOutput
             {
                 float4 vertex   : SV_POSITION;
                 fixed4 color    : COLOR;
                 half2 texCoord  : TEXCOORD0;
                 float3 worldPosition : TEXCOORD1;
             };
             
             sampler2D _MainTex;
             
             float4 _PlayerPos;
             float _Radius;
             float _Border;
 
             vertexOutput vert(vertexInput IN)
             {
                 vertexOutput OUT;
 
                 OUT.vertex = UnityObjectToClipPos(IN.vertex);
                 OUT.texCoord = IN.texCoord;
                 OUT.worldPosition = mul(unity_ObjectToWorld, IN.vertex);
                 OUT.color = IN.color;
 
                 return OUT;
             }
 
             fixed4 frag(vertexOutput IN) : SV_Target
             {
                 half4 color = tex2D(_MainTex, IN.texCoord) * IN.color;
                 
                 // Adding the circle hole
                 float dis = distance(IN.worldPosition.xyz, _PlayerPos.xyz);
                 color.a = lerp(0, color.a, color.a * (dis - _Radius) / _Border);
 
                 return color;
             }
             
             ENDCG
         }
     }
     FallBack "UI/Default"
 }
 
               You can modify the part lerp(0, color.a, color.a * (dis - _Radius) / _Border) to your needs. 
Answer by JuZ-index · Mar 12, 2021 at 08:27 AM
The way to do that is to control opacity of pixels...
Outside of the radius, opacity is 1 Inside, it's 0. And between, I could use lerp and the distance to decrease opacity from 1 (outside) to 0 (inside) to add an antialiasing...
The problem is that in this function
 float4 frag(vertexOutput input) : COLOR
              {
                  float4 textureColor = tex2D(_MainTex, input.tex.xy);
                  float dis = distance(input.worldPos.xyz, _ObjPos);
  
                  if (dis > _Radius)
                  {
                      discard;
                  }
  
                  return textureColor;
              }
 
               I can only define 'true' or 'false' (return or discard) :(
Your answer