この記事は「ちゅらっぷす Advent Calendar 2019」の1日目です。
https://qiita.com/advent-calendar/2019/churapps
環境
- Unity2018.3.6
やること
- アフィン変換の行列を使ってShaderで画像を移動・回転・拡縮できるようにする
Unityでエフェクトとか作っているとShaderだけで画像を動かしたくなる場面が結構あったので、これをアフィン変換というなんか凄い変換で解決する
アフィン変換の行列
アフィン変換で移動・回転・拡縮するための行列はそれぞれ以下の通り
移動
\begin{bmatrix}
x \\
y \\
1
\end{bmatrix}
=
\begin{bmatrix}
x' \\
y' \\
1
\end{bmatrix}
\times
\begin{bmatrix}
1 & 0 & 0 \\
0 & 1 & 0 \\
PosX & PosY & 1
\end{bmatrix}
回転
\begin{bmatrix}
x \\
y \\
1
\end{bmatrix}
=
\begin{bmatrix}
x' \\
y' \\
1
\end{bmatrix}
\times
\begin{bmatrix}
cos\theta & sin\theta & 0 \\
-sin\theta & cos\theta & 0 \\
0 & 0 & 1
\end{bmatrix}
拡縮
\begin{bmatrix}
x \\
y \\
1
\end{bmatrix}
=
\begin{bmatrix}
x' \\
y' \\
1
\end{bmatrix}
\times
\begin{bmatrix}
1/ScaleX & 0 & 0 \\
0 & 1/ScaleY & 0 \\
0 & 0 & 1
\end{bmatrix}
これをShader内で書くと以下のようになる
// 移動
float3x3 posisionMatrix = {
1, 0, 0,
0, 1, 0,
_PosX, _PosY, 1
};
// 回転
float3x3 rotateMatrix = {
cos (_Rotate), sin (_Rotate), 0,
-sin (_Rotate), cos (_Rotate), 0,
0, 0, 1
};
// 拡縮
float3x3 scaleMatrix = {
1/_ScaleX, 0, 0,
0, 1/_ScaleY, 0,
0, 0, 1
};
// UVに乗算
float3 mulUV = mul (uv, positionMatrix);
mulUV = mul (uv, rotateMatrix)
mulUV = mul (uv, scaleMatrix);
uv = mulUV;
画像の左下が中心になっているので、ピボットの計算も加える
fixed3 pivot = fixed3 (0.5, 0.5, 0.0);
// UVに乗算
float3 mulUV = mul (uv, positionMatrix) - pivot;
mulUV = mul (uv, rotateMatrix)
mulUV = mul (uv, scaleMatrix);
uv = mulUV + pivot;
いろいろ加工してみる
移動量に応じてアルファ値を変えてみる
color.a = color.a * (1 - saturate (abs (_PosX)));
ピボットからの距離によって回転量を変えてみる
_Rotate = _Rotate * ((sqrt(2) * 0.5) - pow (distance (pivot, uv), 8))
てきとうに拡縮
_ScaleY = _ScaleY + (1 - _ScaleY) * (sin (i.uv.x * 180) * 0.5 + 0.5) * _ScaleY;