本篇的按钮效果来自哔哩哔哩某大佬
变色按钮
① 普通效果
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
}
}
}
圆角窗口
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
}
}
}
效果图

