読者です 読者をやめる 読者になる 読者になる

Tutti Lab

元シリコンバレー在住のおっさん技術者、モバイルVRアプリ開発に挑戦中

Quadで円形プログレス

Quad fillAmount

uGUIのImageは、fillAmountを使って簡単に円形のプログレスができるのですが、SpriteやQuadにはfillAmountに相当する機能がないようです。
こちらこちらに、Quadを使った円形プログレスの実現方法があるのですが、予め0→360度でα値を1→0とした画像を用意する必要があるようで、面倒だし汎用性がないな、と思いました。
そこで、角度(0~360度)を指定して円形プログレスをするための簡単なシェーダーコードを書いてみました。

f:id:tuti107:20170204193817p:plain

Shader "Tuti/Reticle"
{
  Properties
  {
    [NoScaleOffset] _MainTex("Texture", 2D) = "white" {}
    _Degree("Degree", Float) = 360.0
  }

  SubShader
  {
    Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }

    ZWrite On
    Blend SrcAlpha OneMinusSrcAlpha

    Pass
    {
      CGPROGRAM
      #pragma vertex vert
      #pragma fragment frag

      #include "UnityCG.cginc"

      #define PI 3.14159

      struct appdata
      {
        float4 vertex : POSITION;
        float2 uv : TEXCOORD0;
      };

      struct v2f
      {
        float2 uv : TEXCOORD0;
        float4 vertex : SV_POSITION;
      };

      sampler2D _MainTex;
      float _Degree;

      v2f vert (appdata v)
      {
        v2f o;
        o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
        o.uv = v.uv;
        return o;
      }
			
      half4 frag(v2f i) : SV_Target
      {
        half4 col = tex2D(_MainTex, i.uv);
        float xx = i.uv.x - 0.5;
        float yy = i.uv.y - 0.5;

        float deg = (atan2(yy, xx)) * 180.0 / PI;
        if (yy >= 0) {
          if (deg > _Degree) {
            col.a = 0.0;
          }
        }
        else {
          if (deg + 360.0 > _Degree) {
            col.a = 0.0;
          }
        }

        return col;
      }
      ENDCG
    }
  }
}

時計の12時の位置から時計回りにする場合は、z軸90度回転+Y軸で反転してください。
ちゃんとテストはやっていませんが、とりあえず動いているようです。