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