Unityレインボーシェーダー

Unityレインボーシェーダー

[Unity uGUI] レインボーシェーダー。画像を虹色に光らせる実装。
(Rainbow Shadr)

関連ページ 参考URL
業務で画像を虹色に光らせる必要があり、その時はネットで拾った こちらのシェーダー を使わせて貰いました。
そこから更に自分なりのアレンジを加えたものが完成したので共有します。

虹色シェーダー、コード全文

下は虹色シェーダーのサンプル動画です。
HueType.ToShinyとHueType.ToDarkで二種類の虹色グラデーションを用意しています。
比較するとToShinyは白っぽくToDarkは黒っぽいです。


以下コード全文です。uGUI Imageへの反映方法は こちらの記事 参照。
Shader "UI/Rainbow"
{
    Properties
    {
        _HueBlendRate("Hue Blend Rate", Range(0.1, 5)) = 2 
//RGBの重ね具合、虹色のグラデーションに影響

        _OverrideRate("Override Rate", Range(0, 1)) = 1 
//元々のピクセルの色にどれだけ虹色を被せるか

        _HueOffset("Hue Offset", float) = 0 
//虹色の移動値


        [Space]
        
//虹色の混合の仕方、ToShinyはHueBlendRateが高いほど真っ白に近づく。ToDarkは逆で真っ黒に近づく。

        [KeywordEnum(ToShiny, ToDark)] _HUETYPE("HueType", Int) = 0
        
//虹色の染め上げ方。

        [KeywordEnum(Circle1, Circle2, Vertical, Horizontal)] _GRADATIONTYPE("GradationType", Int) = 0
    }

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

        CGINCLUDE

        #pragma vertex vert
        #pragma fragment frag

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

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

        sampler2D _MainTex;
        
//アタッチされたSpriteのサイズを取得(x=1.0/width, y=1.0/height, z=width, w=height)

        float4 _MainTex_TexelSize;

        fixed _HueBlendRate;
        fixed _OverrideRate;
        fixed _HueOffset;

        #pragma multi_compile _HUETYPE_TOSHINY _HUETYPE_TODARK
        #pragma multi_compile _GRADATIONTYPE_CIRCLE1 _GRADATIONTYPE_CIRCLE2 _GRADATIONTYPE_VERTICAL _GRADATIONTYPE_HORIZONTAL

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

        ENDCG

        
//まず普通に画像を描画

        Pass
        {
            CGPROGRAM

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

            ENDCG
        }

        
//続いて虹色に染め上げた画像を上に重ねる

        Pass
        {
            CGPROGRAM

            
//渡された0~1の範囲の1次元変数をRGBの3次元変数に変換する

            
//taken from: http://www.chilliant.com/rgb2hsv.html

            fixed3 HUEtoRGB(in float H)
            {
                float R = abs(H * 6 - 3) - 1;
                float G = 2 - abs(H * 6 - 2);
                float B = 2 - abs(H * 6 - 4);
                return saturate(float3(R, G, B));
            }

            fixed4 frag(v2f IN) : SV_Target
            {
                fixed4 color = (tex2D(_MainTex, IN.uv)) * IN.color;
                
//_HueOffsetの最小値を0にする

                fixed hueOffset = max(0, _HueOffset);
                fixed3 hueColor;

#ifdef _GRADATIONTYPE_CIRCLE1
                
//中心から回転するように虹色グラデーションが広がる


                
//円周率の2倍を作っておく(以下2πと表記)、radian値の計算では2πがdegree値でいう360°になる

                float pi2 = 6.283184;
                
//x軸の座標を0~1の範囲から-0.5~0.5の範囲に修正する(画像中央を原点とさせるため)

                fixed fixX = IN.uv.x - 0.5;
                
//y軸の座標を0~1の範囲から-0.5~0.5の範囲に修正する(画像中央を原点とさせるため)

                fixed fixY = IN.uv.y - 0.5;

                
//atan2で中心点から対象座標への角度を取得する、返ってくる値は-2πから2πの範囲

                
//-2πと2πは回転方向が違うだけでどちらも同じ一周を表す、0°と360°が同じ角度であるのと一緒

                float rad = atan2(fixY, fixX);
                
//2πを足すことで取得角度の範囲を0~4πに修正し、マイナス値を無くす

                rad += pi2;
                
//hueOffsetの値分だけ取得座標をずらす

                rad += hueOffset;
                
//2πで割ったその余りを算出することで、あらゆる数値を0~2πの範囲の収めてかつ繰り返しのパターンにする

                
//例 : 1 %  = 1, 7.283184 %  = 1

                rad %= pi2;
                
//HUEtoRGBは引数に0~1しか与えられないので、上の値から2πを割ることで0~2πの範囲を0~1に修正する

                rad /= pi2;
                hueColor = (HUEtoRGB(rad) / _HueBlendRate);

#elif _GRADATIONTYPE_CIRCLE2
                
//中心から外側に広がるように虹色グラデーションが広がる


                
//x軸の座標を0~1の範囲から-0.5~0.5の範囲に修正する(画像中央を原点とさせるため)

                fixed fixX = IN.uv.x - 0.5;
                
//y軸の座標を0~1の範囲から-0.5~0.5の範囲に修正する(画像中央を原点とさせるため)

                fixed fixY = IN.uv.y - 0.5;             

                
//画像の縦横の短い方を取得

                fixed minScreen = min(_MainTex_TexelSize.z, _MainTex_TexelSize.w);
                
//x軸とy軸の座標を補正、画像の縦横比を適切に掛けることで正円にする

                fixX = fixX * (minScreen / _MainTex_TexelSize.w);
                fixY = fixY * (minScreen / _MainTex_TexelSize.z);
                
//-0.5も+0.5も中心点からの距離という意味では同じなので絶対値にする

                fixed diffX = abs(fixX);
                fixed diffY = abs(fixY);   

                 
//中心からの直線距離を計算する

                fixed length = sqrt(pow(diffX, 2) + pow(diffY, 2));
                hueColor = (HUEtoRGB((length + hueOffset) % 1) / _HueBlendRate);

#elif _GRADATIONTYPE_VERTICAL
                
//y軸に沿って虹色グラデーションに染める

                hueColor = (HUEtoRGB((IN.uv.y + hueOffset) % 1) / _HueBlendRate);

#elif _GRADATIONTYPE_HORIZONTAL
                
//x軸に沿って虹色グラデーションに染める

                hueColor = (HUEtoRGB((IN.uv.x + hueOffset) % 1) / _HueBlendRate);
#endif

#ifdef _HUETYPE_TOSHINY
                
//光り輝くように虹色を混合

                color.xyz *= 1 / hueColor;
#elif _HUETYPE_TODARK
                
//光を抑えて虹色を混合

                color.xyz *= hueColor;
#endif

                
//_OverrideRateに応じて虹色画像の重ね具合を決める

                color.a *= _OverrideRate;
                return color;
            }

            ENDCG
        }
    }
}

プロパティを解説

用意してあるプロパティは5つです。
虹色シェーダーのプロパティ
 Hue Blend Rate 
: RGBの重ね具合、グラデーションに影響する。この値が低いとRBGがくっきり分かれて虹色にはならない。
 Override Rate 
: 虹色画像の重ね具合。0で元の画像のみを表示、1で虹色に染まった画像のみを表示。
 Hue Offset 
: 虹色のピクセルの移動値。GradationTypeがCircleなら円状に、Verticalなら上下に、Horizontalなら左右に移動。
 Hue Type 
: 虹色の混合の仕方。明るい虹色(ToShiny)か暗めの虹色(ToDark)かの2択。
 Gradation Type 
: Circleなら円状、Verticalなら縦、Horizontalなら横のグラデーションになる。

選択するHueTypeによって適切なHueBlendRateが異なります。ToShinyなら2、ToDarkなら0.3辺りがおすすめ。
下はそれぞれのHueTypeでHueBlendRateを徐々に上げていった動画です。


HueOffsetを上げていくことで虹色が移動するアニメーションが作れます。
この際、選択するGradationTypeにより演出が変わります。


1
1