
Graphilia入門
※この記事は、VRChat(VRSNSプラットフォーム)で活動する「VRChatワールド探索部」、通称ワ探の部員によるアドベントカレンダー、 #ワ探アドカレ の19日目です。
VRChatには、Graphiliaというワールドがあります。
ワールドの中でシェーダーを作ることができます。
ノードベースで、とても操作しやすいUIなので快適に遊べます。
もっとたくさんの人がGraphiliaで遊んだり、それをきっかけにシェーダーを書いたりしてほしいので、今回はGraphiliaの入門記事を書いてみようと思います。
どれくらい読みやすく書けているかわかりませんが、シェーダーがわからなくても、アバター改変やワールド作成でUnityを触ったことがあるVRChatterであればわかる、というところを目指してみます。
基本操作についてはワールド内にも書いてありますが、以下を抑えておけば良いです。
・頭のうえにあるステッキを掴んだ状態で、右手コントローラーのスティックを上に倒しているあいだ、UIが表示されます。
・数値を変更するとき、スティックを下に倒しながら操作すると0.5刻みで変更できます。
シェーダーと言えば主に色を付けるものですが、Graphiliaにおいてより直感的に理解できて入門に適しているのは頂点シェーダーだと思います。
これはモデルの形状を変えたり、動かしたりすることができます。
なので、まずUIからConfigを開き、Vertex Shader(=頂点シェーダー)ONを選びます。
※RadeonのGPUを使用している場合はクラッシュしてしまうそうなのでご注意ください。

頂点シェーダーで何をするか。
ビームを飛ばします。

ビームは作りがシンプルな割に楽しく、基本となる掛け算・足し算がどういった挙動をするのかよく理解することができます。アレンジも色々出来て面白いです。
手順を追っていきましょう。
①元となる球を出す
UIを開き、Outputの中にあるSphereを選びます。
以降、この操作を以下のように書きます。
Output>[Sphere]を出します。

②Local Positionを出す
Input>[Local Position]を出し、先に出した[Sphere]のpositionに繋ぎます。

このノードには何が入っているのでしょうか。

例えば右端の頂点は、X=-1, Y=0, Z=0の位置にあります。
※この画面はHoudini、値を表示する頂点や有効桁数は適当に間引いています。
図のように、球の中心を(0, 0, 0)としたときの各頂点の座標がlocal positionには入っています。
③ビームの形状を作る。
Arith>[Mul]
Value>[Vec3]
を出し、[Mul]に[Local Position]と[Vec3]を繋ぎます。
[Vec3]のXは大きい数値(とりあえず10前後)を入れ、他には1を入れます。

[Mul]は掛け算です。[Local Position]から入ってきたすべての頂点の位置に、[Vec3]の値が掛け算されます。例えば(12,1,1)を入力します。
すると、上の画像で言うところの右端の頂点は(-12, 0, 0)のような位置に移動します。球は左右に伸びます。
高さと奥行きは変えたくないので、YとZには1を掛けます。

それぞれの頂点に同じように(12,1,1)が掛け算されています。
④移動させる。
一番難しいところです。理解を深めるから進めるために、まずは[Add]、つまり足し算がどういう挙動をするのか確認してみましょう。
Arith>[Add]
Input>[Vec3]
を出し、さっきの[Mul]のあとに繋いでみます。

[Vec3]の値を動かしてみると、球が色々な方向に動きます。
全ての頂点に同じ値を足しているので、スライドするように移動するわけです。

次に進む前に、[Vec3]の値は(0,0,0)に戻しておきます。
この[Add]を使って、時間経過で球が移動するようにすればビームの動きを作ることができそうです。
Func1>[Fract]
Input>[Time]
を出し、以下のように繋ぎます。

