Unity ShaderLab特效教程 适用于贴图、sprite和ugui的2d着色器实例 代码+详解注释 【圆角加去锯齿】

如果代码中有什么不清楚请查看以下基础知识

Shader基础知识
unity3d 中 七种坐标知识详解### 圆角具有锯齿,需要加入抗锯齿效果,待更新
//这是来自高人的原理介绍 https://www.cnblogs.com/jqm304775992/p/4987793.html
Shader "Custom/RoundCorner"
{
	Properties
	{
        //贴图、角度(百分比)
		_MainTex ("贴图", 2D) = "black" {}
		_corner("圆角的宽度",Range(0,0.25)) = 0.001
        _radius("圆角的弧度",Range(-0.1,0.1)) = 0.0001
        //抗锯齿平滑度
        _SmoothSize("抗锯齿力度", Range(0,1)) = 0.001
	}
	
	SubShader
	{
		LOD 200
		Tags
		{
            //透明队列、不被灯光影响
			"Queue" = "Transparent"
			"IgnoreProjector" = "True"
			"RenderType" = "Transparent"
		}
		
		Pass
		{
            //2d关闭 提高性能
			Cull Off
			Lighting Off
			ZWrite Off
			Fog { Mode Off }
			Offset -1, -1
            //常规透明度混合
			Blend SrcAlpha OneMinusSrcAlpha
			CGPROGRAM
                //顶点、片元着色器
                #pragma vertex vert
                #pragma fragment frag			
                #include "UnityCG.cginc"

                sampler2D _MainTex;
                fixed _corner;
                fixed _radius;
                //模糊
                fixed _SmoothSize;
        
                struct a2v
                {
                    //顶点坐标、像素uv、顶点颜色
                    float4 vertex : POSITION;
                    float2 texcoord : TEXCOORD0;
                    fixed4 color : COLOR;
                };
        
                struct v2f
                {
                    //像素坐标、像素uv、像素颜色
                    float4 vertex : SV_POSITION;
                    half2 texcoord : TEXCOORD0;
                    fixed4 color : COLOR;
                };
                //顶点着色器
                v2f vert (a2v v)
                {
                    v2f o; 
                    //将顶点坐标转换到裁剪空间,因为2d平面可以直接映射到屏幕
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.texcoord = v.texcoord;
                    o.color = v.color;
                    return o;
                }
                //片段着色器
                fixed4 frag (v2f v) : COLOR
                {
                    //当前像素颜色,计算附加颜色和uv坐标到像素
                    fixed4 col = tex2D(_MainTex, v.texcoord) * v.color;
                    //圆角部分
                    //将当前像素的uv坐标中心点,从左下方移动到中心。uv默认的起始坐标为0,0到1,1,现在设置0.5,0.5(图片正中心)为中心点
                    float2 uv = v.texcoord.xy - float2(0.5, 0.5);
                    //中心点到圆角开始点的百分比距离
                    float centerDistance = 0.5 - _corner;
                    //获取圆角的宽度  当前uv的x坐标 % 中心点到圆角开始点的距离。 当uv.x 大于 centerDistance时 rx越来越大 rx与ry的取值范围就是 rx = 0 -> 圆角的宽度
                    float rx = uv.x % centerDistance;//(uv.x, centerDistance);
                    float ry = uv.y % centerDistance;//fmod(uv.y, centerDistance);
                    //计算不包含四个角部分的透明度是否可见
                    //比较 中心点到圆角开始点的距离 与 中心点到边的宽度, 得到的是x和y 轴中,四个圆角部分值为1,其余部分为0
                    //Step(a, b):如果b >= a返回1否则返回0
                    float mx = step(centerDistance, abs(uv.x));
                    float my = step(centerDistance, abs(uv.y));
                    //计算四个圆角部分的透明度
                    //求一个角的圆弧半径)  //length:向量的长度
                    float cornerLength = length(half2(rx,ry));
                    // 如果当前像素在圆角内返回1,否则返回0
                    float isInCorner = step(_corner, cornerLength);
                    // alpha = 总透明度 - (是否在出去四个角的区域中)*  (是否在四个圆角的区域中)
                    col.a *= 1 - (mx * my) * isInCorner + (0.0);


                    //透明去锯齿
                    //像素颜色
                    float3 c = col.rgb;
                    // //像素透明度
                    float a = col.a;
                    //模糊等级
                    float delta = 6 * _SmoothSize;
                    //
                    float _v = v.texcoord.x + delta;
                    //平滑值
                    float smoothValue = step(1., _v)*(_v-1) / delta;
                    //smoothstep:返回介于0和1之间的平滑Hermite插值   返回的值为–2*((x –min )/(max –min ))3 +3*((x –min )/(max –min ))2
                    a = smoothstep(a, 0.0f, smoothValue);

                    //计算y轴
                    float _v1 = v.texcoord.y + delta;
                    //平滑值
                    float smoothValue1 = step(0., _v1)*(_v1-1) / delta;
                    //smoothstep:返回介于0和1之间的平滑Hermite插值   返回的值为–2*((x –min )/(max –min ))3 +3*((x –min )/(max –min ))2
                    float a1 = smoothstep(a, 0.0f, smoothValue1);


                    return float4(c, a*a1);
                }
			ENDCG
		}
	}
}
发布了134 篇原创文章 · 获赞 37 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/lengyoumo/article/details/104054568
今日推荐