Unity Shader效果 Icon图片圆角处理

之前写过一篇,方形头像和圆形头像的过度效果,Unity随记(三) 方形头像与圆形头像的切换过度效果.当时采用的就是从中心点(0.5,0.5)为圆心,通过控制半径的长度和方形头像进行剪切的操作。
但是如果需要对icon进行圆角处理,则需要换个方式了,不然会显得比较生硬,对比图如下:
在这里插入图片描述
这里采用的是四个角都用一个小圆来进行对边角的裁剪处理(真正的圆角处理不知道是不是这样,不过现在这样的效果看起来已经满足需求了).如下图所示:
在这里插入图片描述
参考右上角的小圆,仅仅找到蓝色部分,将蓝色部分的Alpha设为0使其透明不显示即可,所以关键是通过比较优雅的方式找到蓝色部分.
为了使坐标原点在图片的中心点,需要对坐标进行平移(0.5,0.5)的操作,平移后使得上下左右四个圆角的处理差别仅仅在正负号上面,通过abs方法取绝对值则可方便的消除差异,避开了多个if分支语句的处理:

half2 uv = i.uv.xy - half2(0.5h, 0.5h);//将UV中心移动到图片中心

再来看看最后求alpha的部分,三个step只要有一个为0,则alpha就为1,所以需要裁减的部分(蓝色区域)三个step需要都为1,这三个step后面会有说明:

float alpha = 1 - stepX * stepY * stepL;

假如小圆的半径为R,图中黄色部分的可以表示为 |u| < 0.5 - R && |v| < 0.5 - R
本来uv的范围都是0->1,但是上面平移了坐标轴所以范围都变成了-0.5 -> 0.5.
half threshold = 0.5h - _R;//计算出阈值 uv的xy在 ±threshold范围内为显示,剩下四个角需要根据圆来判断

half stepX = step(threshold, abs(uv.x));// -threshold< x < threshold 范围内, stepX为0 否则为 1
half stepY = step(threshold, abs(uv.y));// -threshold< y < threshold 范围内, stepY为0 否则为 1

接下来就是绿色范围,就需要用到length方法了,圆心位置(threshold, threshold):

half l = length(abs(uv) - half2(threshold, threshold));
half stepL = step(_R, l);  // l <= _R, stepL为0   l > _R , stepL为1

最终通过这几个step操作就可以优雅的求出当前uv处的alpha了。
附上完整代码:

//圆角处理
Shader "Vitens/CircularCorner"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _R("R", range(0, 0.5)) = 0.1
    }
    SubShader
    {
        Tags { "Queue"="Transparent" }
        LOD 100

        Pass
        {
            blend SrcAlpha OneMinusSrcAlpha
            ZWrite off
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed _R;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                half2 uv = i.uv.xy - half2(0.5h, 0.5h);//将UV中心移动到图片中心
                half threshold = 0.5h - _R;//计算出阈值 uv的xy在 +-threshold范围内为显示,剩下四个角需要根据圆来判断
                
                //四个角的范围内
                half l = length(abs(uv) - half2(threshold, threshold));
                half stepL = step(_R, l);
                
                //除了角的其他部分
                half stepX = step(threshold, abs(uv.x));
                half stepY = step(threshold, abs(uv.y));

                //三个step只要有一个为0,则alpha就为1,所以需要裁减的部分三个step需要都为1
                float alpha = 1 - stepX * stepY * stepL;

                fixed4 col = tex2D(_MainTex, i.uv);
                col.a = alpha;
                return col;
            }
            ENDCG
        }
    }
}

对之前的过度方法进行优化,采用圆角的方式从正方向过渡到圆形好像更圆滑一些.
在这里插入图片描述
修改后的效果是这样的,是要舒服一些.
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Vitens/article/details/107371190