1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
| Shader "ImageWithHole"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_TintColor ("Tint", Color) = (1,1,1,1)
_StencilComp ("Stencil Comparison", Float) = 8
_Stencil ("Stencil ID", Float) = 0
_StencilOp ("Stencil Operation", Float) = 0
_StencilWriteMask ("Stencil Write Mask", Float) = 255
_StencilReadMask ("Stencil Read Mask", Float) = 255
_MaskType("Mask Type", Integer) = 1 // 1: 圆形 2: 矩形
_Center("Center", vector) = (0, 0, 0, 0)
_Radius("Radius", Float) = 100 // 圆半径
_ClipData ("Clip Rect", Vector) = (100,0,0,0) // leftBottom.x, leftBottom.y, rightTop.x, rightTop.y
_RoundCornerRadius("Round Corner Radius", Float) = 20 // 圆角半径
_TransitionRange("Transition Range", Range(0.1, 100)) = 0.1 // 过渡范围
}
SubShader
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
Stencil
{
Ref [_Stencil]
Comp [_StencilComp]
Pass [_StencilOp]
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
}
Cull Off
Lighting Off
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
ColorMask RGBA
Pass
{
Name "Default"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#include "UnityCG.cginc"
#include "UnityUI.cginc"
struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
float4 worldPosition : TEXCOORD1;
UNITY_VERTEX_OUTPUT_STEREO
};
fixed4 _TintColor;
fixed4 _TextureSampleAdd;
fixed4 _ClipData;
float2 _Center;
half _Radius;
half _TransitionRange;
int _MaskType;
float _RoundCornerRadius;
sampler2D _MainTex;
fixed getCornerAlpha(fixed isCorner, float dis)
{
fixed inCorner = isCorner * step(dis, _RoundCornerRadius); // 圆角半径外不裁剪
fixed transition = (1 - isCorner) + isCorner * saturate((dis - (_RoundCornerRadius - _TransitionRange)) / _TransitionRange);
transition = (1 - inCorner) + inCorner * transition;
return transition;
}
float smoothStep(float edge0, float edge1, float x)
{
float t = saturate((x - edge0) / (edge1 - edge0));
return t * t * (3.0 - 2.0 * t);
}
v2f vert(appdata_t v)
{
v2f OUT;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
OUT.worldPosition = v.vertex;
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
OUT.texcoord = v.texcoord;
OUT.color = v.color * _TintColor;
return OUT;
}
fixed4 frag(v2f i) : SV_Target
{
half4 color = (tex2D(_MainTex, i.texcoord) + _TextureSampleAdd) * i.color;
fixed typeIsRound = step(_MaskType, 1) * step(1, _MaskType);
fixed typeIsRectangle = (1 - typeIsRound) * step(_MaskType, 2) * step(2, _MaskType);
// ----------圆形----------
// 计算片元屏幕和目标中心位置的距离
float dis = distance(i.vertex.xy, _Center.xy);
// 是否在圆里
fixed insideRound = step(dis, _Radius) * typeIsRound;
// 计算过渡范围内的alpha值
color.a *= (1 - insideRound) + insideRound * saturate((dis - (_Radius - _TransitionRange)) / _TransitionRange);
// ----------矩形----------
float2 roundCorner = float2(_RoundCornerRadius, _RoundCornerRadius);
// 是否在矩形里
fixed insideRect = UnityGet2DClipping(i.vertex.xy, _ClipData) * typeIsRectangle;
// 左下角
fixed isLBCorner = step(i.vertex.x - _ClipData.x, _RoundCornerRadius) * step(i.vertex.y - _ClipData.y, _RoundCornerRadius) * insideRect;
dis = distance(i.vertex.xy, _ClipData.xy + roundCorner);
color.a *= getCornerAlpha(isLBCorner, dis);
// 左上角
fixed isLTCorner = step(i.vertex.x - _ClipData.x, _RoundCornerRadius) * step(_ClipData.w - i.vertex.y, _RoundCornerRadius) * insideRect;
dis = distance(i.vertex.xy, float2(_ClipData.x + _RoundCornerRadius, _ClipData.w - _RoundCornerRadius));
color.a *= getCornerAlpha(isLTCorner, dis);
// 右上角
fixed isRTCorner = step(_ClipData.z - i.vertex.x, _RoundCornerRadius) * step(_ClipData.w - i.vertex.y, _RoundCornerRadius) * insideRect;
dis = distance(i.vertex.xy, _ClipData.zw - roundCorner);
color.a *= getCornerAlpha(isRTCorner, dis);
// 右下角
fixed isRBCorner = step(_ClipData.z - i.vertex.x, _RoundCornerRadius) * step(i.vertex.y - _ClipData.y, _RoundCornerRadius) * insideRect;
dis = distance(i.vertex.xy, float2(_ClipData.z - _RoundCornerRadius, _ClipData.y + _RoundCornerRadius));
color.a *= getCornerAlpha(isRBCorner, dis);
// 其他
fixed notCorner = (1 - (isLBCorner + isLTCorner + isRTCorner + isRBCorner)) * insideRect;
float halfSizeX = (_ClipData.z - _ClipData.x) / 2;
float halfSizeY = (_ClipData.w - _ClipData.y) / 2;
half disCenterX = distance(i.vertex.x, (_ClipData.x + _ClipData.z) / 2); // 和x轴中心的距离
half disCenterY = distance(i.vertex.y, (_ClipData.y + _ClipData.w) / 2); // 和y轴中心的距离
half alphaX= saturate((disCenterX - (halfSizeX - _TransitionRange)) / _TransitionRange);
half alphaY= saturate((disCenterY - (halfSizeY - _TransitionRange)) / _TransitionRange);
color.a *= (1 - notCorner) + notCorner * max(alphaX, alphaY);
clip (color.a - 0.001);
return color;
}
ENDCG
}
}
}
|