Timeにはインスタンスに入ってからの時間が秒単位で入っています。
時間経過で何か動かすにはこれを使いますが、そのままだとどんどん増えてとても大きな値になってしまいます。5分経ったら300が入っています。
Fractは入力の小数点以下の部分だけを取り出すものです。
1.1なら0.1、5.6なら0.6、0.3なら0.3が返ってきます。
TimeとFractを繋げた結果を言葉で説明するのは難しいので、グラフで示します。
以下の黄色いグラフのように変化する値を取り出すことができます。
青は元のTimeです。
何秒経っても0と1の間の値が取れるようになります。

※シェーダーを書くとき便利なgraphtoy.com
これを[Vec3]のxに繋ぎ、[Add]を使ってpositionに足します。
動きます。

⑤早く遠くに飛ばす
今は1秒かけて1しか進まない状態です。ビームらしく早く遠くに飛ばすには、グラフで言うとこうなってほしいわけです。

Arith>[Mul]を出し、Fractのあとに繋ぎます。
[Mul]の数値を300くらいまで上げます。

⑥色を付ける
このままだと黒い物体が飛んでいくだけなので、色を付けます。
Input>[Vec3]を出し、好きな色を指定して[Sphere]のcolorに繋ぎます。
[Vec3]のxyzがそのままRGBとして使われます。
256段階のほうが慣れている人もいるかもしれませんが、ここでは(0,0,0)が黒で(1,1,1)が白になります。(1,0,0)は赤。
また、1以上が入るとBloomの効果で滲んで見えます。つまり光ります。

⑦完成
速度やビームの長さを好みに調整して、完成です。


⑧応用
色々とノードを増やして動きがどう変わるか試してみるのも良いです。
形や移動、色などそれぞれの計算をしているノードを跨って繋げるのが面白かったりします。適宜[Mul]で大きさを調整すると良いです。
・[Add]に繋げている値を[Sin][Cos]に通して形状に反映させる


・Other>[HSV2RGB]にX座標を繋げると進みながら色が変化する


⑨補足
今回はノードベースで主に頂点の座標を操作しました。
全ての頂点に同じ計算が行われる、というのがポイントです。
別々の入力(今回は球の各頂点の座標)に対し、同じプログラムの処理が行われて、その結果を返す。
色の方も似たような考え方で、こちらは各ピクセル(みなさんのHMDの画素)ごとに同じプログラムの処理が行われます。入力には色々使えますが、基本的にはUV座標というものを使います。
おまけ
まったく入門向けでは無いですが、以下のような構成で頂点位置にNaNを繋ぐことでGridを裁断して小さなQuadをたくさん取り出すことができます。
Graphiliaで作るパーティクルの最小構成っぽいやつ(仕組みはphi16さんから教わったやつです)(頂点の位置にNaNを繋ぐと関連するポリゴンが消滅する) pic.twitter.com/ePGOPsxgGx
— Ayano (@AYANO_TFT) June 13, 2022
ここから頑張ると蝶を出したり、色々できて楽しいです。
Graphilia by suzuki_i #VRChat_world紹介 pic.twitter.com/Rln1YNR0Kh
— Ayano (@AYANO_TFT) June 11, 2022
— Ayano (@AYANO_TFT) June 11, 2022
動画(こっちは色味調整前だった…) pic.twitter.com/2usRVwI6N5
— Ayano (@AYANO_TFT) June 14, 2022
あとがき
シェーダーは難しいです。
私もわからないことばかりですがなんとか書いています。
でも、VRChatでは日々シェーダーを使った面白いワールドやギミックが作られていて、それを目にする機会がとても多いです。
入口の部分を少しだけでも知っておくと、それらを前よりも一歩踏み込んで楽しめると思います。
とても綺麗なものが、意外と単純な作りだったりもします。
本当に分からないすごいシェーダーが出てきて頭を抱えることも多いですが。("Graphilia"というワールドそのものとか)
ワ探アドカレ、明日はshrさんの「Just a Pool」の解説記事だそうです。
最近の「本当に分からないすごいシェーダー」の一つなので、とても楽しみです。