UnityでuGUI用カーテンシェーダー。y軸座標に応じてx軸のuv座標をずらす実装。
(Curtain Shader for Unity uGUI)
関連ページ
参考URL
こないだ業務でカーテンの歪みをパッと実装したけど、クオリティに満足いってなかったので更に研究をしていた。
結局求める内容には届かなかったけど、これ以上研究する気力を失くしたのでここで公開。
カーテンシェーダー、コード全文
下がカーテンシェーダーのサンプル動画。
窓が途中で光ってる件に関しては、これは演出上
発光シェーダー
を入れてみただけで今回のカーテンシェーダーは関係ない。
以下コード全文。uGUI Imageへの反映方法は
こちらの記事
参照。
Shader
"UI/CurtainShader"
{
Properties
{
//カーテンを横に押す力
_PressPow
("PressPow",
Range(-1,
1))
=
0
//カーテンのカーブの強さ
_CurvePow
("CurvePow",
Range(0,
10))
=
2
//カーブの外カーブと内カーブの比率に影響
_ReverseCurveRatio
("ReverseCurveRatio",
Range(0,
10))
=
2
}
SubShader
{
Tags
{
"Queue"
=
"Transparent"
}
Blend
SrcAlpha
OneMinusSrcAlpha
Cull
Off
LOD
100
ZWrite
Off
Pass
{
CGPROGRAM
#pragma
vertex
vert
#pragma
fragment
frag
struct
appdata
{
fixed2
uv
:
TEXCOORD0;
fixed4
vertex
:
POSITION;
fixed4
color
:
COLOR;
};
struct
v2f
{
fixed2
uv
:
TEXCOORD0;
fixed4
vertex
:
SV_POSITION;
fixed4
color
:
COLOR;
};
sampler2D
_MainTex;
float
_PressPow;
float
_CurvePow;
float
_ReverseCurveRatio;
v2f
vert
(appdata
v)
{
v2f
o;
o.vertex
=
UnityObjectToClipPos(v.vertex);
o.uv
=
v.uv;
o.color
=
v.color;
return
o;
}
fixed
partRange(v2f
i)
{
return
1
-
i.uv.y;
}
//外カーブ率を百パーセントとした場合の、x軸のピクセルの移動値を返す
fixed
outCurveShift(v2f
i)
{
fixed
y
=
partRange(i);
fixed
slidePos
=
y
*
y
*
pow(y,
_CurvePow)
*
_PressPow;
return
slidePos;
}
//内カーブ率を百パーセントとした場合の、x軸のピクセルの移動値を返す
fixed
inCurveShift(v2f
i)
{
fixed
y
=
partRange(i);
fixed
slidePos
=
y
*
(y
-
2)
*
pow((y
-
2)
*
(y
-
2),
_CurvePow)
*
_PressPow;
return
-slidePos;
}
//内カーブの比率
fixed
inRatio(v2f
i)
{
fixed
y
=
partRange(i);
fixed
inRatio
=
y
*
pow(y,
_ReverseCurveRatio);
return
inRatio;
}
//外カーブのピクセル移動値を比率を適用して取得
fixed
outCurveShiftWithRatio(v2f
i)
{
return
outCurveShift(i)
*
(1
-
inRatio(i));
}
//内カーブのピクセル移動値を比率を適用して取得
fixed
inCurveShiftWithRatio(v2f
i)
{
return
inCurveShift(i)
*
inRatio(i);
}
fixed4
frag
(v2f
i)
:
SV_Target
{
//外カーブと内カーブのピクセル移動値を合成
float
curveX
=
i.uv.x
+
outCurveShiftWithRatio(i)
+
inCurveShiftWithRatio(i);
fixed2
fixUv
=
fixed2(curveX
,
i.uv.y);
//_PressPowに応じてカーテンのy軸のスケールを少し小さくする
fixed
scaler1
=
(1
+
abs(_PressPow
/
1));
//y軸のスケールを小さくしたのに応じて、uv座標を少し上にあげる
fixed
adjust1
=
(1
-
scaler1)
*
0.9;
fixUv
=
fixed2(fixUv.x,
fixUv.y
*
scaler1
+
adjust1);
fixed4
col
=
tex2D(_MainTex,
fixUv);
col
*=
i.color;
return
col;
}
ENDCG
}
}
}
プロパティを解説
インスペクターでプロパティの値を操作し、効果を試すことが出来る。プロパティは3つしかない。
コードを少し解説
基本的にやってることは、v2f iに渡された各ピクセルのy軸座標の大きさに応じて、x軸の座標を横にずらすという処理をしている。
uv座標のy軸は、下から上に向けて0から1に進むので、partRange関数内で1から引かせている。
こうすることで、カーテンが下にいくほどx軸のズレが大きくなっている。
fixed partRange(v2f i)
{
return 1 - i.uv.y;
}
y軸座標からx軸の移動値を算出する際に、まず対象のy軸座標に極端なEaseをかけて値を歪め、x軸のピクセル移動のカーブ処理につなげている。
カーテンの上半分を占める外カーブは、OutQuadの式の一部であるt * tを参考にした。
ただし、t(時間)の値をyに置き換えている。
//外カーブ率を百パーセントとした場合の、x軸のピクセルの移動値を返す
fixed
outCurveShift(v2f
i)
{
fixed
y
=
partRange(i);
fixed
slidePos
=
y
*
y
*
pow(y,
_CurvePow)
*
_PressPow;
return
slidePos;
}
powのべき乗によって、_Curveの値に応じて更に強いEaseをかけている。
カーテンの下半分を占める内カーブは、InQuadの式の一部であるt * (t - 2)を参考にした。こちらもtをyに置き換え。
//内カーブ率を百パーセントとした場合の、x軸のピクセルの移動値を返す
fixed
inCurveShift(v2f
i)
{
fixed
y
=
partRange(i);
fixed
slidePos
=
y
*
(y
-
2)
*
pow((y
-
2)
*
(y
-
2),
_CurvePow)
*
_PressPow;
return
-slidePos;
}
0
0