-->

【Unity Shader】UIヒートグラデーションシェーダー

【Unity Shader】UIヒートグラデーションシェーダー
  ※コードが古くなっていたのでURP用にコードを改修しました。(2026/08/22)  

前回 レインボーシェーダーを作った経験から、これを応用して、出力色を限定して画像を熱するような表現が作れそうだなと思いました。
実際やってみて作れたの共有します。

ヒートグラデーションシェーダーの概要

下がヒートグラデーションのサンプル動画です。
赤 > 黄色 > 白 > 黄色 > 赤の色が反復してアニメーションします。

パーティクルと組み合わせるとよりそれっぽくなりそうです。

ヒートグラデーションシェーダーのコード全文

以下シェーダーのコード全文です。
.shader拡張子であればファイル名は何でもいいですが、とりあえず
 HeatGradation.shader 
というファイルを作り、中身を全てコピペしてください。
Copy Code

Shader "UI/HeatGradation"
{
    Properties
    {
        [HideInInspector]_MainTex("-",2D)="white"{}
        _HueBlendRate("Hue Blend Rate", Range(0.1, 5)) = 1.5 //RGBの重ね具合、熱グラデーションに影響
        _YellowColPow("Yellow Col Pow", Range(0, 1)) = 1
        _WhiteColPow("White Col Pow", Range(0, 1)) = 1

        [Space(10)]
        _OverrideRate("Override Rate", Range(0, 1)) = 1 //元々のピクセルの色にどれだけ熱グラデーションを被せるか
        _HueOffset("Hue Offset", float) = 0 //グラデーションの移動値

        [Space(10)]
        [Toggle] _UseAutoAnim("UseAutoAnim", float) = 0 //経過時間によって自動でアニメーションをするか
        _AnimSpeed("AnimSpeed", Range(0.1, 10)) = 2 //グラデーションが変化するスピード
    }

    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"

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

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

                    //画像の縦横比、nointerpolationで線形補完を禁止
                    nointerpolation half2 ratio : TEXCOORD3;
                };

                //uGUI Image > Source Imageにアタッチされた画像を参照する
                TEXTURE2D(_MainTex);
                SAMPLER(sampler_MainTex);

                //SRP Batcherを適用
                CBUFFER_START(UnityPerMaterial)
                    //Propertiesに対応する変数
                    half _HueBlendRate;
                    half _YellowColPow;
                    half _WhiteColPow;

                    half _OverrideRate;
                    half _HueOffset;

                    float _UseAutoAnim;
                    float _AnimSpeed;
                CBUFFER_END

                //渡された0~1の範囲の1次元変数をRGBの3次元変数に変換する
                //最終的にピクセルシェーダーの方で反転させるので、この関数では赤を出力させず緑と青のみ出力させる
                half3 HUEtoRGB(in float H)
                {
                    float R = 0;
                    //RとGが重なると黄色になるので、ここで_YellowColPowを使ってGの強さを調整する
                    float G = 2.3 - abs(H * 6 - 3) + (1 - _YellowColPow);
                    //R,G,Bが重なると白になるので、ここで_WhiteColPowを使ってBの強さを調整する
                    float B = 2.8 - abs(H * 6 - 3) + (1 - _WhiteColPow);
                    //0~1の間に値を固定
                    float3 fixCol = saturate(float3(R, G, B));
                    return fixCol;
                }

                //頂点シェーダー
                Varyings vert (Attributes input)
                {
                    Varyings output;

                    output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
                    output.uv = input.uv;
                    output.color = input.color;

                    //RectTransformのWidthのHeightの設定値を参照し、そのサイズをratioに保存
                    float2 sizeDelta = abs(input.positionOS.xy) * 2.0;
                    output.ratio = half2(sizeDelta.x , sizeDelta.y);

                    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);

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

                    //画像の縦横の短い方を取得
                    half minScreen = min(input.ratio.x, input.ratio.y);
                    //x軸とy軸の座標を補正、画像の縦横比を適切に掛けることで正円にする
                    uvFixedCenter.x = uvFixedCenter.x * (minScreen / input.ratio.y);
                    uvFixedCenter.y = uvFixedCenter.y * (minScreen / input.ratio.x);
                    //-0.5も+0.5も中心点からの距離という意味では同じなので絶対値にする
                    uvFixedCenter = abs(uvFixedCenter);

                    //lengthで中心からの直線距離を計算
                    float len = length(uvFixedCenter);
                    //_UseAutoAnimがtrueの時は時間経過にしたがってアニメーション、そうでなければ_HueOffsetの値でアニメ
                    half shiftNum = (_UseAutoAnim * _Time.y * _AnimSpeed) + ((1 - _UseAutoAnim) * hueOffset);

                    //グラデーションの初期位置を少しずらす
                    half defaultOffset = 0.3;
                    //対象座標の中心からの距離を、RGBに変換
                    half3 hueColor = (HUEtoRGB((defaultOffset + len + abs(1 - shiftNum % 1)) % 1) / _HueBlendRate);
                    //hueColorを反転、赤を必ず最大値出力させ、赤と緑が重なった所は黄色に、赤と緑と青が重なった所は白色になる
                    hueColor = 1 / hueColor;

                    //ピクセル色にhueColorを混合
                    rainbowColor.rgb *= hueColor;
                    //各色の最大値である1を超えないようにsaturateで収める
                    rainbowColor.rgb = saturate(rainbowColor.rgb);

                    //_OverrideRateに応じて虹色画像の重ね具合を決める
                    half4 resultColor = lerp(originalColor, rainbowColor, _OverrideRate);
                    return resultColor;
                }
            ENDHLSL
        }
    }
}

シェーダーファイルを作成したら、次にMaterialを新規作成し、Shaderの欄に
 UI/Rainbow 
を指定します。

作成したMaterialをImageと紐づければ実装完了です。
インスペクターからMaterialの数値を弄るとシェーダー効果の反映を確認できます。

この辺りの紐づけの仕様についてはこちらでも解説してあります。 p.63 : 【Unity Shader 基礎】Imageにシェーダーを反映させる方法

プロパティの解説

ヒートグラデーションのプロパティ
 Hue Blend Rate 
: RGBの重ね具合、グラデーションに影響する。この値が低いとRBGがくっきり分かれてグラデーションにはならない。
 Yellow Col Pow 
: グラデーション時の黄色の強さ。
 White Col Pow 
: グラデーション時の白の強さ。

 Override Rate 
: 0で元の画像のみを表示、1でヒートグラデーションに染まった画像のみを表示。
 Hue Offset 
: グラデーションのピクセルの移動値。UseAutoAnimtionがfalseの時のみ有効。

 Use Auto Anim 
: Unityプレイ中に自動でアニメーションするかどうか。
 Anim Speed 
: Use Auto Animがtrueの時のアニメーションスピード。
以下それぞれの項目を弄った時のサンプル動画です。

Hue Blend Rate

Yellow Col Pow

White Col Pow

Override Rate

Hue Offset

Use Auto Anim

これをOnにするとHue Offsetによる操作が無効になり、代わりにUnity Play時に自動でアニメーションを実行するようになります。

Anim Speed

0
0