Unity shader 实现圆角矩形

一.前言

很多情况下我们需要给矩形的图片添加圆角,如果每次都让美术处理,又有些繁琐,所以我们今天就使用shader自己实现一个圆角矩形的功能,如下图所示
Unity shader 实现圆角矩形_第1张图片
Unity shader 实现圆角矩形_第2张图片

二.实现原理

把图片拆分成如上图所示的几个不同结构(1中间的一个十字区域,2四个角分别一个1/4圆形区域),我们只需要计算出每个像素的UV在哪个区域,就可以判断是否需要渲染

1.调整uv范围从(0,1)到(-0.5,0.5),即图片uv原点从左下角到中心点

	o.adaptUV = v.texcoord - fixed2(0.5,0.5)

Unity shader 实现圆角矩形_第3张图片

2.计算中间十字区域(圆角半径为radius)

	if(abs(i.adaptUV).x < 0.5-radius||abs(i.adaptUV).y < 0.5-radius){
		//绘制十字区域
	}

Unity shader 实现圆角矩形_第4张图片

3.计算四个角的弧形区域(实际计算圆形区域就行)

	//1.获取每个圆形的圆心p点的uv
	fixed side = 0.5 - radius
	fixed2 p = fixed2(side,side)
	
	//2.计算当前像素点uv到p点距离,小于圆角半径就渲染
	fixed len = length(abs(i.adaptUV) - p)
	if(len < radius)
		//绘制四个角的弧形区域
	else
		discard;//不绘制

Unity shader 实现圆角矩形_第5张图片

三.shader源码

Unity shader 实现圆角矩形_第6张图片

随后附上完整shader源码:

Shader "Custom/UI/RoundRect"
{
    Properties
    {
        [PerRendererData]
        _MainTex ("Main Texture", 2D) = "white" {}
        [PerRendererData]
        _Color ("Main Color", Color) = (1,1,1,1)
        _Radius ("Radius", Range(0,0.5)) = 0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

	pass{
        CGPROGRAM
       
	   #pragma vertex vert
	   #pragma fragment frag
	   #include "unitycg.cginc"
	   
	   sampler2D _MainTex;
	   fixed _Radius;
	   fixed4 _Color;

	   struct v2f{
            float4 pos:SV_POSITION;
            float2 srcUV:TEXCOORD0;		// 原本的uv
            float2 adaptUV:TEXCOORD1;	// 用来调整方便计算的uv
	   };

	   
	   v2f vert(appdata_base v){
			v2f o;
			o.pos = UnityObjectToClipPos(v.vertex);
			o.srcUV = v.texcoord;

			// 调整uv范围从(0,1)到(-0.5,0.5),即图片uv原点从左下角到中心点
			o.adaptUV = o.srcUV - fixed2(0.5,0.5);
			return o;
	   }

	   fixed4 frag(v2f i):COLOR
	   {
			fixed4 col = fixed4(0,0,0,0);

			// 首先绘制中间部分(在设置圆角半径里面的)(adaptUV x y 绝对值小于 0.5-圆角半径内的区域)
			if(abs(i.adaptUV).x<(0.5-_Radius) || abs(i.adaptUV).y<(0.5-_Radius))
			{
				col =tex2D(_MainTex,i.srcUV);
			}
			else
			{  
				// 其次四个圆角部分(相当于以 (0.5-圆角半径,0.5-圆角半径)为圆心,把 uv 在 圆角半径内的uv绘制出来)
				if(length(abs(i.adaptUV)-fixed2(0.5-_Radius,0.5-_Radius)) < _Radius){
					col = tex2D(_MainTex,i.srcUV);
				}
				else// 超出的部分忽略掉
				{
					discard;
				}
			}
			return col*_Color;
	   }

        ENDCG
    }
	}
    FallBack "Diffuse"
}

你可能感兴趣的:(Unity,unity,shader,圆角矩形,圆角,shaderlab)