Unityサークル画面遷移シェーダー

Unityサークル画面遷移シェーダー。円状に画像が広がるシェーダー。
(Circle Transition Shader for Unity uGUI)

関連ページ 参考URL
ふとした瞬間に急に漫画に出てくるような集中線効果のシェーダーが作りたくなった。
色々調べると、どうやらサークル状のグラデーション+シンプルノイズで集中線を作れるらしかった。
今回は勉強のために、まずサークルグラデーションを応用したシェーダーを作成してみた。

このシェーダーの作成の後、実際に 集中線シェーダー も作ったのでそちらもどうぞ。

サークル画面遷移シェーダーの概要

中心から円状に、指定した画像が展開していくシェーダー。
サウンドノベルの画面遷移表現とかでよくありそうな物。


基本的には、UI Canvasの一番下に画面全体を覆うようにImageを用意し、そこにマテリアルをアタッチして使う。
シェーダーをアタッチしたImageの位置

Imageに画像をアタッチしなければ、無地のモノがそのまま埋まっていく。

サークル画面遷移シェーダー、コード全文

以下コード全文。uGUI Imageへの反映方法は こちらの記事 参照。
Shader "UI/CircleTransition"
{
    Properties
    {
        [HideInInspector] _MainTex("-",2D)="white"{}
        [KeywordEnum(Solid, Smooth)] _EDGE("Edge", Int) = 0
        _Transition("Transition", Range(0, 360)) = 0
        _SplitNum("SplitNum", Range(1, 20)) = 1
    }

    SubShader
    {
        Tags { "Queue" = "Transparent" }
        Cull Off
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile _EDGE_SOLID _EDGE_SMOOTH  

            struct appdata
            {
                fixed2 uv : TEXCOORD0;
                fixed4 vertex : POSITION;
                fixed4 color : COLOR;
            };

            struct v2f
            {
                fixed2 uv : TEXCOORD0;
                fixed4 vertex : POSITION;
                fixed4 color : COLOR;
            };

            fixed _Transition;            
            int _SplitNum;
            sampler2D _MainTex;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                o.color = v.color;
                return o;
            }

            
//引数に渡された対象座標の角度を取得

            fixed2 getUvDegree(fixed2 uv)
            {
                
//画面中央を角度0とした時の、対象座標の角度をDegree値で取得

                fixed2 fixUv = uv * 2 - 1;
                fixed deg = degrees(atan2(fixUv.y, fixUv.x));
                
//回転の方向を示してないので角度がマイナスになることがある、0~360の範囲になるように修正

                fixed isMinus = step(deg, 0);
                fixed2 fixDeg = (isMinus * (deg + 360)) + ((1 - isMinus) * deg);
                
//360度を_SplitNumの値で分割し、それを遷移が完了する角度の最大値とする

                
//例えば_SplitNumが2の時、画像は2分割されるので、180度まで広がった画像が2つで完全に遷移が完了する

                fixed maxDeg = 360 / _SplitNum;
                
//対象座標の角度を、各分割された画像の領分に収める

                
//例えば_SplitNumが2でfixdegが190度の場合、分割された2つ目の画像の領分内の10度という解釈をする

                return fixDeg % maxDeg;
            }

            
//分割された画像に合わせて、各画像の領分の遷移スピードを遅らせる計算

            
//この処理をしない場合、例えば_SplitNumが2の時、_Transitionが180の時点で2つの画像が完全に画面を覆ってしまう

            fixed getFixTransition()
            {
                return _Transition / _SplitNum;
            }     

            
//エッジ部分がくっきりさせるアルファ値を取得

            fixed getSolidAlpha(fixed deg)
            {
                fixed isCurtain = step(deg, getFixTransition());
                return isCurtain;
            }

            
//エッジ部分がぼやかすアルファ値を取得

            fixed getSmoothAlpha(fixed deg)
            {
                fixed alpha = (1 - (deg / getFixTransition())) * 2 + 1;
                return alpha;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                col *= i.color;

                fixed deg = getUvDegree(i.uv);

                fixed alpha = 0;
#ifdef _EDGE_SOLID
                alpha = getSolidAlpha(deg);
#elif _EDGE_SMOOTH
                alpha = getSmoothAlpha(deg);
#endif
                col.a = alpha;
                return col;
            }
            ENDCG
        }
    }
}

プロパティの解説

プロパティは3つ用意してある。
サークル画面遷移シェーダーのプロパティ
 Edge 
: Variant 。SolidとSmoothの2種類が用意してあり、Solidはエッジ部分をくっきりに、Smoothはエッジ部分をぼかす。
 Transition 
: 遷移が完了するまでの割合。0~360の値を指定できる。
 SplitNum 
: 遷移する際の画面の分割数。1~20までを指定できる。

下はそれぞれ、EdgeとSplitNumに変更を加えた時の動画。


1
1