# 要約
- スムーズに変化するIFSを考えました
- IFSに用いる関数をFIFOの固定長Queueに入れる感じにできます
- Enqueue/Dequeueをスムーズにでき、イージングをかけることもできます
# はじめに
2023-06-10にVRChatで行われたlambda (opens new window)というDJ/VJイベントでVJをやらせて頂きました。
この記事では、VJシステムをシェーダーで書くに当たって使用した一部の技術(考え方?)を解説します。
なお、VJ全体についての記事は後々書くと思いますので、そちらについてはあまり触れません。
# 目標
私がVJをすることが決まって一番最初に「やりたいな~」と思った作品があります。
— kkmfd (@kk_mfd) February 24, 2023
左下のTESTを見ると分かりやすいのですが、UVがバキバキに変形しています。
これを見て、UVをバキバキにしたいと強く思いました。
バキバキにする方法ですが、私の意思はあまり介在してほしくないのでIFS (opens new window)を使う事にしました。
普通にIFSするだけだとビートに合わせたスムーズなIFSの変形が出来ないため、スムーズに変化するIFSを考えました。私は勝手にこれを『SmoothQueue-IFS』と呼んでいます。
(既に呼び方があったらすいません)
# 解説
SmoothQueue-IFSをUVに対して行う簡単な例を示します。
/*
省略しているFuncでは、与えられたシードによって以下の二つの関数を選択するようになっています
- F0 : UVをランダムに平行移動する
- F1 : UVをランダムに回転する
Twiglで動くコードの全文はこちらです
https://twigl.app?ol=true&ss=-NXkgvDINPBSTVu3hvBR
*/
// uvを[-1, 1]の範囲に変換
vec2 suv = (uv * 2.0 - 1.0);
// Queueを更新する時間間隔
const float span = 0.5;
// Queueの長さ
const int count = 4;
for(int i = 0; i < count; i++)
{
// i番目の関数に流れる時間の定義
float lt = time / span + float(i);
float li = floor(lt);
// 時間の小数部分
float lf = fract(lt);
// ↑にイージングをかける
lf = pow(smoothstep(0.0, 1.0, lf), 0.3);
// 時間の整数部分をハッシュにかけて、関数に固有なシードとする
vec3 s3 = hash31(li) * 42.0;
// Enqueue/Dequeueをスムーズにする
float enque = lf;
float deque = 1.0 - lf;
// 添え字によって関数の強さをスムーズに変えることでEnqueue/Dequeueをする
float ins = ((i == 0) ? deque : (i == count - 1) ? enque : 1.0);
// uvに関数を適用
suv = Func(suv, s3, ins);
}
// 変換したuvを[0, 1]の範囲に戻す
uv = (suv + 1.0) * 0.5;
SmoothQueue-IFSでは、使用する関数は以下の形で定義します。
/*
target : 関数を適用する対象
seed : 関数に固有なシード
ins : 関数の強さ (0.0,1.0)で、0.0の時に関数は何もしない
*/
Hoge Func(Hoge target, vec3 seed, float ins)
{
// targetに対する操作
}
今回の例だと、UVの平行移動は以下の様に定義できます
// UV移動
vec2 F0(vec2 uv, vec3 s3, float ins)
{
float len = 0.5 * ins;
vec2 offset = (hash23(s3) - 0.5) * len;
return uv + offset;
}
以上です。
また、私は言葉による解説が苦手なので、関数の適応をするQueueを可視化してみました。
# 結果
lambdaでのVJで使用した例を紹介します。
# Glitch
こちらは以下の関数が使われています
- uvのfold(折り畳み)
- uvの回転
# Window
こちらは以下の関数が使われています
- uvに対してウィンドウの形状を指定し、固有の識別子を与える
# まとめ
今回はuvに対するIFSのみになってしまいましたが、他の情報に対するIFSもおもしろそうだと思いました。
SDFにSmoothQueue-IFSを適用するとおもしろいものが出来そうですね