Shader
"UI/HeatHaze"
{
Properties
{
[HideInInspector]_MainTex("-",2D)="white"{}
_NoiseTex("NoiseTex",
2D)
=
"white"{}
[Header(LensFlare)]
[Space(10)]
_Degree("Degree",
Range(0,
359))
=
0
//光線の角度を指定
_FlareLength("FlareLength",
Range(0,
1))
=
0.8
//光線の長さを指定
_FlareConverge("FlareConverge",
Range(0,
1))
=
1
//大きいほど光が端に寄り小さいほど中央に寄る
[Space(10)]
_FlareSize("FlareSize",
Range(0.1,
2))
=
0.9
//レンズフレアの大きさ
_FlareHuePlus("FlareHuePlus",
Range(-1,
1))
=
0
//レンズフレアの虹色を変化させる
_FlareLuminance("FlareLuminance",
Range(0.1,
2))
=
0.8
//レンズフレアの光の強さ
[Space(10)]
[Toggle]
_UseFlareAutoAnim("UseFlareAutoAnim",
float)
=
0
//経過時間によって自動で_FlareLuminanceを変化させるか
[Header(Flactuation)]
[Space(10)]
_FluctPow("FluctPow",
Range(0.01,
0.05))
=
0.02
//歪みの強さ
_AnimSpeed("AnimSpeed",
Range(0.1,
1))
=
0.4
//歪みが変化するスピード
_FluctScroll("FluctScroll",
float)
=
0
//参照するノイズ画像の座標をずらす、この値を変化させると画面がゆらぐように見える
[Space(10)]
[Toggle]
_UseFluctAutoAnim("UseFluctAutoAnim",
float)
=
0
//経過時間によって自動で_FluctScrollを変化させるか
[Header(Other)]
[Space(10)]
_Brightness("Brightness",
Range(1,
2))
=
1.3
//画面全体の輝き
_OverrideCol("OverrideCol",
Color)
=
(1,
0,
0,
1)
//画面全体を単一色で上書きする際の色
_OverrideRate("OverrideRate",
Range(0,
1))
=
0.15
//画面全体を単一色で上書きする配合率
}
SubShader
{
Tags
{
"Queue"
=
"Transparent"
"RenderType"="Transparent"
}
Cull
Off
ZWrite
Off
Blend
SrcAlpha
OneMinusSrcAlpha
CGINCLUDE
#pragma
vertex
vert
#pragma
fragment
frag
#include
"UnityCG.cginc"
struct
appdata
{
float4
vertex
:
POSITION;
float2
uv
:
TEXCOORD0;
};
struct
v2f
{
float4
vertex
:
SV_POSITION;
float2
uv
:
TEXCOORD0;
};
sampler2D
_MainTex;
sampler2D
_NoiseTex;
sampler2D
_GrabTexture;
//LensFlare
fixed
_Degree;
fixed
_FlareLength;
fixed
_FlareConverge;
fixed
_FlareSize;
fixed
_FlareLuminance;
fixed
_FlareHuePlus;
float
_UseFlareAutoAnim;
//Flactuation
float
_FluctPow;
float
_AnimSpeed;
float
_FluctScroll;
float
_UseFluctAutoAnim;
//Other
fixed
_Brightness;
fixed4
_OverrideCol;
fixed
_OverrideRate;
v2f
vert(appdata
v)
{
v2f
o;
o.vertex
=
UnityObjectToClipPos(v.vertex);
o.uv
=
ComputeGrabScreenPos(o.vertex);
return
o;
}
//光線の長さを修正
fixed2
reflectLength(fixed
baseX,
fixed
baseY)
{
fixed
remainX
=
saturate(0.5
-
baseX)
*
(1
-
_FlareLength);
fixed
remainY
=
saturate(0.5
-
baseY)
*
(1
-
_FlareLength);
return
fixed2(baseX
+
remainX,
baseY
+
remainY);
}
//光線を適切に中央に寄せる
fixed2
reflectConverge(fixed
baseX,
fixed
baseY)
{
return
fixed2(baseX
*
_FlareConverge,
baseY
*
_FlareConverge);
}
//_Degreeの入力値に合わせて座標を適切に変換
//baseX = 右上にレンズフレアがある時のx軸のベース座標
//baseY = 右上にレンズフレアがある時のy軸のベース座標
fixed2
reflectDegree(fixed
baseX,
fixed
baseY)
{
//_Degree=0が右上になってるので、少し計算が特殊になってる
//画面を左45度傾けたとして、_Degree値が中心から右に寄ってるか。180で割るとバグるので179.9で代替え
fixed
isRight
=
step(_Degree
/
179.9,
1);
//画面を左45度傾けたとして、_Degree値が中心から上に寄ってるか。90で割るとバグるので89.9で代替え
fixed
isUp
=
isRight
*
step(_Degree
%
179.9
/
89.9,
1)
+
(1
-
isRight)
*
(1
-
step(_Degree
%
179.9
/
89.9,
1));
//画面を4つの区間に分割
fixed
isRightUp
=
isRight
*
isUp;
fixed
isRightDown
=
isRight
*
(1
-
isUp);
fixed
isLeftDown
=
(1
-
isRight)
*
(1
-
isUp);
fixed
isLeftUp
=
(1
-
isRight)
*
isUp;
//0~1の値を返す。_Degreeが45, 135, 225, 315の時transは(ほぼ)ゼロになる
fixed
trans
=
(45
-
_Degree
%
89.9)
/
45;
//x軸の座標を修正
fixed
fixX
=
isRightUp
*
baseX
+
isRightDown
*
baseX
*
trans
+
isLeftDown
*
-baseX
+
isLeftUp
*
-baseX
*
trans;
//y軸の座標を修正
fixed
fixY
=
isRightUp
*
baseY
*
trans
+
isRightDown
*
-baseY
+
isLeftDown
*
-baseY
*
trans
+
isLeftUp
*
baseY;
return
fixed2(fixX,
fixY);
}
//レンズフレアの座標修正
fixed2
fixFlarePos(fixed
x,
fixed
y)
{
fixed2
fixUv
=
reflectConverge(x,
y);
fixUv
=
reflectLength(fixUv.x,
fixUv.y);
fixUv
=
reflectDegree(fixUv.x,
fixUv.y);
return
fixUv;
}
//レンズフレアの大きさを修正
fixed2
reflectSize(fixed
size)
{
return
size
*
_FlareSize
;
}
//floatをRGBに変換
fixed3
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);
return
saturate(float3(R,
G,
B));
}
//レンズフレアの円を作成する
//shiftX = 画面中央からどれだけズレるか、-0.5~0.5の値を受け入れる
//shiftY = 画面中央からどれだけズレるか、-0.5~0.5の値を受け入れる
fixed4
createFlare(v2f
IN,
fixed
size,
fixed
shiftX,
fixed
shiftY,
fixed
hueBlendRate,
fixed
overrideRate,
fixed
hueOffset,
fixed
inStartAlpha,
fixed
inRangeAlpha,
fixed
outStartAlpha,
fixed
outRangeAlpha)
{
size
=
reflectSize(size);
fixed4
color
=
(tex2D(_MainTex,
IN.uv));
fixed
offset
=
max(0,
hueOffset
+
_FlareHuePlus);
fixed3
hueColor;
fixed
outAlpha
=
1;
fixed
inAlpha
=
1;
//渡されたuv座標を作成する円の座標に改変。座標は画面中央を0とし、xもyも最小値が-1、最大値が1になる
fixed
fixX
=
abs(IN.uv.x
-
0.5
-
shiftX)
*
2;
fixed
fixY
=
abs(IN.uv.y
-
0.5
+
shiftY)
*
2;
//解像度の縦横比に関わらず円を正円にするための処理と、円の大きさの修正
fixed
minScreen
=
min(_ScreenParams.x,
_ScreenParams.y);
fixX
=
fixX
*
(minScreen
/
_ScreenParams.y)
/
size;
fixY
=
fixY
*
(minScreen
/
_ScreenParams.x)
/
size;
//画面中央からの直線距離を取得
fixed
atan
=
sqrt(fixX
*
fixX
+
fixY
*
fixY);
//距離からHUE値を取得
fixed
fixHue
=
abs(atan
+
offset);
//HUEをRGBに変換しを虹色として円に反映
hueColor=
(HUEtoRGB((abs(fixHue))
%
1)
/
hueBlendRate);
color.xyz
*=
1
/
hueColor;
//円の中心から外に向かうアルファ値を取得
fixed
fixInStartAlpha
=
inStartAlpha
-
hueBlendRate;
inAlpha
=
saturate(atan
-
fixInStartAlpha);
inAlpha
=
saturate(inAlpha
/
inRangeAlpha);
//円の輪郭付近のアルファ値を取得
fixed
fixOutStartAlpha
=
outStartAlpha
-
(hueBlendRate
/
2)
;
outAlpha
=
saturate(atan
-
fixOutStartAlpha);
outAlpha
=
1
-
saturate(outAlpha
/
outRangeAlpha);
//変数を4つかけて最終的なアルファ値を決定
fixed
luminance
=
_UseFlareAutoAnim
*
(_FlareLuminance
+
sin(_Time.y)
*
0.2)
+
(1
-
_UseFlareAutoAnim)
*
_FlareLuminance;
color.a
=
outAlpha
*
inAlpha
*
overrideRate
*
luminance;
return
color;
}
ENDCG
//画面全体のゆらぎを実行
GrabPass{}
Pass
{
CGPROGRAM
fixed4
frag
(v2f
i)
:
SV_Target
{
float2
nUv
=
i.uv;
//UseFlareAutoAnimがOnの時は時間経過によってノイズの位置をずらす、Offの時はFluctScrollを参照する
fixed
shift
=
((_UseFluctAutoAnim
*
_Time.y)
+
((1
-
_UseFluctAutoAnim)
*
_FluctScroll))
*
_AnimSpeed;
//ノイズ画像をループさせる時に途切れ感を失くすために、サイン波を利用する
//まずsin関数にuv座標のy軸とshift値を合計したものを渡し、数値を-1~1の範囲に収める
//それをuv座標用に0~1の範囲に圧縮し、y軸に上書き
nUv.y
=
(sin(nUv.y
+
shift)
+
1)
/
2;
//tex2Dを使うことで、指定テクスチャの指定uv座標のカラー値を取得
fixed4
uvNoise=
tex2D(_NoiseTex,
nUv);
//カラーのRGB値を座標の修正値として無理やり変形させる処理
//ノイズ画像はモノクロのため、黒=(0, 0, 0)、白=(1, 1, 1)のようにRGB値は全て一緒になる
//どこから取得してもいいがここではrから値を取得、更に値の範囲を0~1から-1~1に拡大し座標の修正値とする
fixed
noise
=
uvNoise.r
*
2
-
1;
//画面の上下端では歪みを実行させないためのnoise配合率を算出
fixed
isUvBotom
=
step(i.uv.y,
0.1);
fixed
rate1
=
isUvBotom
*
(i.uv.y
/
0.1)
+
(1
-
isUvBotom)
*
1;
fixed
isUvUp
=
1
-
step(i.uv.y,
0.9);
fixed
rate2
=
isUvUp
*
((0.1
-
(i.uv.y
-
0.9))
/
0.1)
+
(1
-
isUvUp)
*
1;
fixed
noiseRate
=
rate1
*
rate2;
//noiseの値は-1~1の範囲に収まっている
//これに_FluctPowを掛けると、最小で-0.01~0.01、最大で-0.1~0.1の範囲に収まる
//その修正された値で、対象画像のuv座標のy軸だけ移動させ、描画するピクセルをズラす
i.uv.y
+=
noiseRate
*
(noise
*
_FluctPow);
//Grabした画像に変形させたuv座標を適用させ歪ませる
fixed4
col
=
tex2D(_GrabTexture,
i.uv);
return
col;
}
ENDCG
}
//虹リング大の描写
Pass
{
CGPROGRAM
fixed4
frag(v2f
IN)
:
SV_Target
{
fixed2
fixPos
=
fixFlarePos(0.35,
0.35);
fixed4
color
=
createFlare(IN,
0.4,
fixPos.x,
fixPos.y,
0.1,
0.25,
12.8,
0,
0,
0.95,
0.1);
return
color;
}
ENDCG
}
//虹リング小の描写
Pass
{
CGPROGRAM
fixed4
frag(v2f
IN)
:
SV_Target
{
fixed2
fixPos
=
fixFlarePos(0.17,
0.17);
fixed4
color
=
createFlare(IN,
0.23,
fixPos.x,
fixPos.y,
0.1,
0.2,
14.9,
0,
1,
0.8,
0.2);
return
color;
}
ENDCG
}
//虹リング中の描写
Pass
{
CGPROGRAM
fixed4
frag(v2f
IN)
:
SV_Target
{
fixed2
fixPos
=
fixFlarePos(0.23,
0.23);
fixed4
color
=
createFlare(IN,
0.38,
fixPos.x,
fixPos.y,
0.55,
0.35,
4.65,
0.2,
0.8,
0.9,
0.1);
return
color;
}
ENDCG
}
//白色発光大の描写
Pass
{
CGPROGRAM
fixed4
frag(v2f
IN)
:
SV_Target
{
fixed2
fixPos
=
fixFlarePos(0.47,
0.47);
fixed4
color
=
createFlare(IN,
0.6,
fixPos.x,
fixPos.y,
1,
0.9,
0.3,
0,
0,
0.8,
0.7);
return
color;
}
ENDCG
}
//白色発光中の描写
Pass
{
CGPROGRAM
fixed4
frag(v2f
IN)
:
SV_Target
{
fixed2
fixPos
=
fixFlarePos(0.26,
0.26);
fixed4
color
=
createFlare(IN,
0.3,
fixPos.x,
fixPos.y,
1,
0.5,
1.5,
0,
0,
0.9,
0.15);
return
color;
}
ENDCG
}
//白色発光小の描写
Pass
{
CGPROGRAM
fixed4
frag(v2f
IN)
:
SV_Target
{
fixed2
fixPos
=
fixFlarePos(0.12,
0.12);
fixed4
color
=
createFlare(IN,
0.15,
fixPos.x,
fixPos.y,
0.9,
0.3,
2,
0,
0,
0.9,
0.1);
return
color;
}
ENDCG
}
//画面全体を発光させる処理
GrabPass{}
Pass
{
CGPROGRAM
fixed4
frag(v2f
IN)
:
SV_Target
{
fixed4
color
=
(tex2D(_GrabTexture,
IN.uv));
color
=
color
*
_Brightness;
color
=
(1
-
_OverrideRate)
*
color
+
(_OverrideRate)
*
_OverrideCol;
return
color;
}
ENDCG
}
}
}