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 }

效果如下:

转载请注明出处:https://www.cnblogs.com/jietian331/p/17745580.html

posted @ 2023-10-07 09:44  孤独の巡礼  阅读(244)  评论(0编辑  收藏  举报