Unity uses another Mask solution to solve the aliasing of Mask components

This article shares another Mask solution used in Unity to solve the aliasing of Mask components

motivation

In the previous article, careful students may have seen that when the avatar is enlarged, obvious sawtooth can be seen, as shown in the figure:

This is because the template test is based on pixels, either pass or fail. If it fails, it will not be rendered. In those transition places, because of the high opacity, the effect of mixing is almost the same as that of no mixing

We use another idea to make a mask: when drawing a picture, we sample the transparency from the mask texture to modify the transparency of the slice element. The transparency of the part outside the circle of the mask is 0, and there are different transparency in the excessive part, so that we can mix correctly and play the mask effect correctly

Process and effect

As in the previous article, we need to prepare two pictures, a circular semi transparent picture as a mask and a head picture. As shown in the figure, two pictures:

Create a material and a shader (directly copy the UI default of Unity for modification), as follows:

  • CustomMask2.shader
  • Object2.mat

The corresponding shader code is:

Shader "Custom/CustomMask2"
{
	Properties
	{
		[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
		_MaskTex ("Mask Texture", 2D) = "white" {}
		_Color ("Tint", Color) = (1,1,1,1)

		_ColorMask ("Color Mask", Range(0, 15)) = 15

		[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
	}

	SubShader
	{
		Tags
		{
			"Queue"="Transparent"
			"IgnoreProjector"="True"
			"RenderType"="Transparent"
			"PreviewType"="Plane"
			"CanUseSpriteAtlas"="True"
		}

		Cull Off
		Lighting Off
		ZWrite Off
		ZTest [unity_GUIZTestMode]
		Blend SrcAlpha OneMinusSrcAlpha
		ColorMask [_ColorMask]

		Pass
		{
			Name "CustomMask2"
		CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma target 2.0

			#include "UnityCG.cginc"
			#include "UnityUI.cginc"

			#pragma multi_compile __ UNITY_UI_ALPHACLIP

			struct appdata_t
			{
				float4 vertex   : POSITION;
				float4 color    : COLOR;
				float2 texcoord : TEXCOORD0;
				UNITY_VERTEX_INPUT_INSTANCE_ID
			};

			struct v2f
			{
				float4 vertex   : SV_POSITION;
				fixed4 color    : COLOR;
				float2 texcoord  : TEXCOORD0;
				float4 worldPosition : TEXCOORD1;
				UNITY_VERTEX_OUTPUT_STEREO
			};

			fixed4 _Color;
			fixed4 _TextureSampleAdd;
			float4 _ClipRect;

			v2f vert(appdata_t IN)
			{
				v2f OUT;
				UNITY_SETUP_INSTANCE_ID(IN);
				UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
				OUT.worldPosition = IN.vertex;
				OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);

				OUT.texcoord = IN.texcoord;

				OUT.color = IN.color * _Color;
				return OUT;
			}

			sampler2D _MainTex;
			sampler2D _MaskTex;

			float _OneMinusSaturability;

			fixed4 frag(v2f IN) : SV_Target
			{
				half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd);
				if (IN.color.r < 0.0001 && IN.color.g < 0.0001 && IN.color.b > 0.0001 && IN.color.b < 0.004)
				{
					float gray = dot(color.rgb, float3(0.2125, 0.7154, 0.0721));
					color.rgb = float3(gray, gray, gray);
				}
				else
				{
					color *= IN.color;

					if (_OneMinusSaturability > 0.05)
					{
						float gray = dot(color.rgb, float3(0.2125, 0.7154, 0.0721));
						color.rgb = lerp(float3(gray, gray, gray), color.rgb, 1 - _OneMinusSaturability);
					}
				}

				color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
				color.a *= tex2D(_MaskTex, IN.texcoord).a;
				
				#ifdef UNITY_UI_ALPHACLIP
				clip (color.a - 0.001);
				#endif

				return color;
			}
		ENDCG
		}
	}
}

Compared with the previous shader, we deleted the configuration related to the template test and added a texture_ MaskTex ("Mask Texture", 2D) = "white" {}, and added a line of code color.a *= tex2D(_MaskTex, IN.texcoord).a

Then build two rawimages with the size of 120x120. One is used to display the original image and the other is used to mask the avatar, as shown in the figure:

After setting the material and shader for the mask avatar, drag the texture of the circular mask onto the Mask Texture to complete all the work, as shown in the figure:

Of course, you can also further optimize the effect of the edge by adjusting the transparency of the edge of the circular mask. As long as you understand that transparency mixing is used to solve the problem of edge aliasing. I hope it will be helpful to you

Keywords: Unity

Added by envexlabs on Mon, 08 Nov 2021 02:59:47 +0200