Unity UGUI之UI圆角shader
可参考:https://blog.csdn.net/newchenxf/article/details/125811641
shader代码如下:
1 Shader "TA/Unlit/UI/RoundConor" 2 { 3 Properties 4 { 5 [PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {} 6 _Color("Tint", Color) = (1,1,1,1) 7 8 _StencilComp("Stencil Comparison", Float) = 8 9 _Stencil("Stencil ID", Float) = 0 10 _StencilOp("Stencil Operation", Float) = 0 11 _StencilWriteMask("Stencil Write Mask", Float) = 255 12 _StencilReadMask("Stencil Read Mask", Float) = 255 13 14 _ColorMask("Color Mask", Float) = 15 15 16 [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip("Use Alpha Clip", Float) = 0 17 18 [Space(20)] 19 [Header(Round)] 20 _RoundedRadius("圆角半径(左上,右上,右下,左下)", Vector) = (64,64,64,64) 21 _Width("图片宽度", Float) = 200 22 _Height("图片高度", Float) = 200 23 } 24 25 SubShader 26 { 27 Tags 28 { 29 "Queue"="Transparent" 30 "IgnoreProjector"="True" 31 "RenderPipeline"="UniversalPipeline" 32 "RenderType"="Transparent" 33 "PreviewType"="Plane" 34 "CanUseSpriteAtlas"="True" 35 } 36 37 Stencil 38 { 39 Ref [_Stencil] 40 Comp [_StencilComp] 41 Pass [_StencilOp] 42 ReadMask [_StencilReadMask] 43 WriteMask [_StencilWriteMask] 44 } 45 46 Cull Off 47 Lighting Off 48 ZWrite Off 49 ZTest [unity_GUIZTestMode] 50 Blend One OneMinusSrcAlpha 51 ColorMask [_ColorMask] 52 53 Pass 54 { 55 HLSLPROGRAM 56 #pragma vertex vert 57 #pragma fragment pixel 58 #pragma target 2.0 59 60 #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl" 61 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" 62 63 #pragma multi_compile_local _ UNITY_UI_CLIP_RECT 64 #pragma multi_compile_local _ UNITY_UI_ALPHACLIP 65 66 struct appdata_t 67 { 68 float4 vertex : POSITION; 69 float4 color : COLOR; 70 float2 texcoord : TEXCOORD0; 71 UNITY_VERTEX_INPUT_INSTANCE_ID 72 }; 73 74 struct v2f 75 { 76 float4 vertex : SV_POSITION; 77 float4 color : COLOR; 78 float2 texcoord : TEXCOORD0; 79 float4 worldPosition : TEXCOORD1; 80 half4 mask : TEXCOORD2; 81 UNITY_VERTEX_OUTPUT_STEREO 82 }; 83 84 TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); 85 86 CBUFFER_START(UnityPerMaterial) 87 float4 _TextureSampleAdd; 88 float4 _ClipRect; 89 float _UIMaskSoftnessX; 90 float _UIMaskSoftnessY; 91 float4 _Color; 92 float4 _MainTex_ST; 93 94 float4 _RoundedRadius; 95 float _Width; 96 float _Height; 97 float4 _MainTex_TexelSize; //纹理的大小,可能没有纹理,只有顶点颜色 98 CBUFFER_END 99 100 101 v2f vert(appdata_t v) 102 { 103 v2f OUT; 104 105 UNITY_SETUP_INSTANCE_ID(v); 106 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); 107 108 109 OUT.worldPosition = v.vertex; 110 OUT.vertex = TransformObjectToHClip(v.vertex.xyz); 111 112 float2 pixelSize = OUT.vertex.w; 113 pixelSize /= float2(1, 1) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); 114 115 float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); 116 float2 maskUV = (v.vertex.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); 117 OUT.texcoord = TRANSFORM_TEX(v.texcoord.xy, _MainTex); 118 OUT.mask = half4(v.vertex.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_UIMaskSoftnessX, _UIMaskSoftnessY) + abs(pixelSize.xy))); 119 120 OUT.color = v.color * _Color; 121 return OUT; 122 } 123 124 // This is a overridable method for calculate UI image color 125 // if you want make some effects for UI image, please override this method. 126 #ifndef INITIALIZE_UI_IMAGE 127 #define INITIALIZE_UI_IMAGE InitializeUIImage 128 void InitializeUIImage(v2f IN,inout float4 color) 129 { 130 color = IN.color * (SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex,IN.texcoord) + _TextureSampleAdd); 131 } 132 #endif 133 134 void SetRoundConorAlpha(float2 uv, inout half4 color) 135 { 136 float width = _Width; 137 float height = _Height; 138 139 if (width <= 0 && _MainTex_TexelSize.z > 0) 140 { 141 //如果没定义宽度,而纹理又定义了宽度,则从纹理宽度读取 142 width = _MainTex_TexelSize.z; 143 } 144 if (height <= 0 && _MainTex_TexelSize.w > 0) 145 { 146 //同上 147 height = _MainTex_TexelSize.w; 148 } 149 150 151 float x = uv.x * width; 152 float y = uv.y * height; 153 154 float r; 155 float arc_size; 156 157 //左上角 158 r = _RoundedRadius.x; 159 if (x < r && y > (height - r)) 160 { 161 arc_size = (x - r) * (x - r) + (y - (height - r)) * (y - (height - r)); 162 if (arc_size > r * r) 163 { 164 color.a = 0; 165 } 166 } 167 168 //右上角 169 r = _RoundedRadius.y; 170 if (x > (width - r) && y > (height - r)) 171 { 172 arc_size = (x - (width - r)) * (x - (width - r)) + (y - (height - r)) * (y - (height - r)); 173 if (arc_size > r * r) 174 { 175 color.a = 0; 176 } 177 } 178 179 //右下角 180 r = _RoundedRadius.z; 181 if (x > (width - r) && y < r) 182 { 183 arc_size = (x - (width - r)) * (x - (width - r)) + (y - r) * (y - r); 184 if (arc_size > r * r) 185 { 186 color.a = 0; 187 } 188 } 189 190 //左下角 191 r = _RoundedRadius.w; 192 if (x < r && y < r) 193 { 194 arc_size = (x - r) * (x - r) + (y - r) * (y - r); 195 if (arc_size > r * r) 196 { 197 color.a = 0; 198 } 199 } 200 } 201 202 float4 pixel(v2f IN) : SV_Target 203 { 204 //Round up the alpha color coming from the interpolator (to 1.0/256.0 steps) 205 //The incoming alpha could have numerical instability, which makes it very sensible to 206 //HDR color transparency blend, when it blends with the world's texture. 207 const half alphaPrecision = half(0xff); 208 const half invAlphaPrecision = half(1.0/alphaPrecision); 209 IN.color.a = round(IN.color.a * alphaPrecision)*invAlphaPrecision; 210 211 half4 color; 212 INITIALIZE_UI_IMAGE(IN,color); 213 214 #ifdef UNITY_UI_CLIP_RECT 215 half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw); 216 color.a *= m.x * m.y; 217 #endif 218 219 #ifdef UNITY_UI_ALPHACLIP 220 clip (color.a - 0.001); 221 #endif 222 223 // 圆角 224 SetRoundConorAlpha(IN.texcoord, color); 225 226 // Guaranteeing that your UI shader is in mode of "One OneMinusSrcAlpha". 227 color.rgb *= color.a; 228 229 return color; 230 } 231 232 ENDHLSL 233 } 234 } 235 236 FallBack "Hidden/Universal Render Pipeline/FallbackError" 237 }
效果如下: