Shader "UI/RoundedRectangle" { Properties { _Color("Color", Color) = (1,1,1,1) _Radius("Corner Radius", Range(0, 2.5)) = 0.1 } SubShader { Tags { "Queue" = "Transparent" "RenderType" = "Transparent" "PreviewType" = "Plane" } Blend SrcAlpha OneMinusSrcAlpha ZWrite Off Cull Off Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_instancing #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float2 size : TEXCOORD1; // 传递 UI 组件的宽高 UNITY_VERTEX_INPUT_INSTANCE_ID }; UNITY_INSTANCING_BUFFER_START(Props) UNITY_DEFINE_INSTANCED_PROP(fixed4, _Color) UNITY_DEFINE_INSTANCED_PROP(half, _Radius) UNITY_INSTANCING_BUFFER_END(Props) v2f vert(appdata v) { v2f o; UNITY_SETUP_INSTANCE_ID(v); UNITY_TRANSFER_INSTANCE_ID(v, o); o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; // 计算 UI 组件的实际宽高 float2 size = float2( length(float3(unity_ObjectToWorld[0].x, unity_ObjectToWorld[1].x, unity_ObjectToWorld[2].x)), length(float3(unity_ObjectToWorld[0].y, unity_ObjectToWorld[1].y, unity_ObjectToWorld[2].y)) ); o.size = size; // 传递宽高信息 return o; } // 计算 SDF 圆角边界 float roundedBoxSDF(float2 uv, float2 size, float radius) { // 归一化 UV 到 [-1,1],保持正确比例 uv = (uv - 0.5) * 2.0; uv *= size / min(size.x, size.y); // 保持等比例缩放 // 计算边界 float2 corner = float2(1.0 - radius, 1.0 - radius); float2 d = abs(uv) - corner; return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0) - radius; } fixed4 frag(v2f i) : SV_Target { UNITY_SETUP_INSTANCE_ID(i); float radius = UNITY_ACCESS_INSTANCED_PROP(Props, _Radius) * min(i.size.x, i.size.y) * 0.5; // 计算 SDF 圆角 float sdf = roundedBoxSDF(i.uv, i.size, radius); // 抗锯齿处理 float alpha = 1.0 - smoothstep(0.0, 0.01 * min(i.size.x, i.size.y), sdf); fixed4 color = UNITY_ACCESS_INSTANCED_PROP(Props, _Color); return fixed4(color.rgb, alpha * color.a); } ENDCG } } }