Shader
"UI/Rainbow"
{
Properties
{
_HueBlendRate("Hue
Blend
Rate",
Range(0.1,
5))
=
2
//RGBの重ね具合、虹色のグラデーションに影響
_OverrideRate("Override
Rate",
Range(0,
1))
=
1
//元々のピクセルの色にどれだけ虹色を被せるか
_HueOffset("Hue
Offset",
float)
=
0
//虹色の移動値
[Space]
//虹色の混合の仕方、ToShinyはHueBlendRateが高いほど真っ白に近づく。ToDarkは逆で真っ黒に近づく。
[KeywordEnum(ToShiny,
ToDark)]
_HUETYPE("HueType",
Int)
=
0
//虹色の染め上げ方。
[KeywordEnum(Circle1,
Circle2,
Vertical,
Horizontal)]
_GRADATIONTYPE("GradationType",
Int)
=
0
}
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
_OverrideRate;
fixed
_HueOffset;
#pragma
multi_compile
_HUETYPE_TOSHINY
_HUETYPE_TODARK
#pragma
multi_compile
_GRADATIONTYPE_CIRCLE1
_GRADATIONTYPE_CIRCLE2
_GRADATIONTYPE_VERTICAL
_GRADATIONTYPE_HORIZONTAL
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次元変数に変換する
//taken from: http://www.chilliant.com/rgb2hsv.html
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));
}
fixed4
frag(v2f
IN)
:
SV_Target
{
fixed4
color
=
(tex2D(_MainTex,
IN.uv))
*
IN.color;
//_HueOffsetの最小値を0にする
fixed
hueOffset
=
max(0,
_HueOffset);
fixed3
hueColor;
#ifdef
_GRADATIONTYPE_CIRCLE1
//中心から回転するように虹色グラデーションが広がる
//円周率の2倍を作っておく(以下2πと表記)、radian値の計算では2πがdegree値でいう360°になる
float
pi2
=
6.283184;
//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;
//atan2で中心点から対象座標への角度を取得する、返ってくる値は-2πから2πの範囲
//-2πと2πは回転方向が違うだけでどちらも同じ一周を表す、0°と360°が同じ角度であるのと一緒
float
rad
=
atan2(fixY,
fixX);
//2πを足すことで取得角度の範囲を0~4πに修正し、マイナス値を無くす
rad
+=
pi2;
//hueOffsetの値分だけ取得座標をずらす
rad
+=
hueOffset;
//2πで割ったその余りを算出することで、あらゆる数値を0~2πの範囲の収めてかつ繰り返しのパターンにする
//例 : 1 % 2π = 1, 7.283184 % 2π = 1
rad
%=
pi2;
//HUEtoRGBは引数に0~1しか与えられないので、上の値から2πを割ることで0~2πの範囲を0~1に修正する
rad
/=
pi2;
hueColor
=
(HUEtoRGB(rad)
/
_HueBlendRate);
#elif
_GRADATIONTYPE_CIRCLE2
//中心から外側に広がるように虹色グラデーションが広がる
//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));
hueColor
=
(HUEtoRGB((length
+
hueOffset)
%
1)
/
_HueBlendRate);
#elif
_GRADATIONTYPE_VERTICAL
//y軸に沿って虹色グラデーションに染める
hueColor
=
(HUEtoRGB((IN.uv.y
+
hueOffset)
%
1)
/
_HueBlendRate);
#elif
_GRADATIONTYPE_HORIZONTAL
//x軸に沿って虹色グラデーションに染める
hueColor
=
(HUEtoRGB((IN.uv.x
+
hueOffset)
%
1)
/
_HueBlendRate);
#endif
#ifdef
_HUETYPE_TOSHINY
//光り輝くように虹色を混合
color.xyz
*=
1
/
hueColor;
#elif
_HUETYPE_TODARK
//光を抑えて虹色を混合
color.xyz
*=
hueColor;
#endif
//_OverrideRateに応じて虹色画像の重ね具合を決める
color.a
*=
_OverrideRate;
return
color;
}
ENDCG
}
}
}