-->

Unity UIレインボーシェーダー

Unity UIレインボーシェーダー

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

関連ページ 参考URL
  ※コードが古くなっていたのでURP用にコードを改修しました。(2026/04/27)  

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

またこのシェーダーを応用した ヒートグラデーションシェーダー アイスグラデーションシェーダー も作成してあります。併せてどうぞ。

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

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


以下コード全文です。uGUI Imageへの反映方法は こちらの記事 参照してください。
Shader "UI/Rainbow"
{
    Properties
    {
        _HueBlendRate("Hue Blend Rate", Range(0.1, 5)) = 3 
//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
        {
            "RenderPipeline" = "UniversalPipeline"
            "Queue" = "Transparent" 
        }
        Cull Off
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            HLSLPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"     
                
//後述のSRGBToLinearで必要なライブラリ

                #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"                             

                struct Attributes
                {
                    float4 positionOS : POSITION;
                    half4 color : COLOR;
                    half2 uv : TEXCOORD0;
                };

                struct Varyings
                {
                    float4 positionCS : POSITION;
                    half4 color : COLOR;
                    half2 uv : TEXCOORD0;
                };

                
//uGUI Image > Source Imageにアタッチされた画像を参照する

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

                float4 _MainTex_TexelSize;

                
//SRP Batcherを適用、動的に変更される数値はこの中に定義

                CBUFFER_START(UnityPerMaterial)
                    half _HueBlendRate, _OverrideRate, _HueOffset;
                CBUFFER_END                    

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

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

                //taken from: http://www.chilliant.com/rgb2hsv.html
                half3 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);
                    half3 rgb = saturate(float3(R, G, B));

                    
//URPのリニア空間用に色を変換

                    return SRGBToLinear(rgb);                   
                }

                Varyings vert(Attributes input)
                {
                    Varyings output;
                    output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
                    output.uv = input.uv;
                    output.color = input.color;
                    return output;
                }

                half4 frag (Varyings input) : SV_Target
                {
                    
//オリジナルの色を保存しておく

                    half4 originalColor = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv);
                    
//これから編集する色にコピー

                    half4 rainbowColor = originalColor;
                    
//originalColorの方は、Imageのインスペクターのカラー値を反映させる

                    originalColor *= input.color;

                    
//_HueOffsetの最小値を0にする

                    half hueOffset = max(0, _HueOffset);
                    half3 hueColor;

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

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

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

                        half2 uvFixedCenter = input.uv.xy - 0.5;

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

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

                        float rad = atan2(uvFixedCenter.y, uvFixedCenter.x);
                        
//hueOffsetの値分だけ算出した角度をずらす

                        rad += hueOffset;

                        
//fracを使い1で割った余りを算出して0~0.999..の循環パターンにし、同時にマイナス値はプラスに変換

                        float h1 = frac((rad / pi2));
                        hueColor = HUEtoRGB(h1) / _HueBlendRate;

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

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

                        half2 uvFixedCenter = input.uv.xy - 0.5;

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

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

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

                        uvFixedCenter = abs(uvFixedCenter);

                        
//lengthで中心からの直線距離を計算

                        float dist = length(uvFixedCenter);
                        
//hueOffsetの値分だけ算出した距離をずらす

                        dist += hueOffset;

                        
//結果を1で割った余りを算出することで、0~0.999..の循環パターンにする

                        dist %= 1;
                        hueColor = HUEtoRGB(dist) / _HueBlendRate;

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

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

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

                        hueColor = (HUEtoRGB((input.uv.x + hueOffset) % 1) / _HueBlendRate);
                    #endif
                    
                    #ifdef _HUETYPE_TOSHINY
                        
//光り輝くように虹色を混合、この際にmaxで0除算を防ぐ

                        rainbowColor.xyz = rainbowColor.xyz / max(0.01, hueColor);
                    #elif _HUETYPE_TODARK
                        
//光を抑えて虹色を混合

                        rainbowColor.xyz = rainbowColor.xyz * hueColor * 10;
                    #endif

                    
//各色の最大値である1を超えないようにsaturateで収める

                    rainbowColor.xyz = saturate(rainbowColor.xyz);

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

                    half4 resultColor = lerp(originalColor, rainbowColor, _OverrideRate);
                    return resultColor;
                }  
            ENDHLSL
        }
    }
}

プロパティを解説

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

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


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


2
2