Unity - 对象上具有抗锯齿功能的 2D 圆孔

Unity - 2D circle hole with antialiasing on object

我想在一个空物体内添加一个洞,里面有精灵。这个洞是圆形的。

为此,我将着色器添加到 material 并将 material 添加到 Sprite Renderer 组件到空对象。

这是我的着色器:

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"
}

这个方法的问题是圆没有抗锯齿...

所以我尝试给空对象添加一个Sprite蒙版,但是没有抗锯齿下层...

我认为着色器是实现该目标的良好解决方案,但我真的不知道该怎么做!

任何帮助都是完美的!!!

终于找到了!!

我将带有着色器的 material 应用于我想要看到圆圈的对象的精灵。

这是我的着色器:

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"
}

您可以根据需要修改 lerp(0, color.a, color.a * (dis - _Radius) / _Border) 部分。