本篇的按钮效果来自哔哩哔哩某大佬

变色按钮

① 普通效果

text
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
Shader "Unlit/BtnClickWaveShader"
{
   Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _ColorLeft ("ColorLeft", Color) = (0,1,0,1)
        _ColorRight ("ColorRight", Color) = (0,0,1,1)
        _Radius ("Radius", Float) = 1
        _RadiusThickness ("RadiusThickness", Float) = 1
        _WaveAlpha ("WaveAlpha", Range(0, 1)) = 0.5
        [HDR] _WaveColor ("WaveColor", Color) = (1,1,1,1)
        [hideInInspector] _CircleScaleOffset ("CircleScaleOffset", Float) = 1 // Width / Height
        [hideInInspector] _MouseUVPos ("MouseUVPos", Vector) = (0,0,0,0)
    }
    SubShader
    {
        Tags { "RenderType"="Transparent" "Queue"="Transparent"}
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            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;
            float4 _ColorLeft;
            float4 _ColorRight;

           
            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
            {
                fixed4 shape = tex2D(_MainTex, i.uv);
                fixed4 col = fixed4(lerp(_ColorLeft, _ColorRight, i.uv.x).rgb, shape.a);
                return col;
            }
            ENDCG
        }
        Pass
        {
            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;
            float4 _ColorLeft;
            float4 _ColorRight;
            float _Radius;
            float _RadiusThickness;
            float _CircleScaleOffset;
            float _WaveAlpha;
            float4 _WaveColor;
            float4 _MouseUVPos;

            fixed4 PixelColor(float2 uv)
            {
                // 将uv原点移到中心
                uv -= _MouseUVPos.xy;
                uv = uv * 2 - 1;
                // 离uv坐标原点的距离,排除屏幕长宽比、图片长宽比的影响
                float2 dv = float2(uv.x, uv.y)* float2(_ScreenParams.x / _ScreenParams.y * _CircleScaleOffset, 1);
                float d = sqrt(pow(dv.x, 2) + pow(dv.y, 2));
                // 用小圆减大圆 得到圆环
                fixed3 c = smoothstep(_Radius-_RadiusThickness, _Radius, d) - smoothstep(_Radius, _Radius+_RadiusThickness, d);

                return fixed4(c * _WaveColor.rgb, saturate(c.g)); // -0.5
            }

            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
            {
                fixed4 shape = tex2D(_MainTex, i.uv);
                fixed4 wave = PixelColor(i.uv);
                wave.rgb *= _WaveColor.rgb;
                wave.a *= shape.a * _WaveAlpha;
                return wave;
            }
            ENDCG
        }
    }
}

② 带SDF效果

text
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
Shader "Unlit/BtnClickWaveSDFShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _ColorLeft ("ColorLeft", Color) = (0,1,0,1)
        _ColorRight ("ColorRight", Color) = (0,0,1,1)
        [hideInInspector] _CircleScaleOffset ("CircleScaleOffset", Float) = 1 // Width / Height
        [hideInInspector] _CirclePosOffset ("CirclePosOffset", Vector) = (0,0,0,0)
        _Radius ("Radius", Float) = 1.5
        _RadiusThickness ("RadiusThickness", Float) = 0.2
        [HDR] _WaveColor ("WaveColor", Color) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType"="Transparent" "Queue"="Transparent"}
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            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;
            float4 _ColorLeft;
            float4 _ColorRight;

            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
            {
                fixed4 shape = tex2D(_MainTex, i.uv);
                fixed4 col = fixed4(lerp(_ColorLeft, _ColorRight, i.uv.x).rgb, shape.a);
                return col;
            }
            ENDCG
        }
        Pass
        {
            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;
            float _CircleScaleOffset;
            float _Radius;
            float4 _CirclePosOffset;
            float _RadiusThickness;
            float4 _WaveColor;

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

            float sdCircle(float2 p, float r)
            {
                return length(p) - r;
            }
            float opAnnular(float sdf, float r)
            {
                return abs(sdf) - r;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 shape = tex2D(_MainTex, i.uv);
                // 全象限
                i.uv -= _CirclePosOffset.xy;
                i.uv.y = 1.0 - i.uv.y;
                i.uv = i.uv * 2 - 1;
                // 消除屏幕拉伸影响
                float w = _ScreenParams.x;
                float h = _ScreenParams.y;
                half co = w/h * _CircleScaleOffset;
                i.uv = float2(i.uv.x * co, i.uv.y);

                float step = 1.0 / w;
                fixed4 circle = smoothstep(step, -step, opAnnular(sdCircle(i.uv, _Radius) , _RadiusThickness));

                fixed4 col = fixed4(circle.rgb, shape.a);
                col.rgb = col.rgb * _WaveColor.rgb;
                col.a *= col.r;
                col.a = _WaveColor.a * col.a;
                
                return col;
            }
            ENDCG
        }
    }
}

效果图 image-20260201233916124

圆角窗口

text
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
Shader "Unlit/ImageRoundCorner"
{
    Properties
    {
        [PerRendererData]_MainTex ("Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)

        // 四个角的半径
        _Radius ("Corner Radius (LTRB)", Vector) = (0.1, 0.1, 0.1, 0.1)

        // 边框
        _BorderWidth ("Border Width", Float) = 0.0
        _BorderColor ("Border Color", Color) = (1,1,1,1)

        // 全局透明度
        _Alpha ("Alpha", Range(0,1)) = 1.0
    }

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

        Cull Off
        Lighting Off
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

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

            struct v2f
            {
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;
                float4 color : COLOR;
            };

            sampler2D _MainTex;
            float4 _MainTex_TexelSize;
            float4 _MainTex_ST;
            fixed4 _Color;

            float4 _Radius; // 左上、右上、右下、左下 半径
            float _BorderWidth;
            fixed4 _BorderColor;
            float _Alpha;

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

            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv) * i.color;
                float2 uv = i.uv;
                float width = 1.0;
                float height = 1.0;

                float rL = _Radius.x; // 左上
                float rR = _Radius.y; // 右上
                float rB = _Radius.z; // 右下
                float rBL = _Radius.w; // 左下

                float b = _BorderWidth;

                // 四个角圆角+边框处理
                float2 p = uv;

                // 左下角
                if (p.x < rBL && p.y < rBL)
                {
                    float d = distance(p, float2(rBL, rBL));
                    if (d > rBL) col.a = 0;
                    else if (b > 0 && d > rBL - b) col = _BorderColor;
                }

                // 左上角
                if (p.x < rL && p.y > 1 - rL)
                {
                    float d = distance(p, float2(rL, 1 - rL));
                    if (d > rL) col.a = 0;
                    else if (b > 0 && d > rL - b) col = _BorderColor;
                }

                // 右下角
                if (p.x > 1 - rB && p.y < rB)
                {
                    float d = distance(p, float2(1 - rB, rB));
                    if (d > rB) col.a = 0;
                    else if (b > 0 && d > rB - b) col = _BorderColor;
                }

                // 右上角
                if (p.x > 1 - rR && p.y > 1 - rR)
                {
                    float d = distance(p, float2(1 - rR, 1 - rR));
                    if (d > rR) col.a = 0;
                    else if (b > 0 && d > rR - b) col = _BorderColor;
                }

                // 透明度控制
                col.a *= _Alpha;

                return col;
            }
            ENDCG
        }
    }
}

效果图

​ image-20260201234237217