Shader
"UI/Rainbow"
{
Properties
{
_HueBlendRate("Hue
Blend
Rate",
Range(0.1,
5))
=
3
//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
{
"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"
//後述のSRGBToLinearで必要なライブラリ
#include
"Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
struct
Attributes
{
float4
positionOS
:
POSITION;
half4
color
:
COLOR;
half2
uv
:
TEXCOORD0;
};
struct
Varyings
{
float4
positionCS
:
POSITION;
half4
color
:
COLOR;
half2
uv
:
TEXCOORD0;
};
//uGUI Image > Source Imageにアタッチされた画像を参照する
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
//アタッチされたSpriteのサイズを取得(x=1.0/width, y=1.0/height, z=width, w=height)
float4
_MainTex_TexelSize;
//SRP Batcherを適用、動的に変更される数値はこの中に定義
CBUFFER_START(UnityPerMaterial)
half
_HueBlendRate,
_OverrideRate,
_HueOffset;
CBUFFER_END
#pragma
multi_compile
_HUETYPE_TOSHINY
_HUETYPE_TODARK
#pragma
multi_compile
_GRADATIONTYPE_CIRCLE1
_GRADATIONTYPE_CIRCLE2
_GRADATIONTYPE_VERTICAL
_GRADATIONTYPE_HORIZONTAL
//渡された0~1の範囲の1次元変数をRGBの3次元変数に変換する
//taken
from:
http://www.chilliant.com/rgb2hsv.html
half3
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);
half3
rgb
=
saturate(float3(R,
G,
B));
//URPのリニア空間用に色を変換
return
SRGBToLinear(rgb);
}
Varyings
vert(Attributes
input)
{
Varyings
output;
output.positionCS
=
TransformObjectToHClip(input.positionOS.xyz);
output.uv
=
input.uv;
output.color
=
input.color;
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);
half3
hueColor;
#ifdef
_GRADATIONTYPE_CIRCLE1
//中心から回転するように虹色グラデーションが広がる
//円周率の2倍を作っておく(以下2πと表記)、radian値の計算では2πがdegree値でいう360°になる
float
pi2
=
6.283184;
//x, y軸の座標を0~1の範囲から-0.5~0.5の範囲に修正する(画像中央を原点とさせるため)
half2
uvFixedCenter
=
input.uv.xy
-
0.5;
//atan2で中心点から対象座標への角度を取得する、返ってくる値は-2πから2πの範囲
//-2πと2πは回転方向が違うだけでどちらも同じ一周を表す、-360°と360°が同じ角度であるのと一緒
float
rad
=
atan2(uvFixedCenter.y,
uvFixedCenter.x);
//hueOffsetの値分だけ算出した角度をずらす
rad
+=
hueOffset;
//fracを使い1で割った余りを算出して0~0.999..の循環パターンにし、同時にマイナス値はプラスに変換
float
h1
=
frac((rad
/
pi2));
hueColor
=
HUEtoRGB(h1)
/
_HueBlendRate;
#elif
_GRADATIONTYPE_CIRCLE2
//中心から外側に広がるように虹色グラデーションが広がる
//x, y軸の座標を0~1の範囲から-0.5~0.5の範囲に修正する(画像中央を原点とさせるため)
half2
uvFixedCenter
=
input.uv.xy
-
0.5;
//画像の縦横の短い方を取得
half
minScreen
=
min(_MainTex_TexelSize.z,
_MainTex_TexelSize.w);
//x軸とy軸の座標を補正、画像の縦横比を適切に掛けることで正円にする
uvFixedCenter.x
=
uvFixedCenter.x
*
(minScreen
/
_MainTex_TexelSize.w);
uvFixedCenter.y
=
uvFixedCenter.y
*
(minScreen
/
_MainTex_TexelSize.z);
//-0.5も+0.5も中心点からの距離という意味では同じなので絶対値にする
uvFixedCenter
=
abs(uvFixedCenter);
//lengthで中心からの直線距離を計算
float
dist
=
length(uvFixedCenter);
//hueOffsetの値分だけ算出した距離をずらす
dist
+=
hueOffset;
//結果を1で割った余りを算出することで、0~0.999..の循環パターンにする
dist
%=
1;
hueColor
=
HUEtoRGB(dist)
/
_HueBlendRate;
#elif
_GRADATIONTYPE_VERTICAL
//y軸に沿って虹色グラデーションに染める
hueColor
=
(HUEtoRGB((input.uv.y
+
hueOffset)
%
1)
/
_HueBlendRate);
#elif
_GRADATIONTYPE_HORIZONTAL
//x軸に沿って虹色グラデーションに染める
hueColor
=
(HUEtoRGB((input.uv.x
+
hueOffset)
%
1)
/
_HueBlendRate);
#endif
#ifdef
_HUETYPE_TOSHINY
//光り輝くように虹色を混合、この際にmaxで0除算を防ぐ
rainbowColor.xyz
=
rainbowColor.xyz
/
max(0.01,
hueColor);
#elif
_HUETYPE_TODARK
//光を抑えて虹色を混合
rainbowColor.xyz
=
rainbowColor.xyz
*
hueColor
*
10;
#endif
//各色の最大値である1を超えないようにsaturateで収める
rainbowColor.xyz
=
saturate(rainbowColor.xyz);
//_OverrideRateに応じて虹色画像の重ね具合を決める
half4
resultColor
=
lerp(originalColor,
rainbowColor,
_OverrideRate);
return
resultColor;
}
ENDHLSL
}
}
}