C for Graphic:Sliced Circle Image

      不做UI不知道,没想到时至今日,ugui居然没有sliced filled image模式,用circle做filled,不能用sliced九宫格图,导致每次使用这个效果必须一张新图,何其浪费资源。
      原始功能如下:
C for Graphic:Sliced Circle Image_第1张图片
      我觉得还是自己写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
        }
    }
}

      效果如下:
C for Graphic:Sliced Circle Image_第2张图片
      后面我试了下最新的unity版本,ugui有一样的问题,可见unity还需要持续完善。

你可能感兴趣的:(入门图形学之C,for,Graphic,unity,shader,ugui)