不做UI不知道,没想到时至今日,ugui居然没有sliced filled image模式,用circle做filled,不能用sliced九宫格图,导致每次使用这个效果必须一张新图,何其浪费资源。
原始功能如下:
我觉得还是自己写shader解决这个问题比较方便,原理很简单,通过frag函数逐uv扫描中心pixel坐标与uv pixel坐标的朝向向量,与轴向量(比如up direction)的夹角,从0-360度限制discard像素即可。
唯一注意事项就是:夹角的正负值计算问题,这里我们用叉积判断正负值即可(unity右手坐标系扩展z轴)
直接上代码:
Shader "UI360FilledAndSliced/UI360FilledUnlitShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Axis("Axis",vector) = (0,0.5,0,0)
_Degree("Degree",Range(0,360)) = 0
}
SubShader
{
Tags { "RenderType"="Transparent" "Queue"="Transparent" }
LOD 100
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define RAD2DEG 57.29578
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float2 _Axis;
float _Degree;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
//unity右手坐标系
//获取夹角正负值
//左手定则
float getClampPM(float2 f,float2 t)
{
float3 f3 = float3(f,0);
float3 t3 = float3(t,0);
float3 n3 = cross(f3,t3);
return n3.z;
}
//计算夹角
//左手定则
float getClampDegree(float2 f,float2 t)
{
float cos = dot(f,t)/(length(f)*length(t));
float deg = acos(cos)*RAD2DEG;
float pm = getClampPM(f,t);
if(pm>0)
{
deg = 360-abs(deg);
}
return deg;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
float2 cuv = float2(0.5,0.5);
float2 p2c = i.uv-cuv;
float deg = getClampDegree(_Axis,p2c);
if(deg>_Degree)
{
discard;
}
return col;
}
ENDCG
}
}
}
效果如下:
后面我试了下最新的unity版本,ugui有一样的问题,可见unity还需要持续完善。