-->


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


