Unityヒートグラデーションシェーダー

Unityヒートグラデーションシェーダー

[Unity uGUI] ヒートグラデーションシェーダー。画像を熱したように見せる実装。
(Heat Gradation Shader)

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

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

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

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

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

以下コード全文です。uGUI Imageへの反映方法は こちらの記事 参照。
Shader "UI/HeatGradation"
{
    Properties
    {
        _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 { "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 _YellowColPow;
        fixed _WhiteColPow;

        fixed _OverrideRate;
        fixed _HueOffset;

        float _UseAutoAnim;     
        float _AnimSpeed;   

        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次元変数に変換する

            
//最終的にピクセルシェーダーの方で反転させるので、この関数では赤を出力させず緑と青のみ出力させる

            fixed3 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;
            }

            
//中心から外側に広がるように熱グラデーションが広がる

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

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

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

                fixed hueOffset = max(0, _HueOffset);
                
//_UseAutoAnimがtrueの時は時間経過にしたがってアニメーション、そうでなければ_HueOffsetの値でアニメ

                fixed shiftNum = (_UseAutoAnim * _Time.y * _AnimSpeed) + ((1 - _UseAutoAnim) * hueOffset);

                
//グラデーションの初期位置を少しずらす

                fixed defaultOffset = 0.3;
                
//対象座標の中心からの距離を、RGBに変換

                fixed3 hueColor = (HUEtoRGB((defaultOffset + length + abs(1 - shiftNum % 1)) % 1) / _HueBlendRate);
                
//hueColorを反転、赤を必ず最大値出力させ、赤と緑が重なった所は黄色に、赤と緑と青が重なった所は白色になる

                hueColor = 1 / hueColor;
                
//ピクセル色にhueColorを混合

                color.rgb *= hueColor;
   
                
//_OverrideRateに応じて熱グラデーション画像の重ね具合を決める

                color.a *= _OverrideRate;
                return color;
            }

            ENDCG
        }
    }
}

プロパティの解説

ヒートグラデーションのプロパティ
 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 
: UseAutoAnimationがtrueの時のアニメーションスピード。
0
0