TH1/Unity/Assets/Shaders/UI/RoundedRectangle.shader
2025-07-17 18:26:28 +08:00

102 lines
3.0 KiB
Plaintext

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
}
}
}