見出し画像

Vket2021に出した無限に広がっているように見えるブースの話

#ワ探アドカレ 10日目、2回目の登場となりますAYANO_TFTです。

なんと!昨日無事にワ探アドカレの全予定が埋まりました!発案したときは半分くらい埋まれば良い方かな?と思っていましたが期待以上にご協力いただき、また予想以上に楽しい記事がたくさん読めて本当に嬉しい気持ちです。発案しただけなのですが勝手にプレッシャーを感じていたところもあり只々喜んでいます。しかもまだ折り返していないなんて…残りの記事を読めるのが楽しみです。

前回3日目は自己紹介も無しにいきなり長文ポエムを詠唱してしまったわけですが、今回は普通の口調でVket2021に出したブースの話をしようと思います。ワールド探索とは少し離れますが、バーチャル展示会について思うところなども書いていきます。

こちらのブースですね。色々話題にしてもらえたり、Vket2021公認配信もチェックした限りはおおむね好評だったようで良かったです。

自己紹介

そう、まだ自己紹介すらしていませんでした。

VRChatはQuest2発売くらいから始めたので、1年ちょっとになります。元々特にモデリングやプログラミングや絵ができるわけでもなく、コミケにサークル参加する友達を応援しながら内心羨ましく思っているくらいの創作との距離感だったわけですが、VRChatの熱にあてられてこの1年は色々やれた気がします。アバターを自作してみたりワールドを作ってみたり、シェーダーを書いてみたり売ってみたりしました。ここ半年ほどは専らシェーダーに執心していたので、最近知り合った方はシェーダーの人というイメージが強いかもしれませんが、割と素人寄りです。来年はアバター自作にリベンジしたいなと思ったりしています。Twitterの固定ツイートにあるモーメントにやってきたことをまとめているので、もし興味があれば見てもらえると嬉しいです。

きっかけ

Vket6で見たmyxyさんのこちらのブースがとても印象に残っていました。
まず超良いなと思いました。改めて見て、やはり美しい機構だと思います。

コードも公開されており、解説記事の最後にはこうあります。

何かの参考やインスピレーションの元になれば幸いです。

インスピレーションを受けました。ちょうど次のVketには出展したいな…と思っていたので、何かこういったギミックのあるブースを出そうと思いました。

思想

バーチャル展示会の形式については色々な議論や試行錯誤がされているようです。私が紹介できる範囲では、先月のワールド探索部記事「楽しむ想いから生まれる「インディーズ空間」──"バーチャル空間"の"現在"(sabakichi × FUKUKOZY)」の「第0回建築コンテスト」について話されているパートが非常にわかりやすく、共感できました。Vket6の時期には、ワールドに組み込まれたストーリー演出に対し「そんなものに容量を使うより出展者の制限を緩くすべきだ」という意見が議論を呼んでいたような記憶もあります。

バーチャル展示会というと無限の可能性を感じます。しかし実態としてはまだまだ様々な技術的制約があり、特に容量や他の出展者との兼ね合いといったところに課題がありそうです。VRAAのような形式が私は好きですが、Vketに限れば個々の出展者が別々にワールドを出すのでは意味が無いというのは言うまでもないでしょう。

Vketでは割と厳しい入稿制限を設けることで、ワールドの景観や容量、他の出展者とのバランスを保つという形式に落ち着いています。
入稿ルールのリンクも貼っておきますが、主なところでは以下でしょうか。

・ビルドサイズ10.00MB以内
・ブースを配置できるスペースは幅4m×奥行き4m×高さ5m
・実行時のSetPassCallsの基準値20(≒マテリアルの数)

制限されると突破したくなります。子供の頃、ゲームは1日30分と厳しい制限をされたときはあらゆる手段で搔い潜り、ゲームをプレイしていないときもゲームのことだけ考えていました。その甲斐あって毎日ゲームばかりしている今の私があります。話が脱線しました。

どれもなかなかの厳しさですが、特に2点目が気になりますね。よくVRChat界隈で笑われている話として「仮想空間の土地を買う」というのがありますが、どうやら私は気づかないうちに仮想空間の土地を買っていたようです。出展料は3300円なので、1坪700円弱の良心的な価格です。しかし既にVRChatでも土地に値段が付いているわけです。Vket会場という一定の来場者数が保証された土地には、現実の土地やwebサイトの広告費用と同じように値段が付くわけです。それは妥当なことだと思います。

また、もちろんVket運営が制約を設けなければならない事情はわかっていて、現状のVketの形式や入稿制限はその中で最善を尽くした1つの結果だと思います。

しかしそれはそれとして…無限の大きさのブースを入稿したいですよね。拡大でもループでもなく、無限。1坪いくらに変わるんでしょうか。myxyさんのブースから受けたインスピレーションと、自分の技術的な手札を見合わせて考えてみました。バーチャル展示会なのに空間的な制約を受けている現状に、自分なりのアプローチを見せつけたいと思いました。

レイマーチング

ちょっと技術的な話になります。
そもそも「立体的に絵が映る板」なんてVRChatではありふれていて、みんな感覚的に理解しているような気もします。シェーダーに興味が無ければ、「ブースの構造」の章まで飛ばしても良いかもしれません。

私の未熟な3DCGスキルツリーの中では一番育っている領域として、「レイマーチング」という手法を用いたシェーダーがあります。VRChat内では色々な人がこれを使って大暴れしているので聞いたことはあるという方も多いでしょう。概念の説明としては以下の動画がとてもわかりやすいので引用させて頂きます。

仕組みの詳しい解説は省略します。要するに何が出来るものなのかというと「カメラ位置(VRChatでいうとプレイヤーの視点位置)からプログラム上で定義した3D図形の見え方を計算して描画する」ことができます。
普通のシェーダーはテクスチャをポリゴン上に貼るような動作ですが、レイマーチングのシェーダーではポリゴンを3Dディスプレイのスクリーンのように扱い、プログラム上で定義した図形を投影することができます。
…まだわかりにくいですね。画像でいきましょう。

standardシェーダーのマテリアルを使えばただの板、ただの箱ですが…

スクリーンショット 2021-12-09 211656

今回作成したシェーダーを割り当てるといきなりこうなります。

スクリーンショット 2021-12-09 211907

Unityのヒエラルキー上に床面やパーティクル、上空に浮いた巨大なクリスタルといったオブジェクトはありません。あくまで3Dディスプレイのように「映しているだけ」ということです。視点が取れるとそれを立体的に行えるわけです。

今回活かせるレイマーチング由来の強みは3点あります。
①4×4×5mより広い範囲の景色を見せられる
②シェーダーのプログラムはテキストだから容量が小さい
③カメラ位置を利用していて、その気になればそれをズラせる

①4×4×5mより広い範囲の景色を見せられる
Vketの入稿規定でブースの大きさが決められています。すべてのオブジェクトが範囲内に収まっている必要があります。非表示にしていてもダメですし、ブースに入ったあとUdonなどで外側に移動させてももちろんダメです。しかしレイマーチングのシェーダーで全て囲い、プラネタリウムのように全天に景色を投影すれば、範囲外にオブジェクトを配置することなく疑似的に遠くの景色を見せることができます。実際には4×4×3mの箱に囲われているだけで、外側には何も出ていません。

②シェーダーのプログラムはテキストだから容量が小さい
Vketの入稿規定で容量は10MBまでと制限されています。これは昨今のメジャーな販売アバター1体で上回るかもしれないくらいの容量です。例えばBlenderで影を焼いたような高解像度かつ使いまわせないテクスチャを持ち込む場合は限界があり、展示物の容量とトレードオフになるということです。
構想段階では展示物がどれだけ準備できるか、どんなものになるか未計画でした。前述の思想を踏まえると「たくさん置ける」ようにしたいです。また結果的には無理でしたが汎用性を持たせてブース自体を配布または販売することも検討していたので、ブース側の容量は極限まで削りたかったです。
レイマーチングのシェーダー上でライトやエミッション、フォグなどを定義しリアルタイムで全て計算されるようにすれば、描画負荷は上がりますが容量は削ることができます。プログラムはただのテキストだからです。

③カメラ位置を利用していて、その気になればそれをズラせる
最後のこれが一番重要です。シェーダーのプログラムではカメラ位置、つまりプレイヤーの視点座標を取得できます。それに数値を足せば、別の位置からの景色も投影できるということです。

ブースの仕組み

本題です。
まず簡単なUdonを書いています。
なおテレポートに関する規定は以下の一文のみ、割と緩いです。おそらく2階に移動するテレポートギミックなどを想定しているのでしょう。

プレイヤーのテレポートは、プレイヤーがスペース内にいる状態で、かつスペース内に移動させる場合のみ許可されます。

真上から見るとこんな感じで、テレポート判定のコライダーを置いています。内側の移動可能なスペースはだいたい一辺3.7mくらいです。

スクリーンショット 2021-12-09 213004

四辺を囲うコライダーに触れると、その反対側に3.0mぴったりテレポートするようになっています。一般的なテレポートギミックは「指定の座標に飛ばす」ようになっていますが、これは「現在位置から反対向きに3.0mぶん移動させる」というギミックになっています。

その移動量をシェーダー(マテリアル)のパラメータにも渡すようにしています。すると先ほどの「③カメラ位置を利用していて、その気になればそれをズラせる」が活きてきます。プレイヤーがテレポートした方向と反対向きに同じ量、シェーダーで利用しているプレイヤー視点座標をズラします。するとレイマーチングのシェーダー上におけるプレイヤー視点座標はテレポートしなかったかのように連続して移動しているような状態になります。

イラスト

わかりやすい図ですね。すみません。わかりにくいです。
実際にプレイヤー視点が完全に移動しているのではなく、あくまでこの内壁の描画においてのみ疑似的に移動しているような状態です。だから複数人で入ると本当の位置関係で他の人が表示されます。1回テレポートすれば+3.0m、2回で+6.0m…というように今何回テレポートしたかをシェーダーのパラメータが持っていて、それに合わせた景色を映しています。

図の2と3はUdonで同時に処理していますが、そこでラグなどが発生してテレポートした感が出ないかどうか、というのが心配でした。結果としてそれは杞憂でした。このあたりの処理は詳しくないのですが、テレポートもマテリアルに値を渡すのも1フレームで終わるようです。個々人の視界にだけ関わるギミックなので、同期なども行う必要はありません。脚のIKは遅れて動くようで、テレポートに合わせて一瞬脚が上がりますが許容範囲です。

なんとメインの仕組みはこれだけです。3.0mちょうどテレポートさせて、その移動量の合計をマテリアルのパラメータで保持して視点の座標から引くだけです。あとは以下の細かな処理があります。

・初期位置で扉をくぐったときはテレポートしない(つまり脱出できる)
・一定範囲を超えたらテレポート処理をやめる(一応200mくらいで行き止まりです)
・座標に応じて展示物を出し入れする
以下のような形で何をどこで出すか登録できるようにしておき、一致していたら出し、一致していなかったら出さないようにしました。

画像4

・VRCメニューからリスポーンした場合を考慮し、ブースから脱出したら移動量をリセットする

Udonについてはこんなところです。
次にシェーダー側の説明をしていきます。ただのレイマーチングといえばそれまでですが、工夫した点を書いていきましょう。

見えているものは全て基本的な図形(平面、箱、円柱、正八面体など)の組合せ(足したり引いたり)でシェーダーのプログラム内で定義されています。例えば街灯は円柱を3つ組み合わせ、真ん中のものを光るようにしています。左右の展示スペースは箱から円柱を引くことで穴を空けて作っています。

画像7

床、街灯、壁など基本的なものはループしていますが、扉とクリスタルは1点のみにしてループではない構造にしています。さらに疑似的なパーティクルをランダムに配置したり、光る部分の色を滑らかに変化させることでループ感を減らそうとしています。

テクスチャは三種類のレンガ画像とクリスタル用のMatCap画像のみ使っています。シェーダー内でTriPlanerというUV無しでテクスチャを貼るロジックを実装したりしました。

画像8

さらにdepthといってその物体がどれくらいの距離にあるかというのもシェーダー側で操作して書き込むことができます。今回は以下のように書き込むことで、壁や街灯にアバターが触れたときの前後関係をある程度正確にしました。
・描画されるものの位置が4×4に収まっているときは、その位置(触れられる)
・収まっていないときは4×4の壁の位置(ワープ判定ギリギリから思いっきり手を伸ばすとブースの本当の壁に触れることができるはずです)

実はこの辺にキューブとか置くとこうなります。

画像9

また展示物を表示するエリアに移動するまでは、そこに展示物が無いことを隠す必要があります。そのために近づくと消える円柱を置きました。3×3で区切ったスペースの中央に展示物があるという形です。

画像5

最大の敵は軽量化でした。レイマーチングの欠点はシェーダー内でループ処理が行われていて重いことです。軽量化には以下の対策が効果を発揮しました。
・発光物とそれ以外は完全にループを分け、別々に描画する
見た目にも処理負荷にも分けたほうが良さそうでした。
・クリスタルもループを分け個別に描画する
レイマーチングの特性上、遠くのものを描画するほど重くなります。しかし広さの表現のためにクリスタルは必須です。泣く泣く原案より形状を単純にしつつ、ループを分けるといくらか改善しました。

最後に周りをGrabPassという機能を用いた透明マントのようなシェーダーのマテリアルで囲って終わりです。扉だけ外から見えるように開けておきます。実はこれは建物のモデリングをしたくなくてサボった案なのですが、異質な感じで結果的には良かったかもしれません。原案では外から見るとモデリングした普通の建物があり、中に入ると広いというのを考えていました。

反省

正直重めの反省があります。迷子が出ることについてです。
これはただただ対策不足でした。一応範囲は制限しており、クリスタルの位置から最初にどちらに進んだか覚えていれば扉には辿り着けます。しかしVketほど多くの人が訪れるワールドで、来場者にリスポーンなどの悪い体験を与える可能性はもう少し丁寧に排除すべきでした。単純に範囲を狭める(扉が見える程度の範囲で)、矢印など言語に依存しない案内を出すなどの対策が有り得たと思います。次回があれば改善したいところです。

Vket開催後に自覚し、強めの批判が来るかなと身構えていたのですが今のところ来ていません。心配でVketワールド巡りみたいなインスタンスに入って観察したりしていたのですが、迷うというなかなか重大な課題があるにもかかわらず何故かブース自体は多くの人に好意的に受け止められていて不思議な気持ちでした。

出来たブース

・容量1.3MB(展示物を除くとおそらく1MB未満)
・大きさは4×4×3m程度
・SetPassCallは7くらい
・広さは無限に設定可能、一定の大きさに制限することも可能
・展示物の位置や大きさには一定の制限があるものの、容量が許す限りはいくつでも配置可能。展示物を切り替えた際のSetPassCallの増加は同時に基準値を超えなければOKらしい(Vket公式discordにて質問済み)

結果的にバーチャルマーケット in Vketみたいなギミックになりました。
今後、展示物が増えても特に気にすることなく全部配置できるのは良さそうです。Vketの規定が変わらなければ、ですが。(結局縛られている)

おわりに

人はなぜシェーダーを学ぶのか。多くはゲーム開発で必要だからだと思います。
しかし私や一部のVRChatプレイヤーにおいてはそれが「魔法を使えるようになるから」という凄まじくポジティブな動機になります。異世界転生したら何をしますか?私は絶対♰最強魔術師♰になりたいです。本当に魔法が使えるのなら、それがどれだけ難しくても、今の時点で全く知らないことでも、きっと取り組むと思います。その過程はきっと楽しいと思います。楽しいです。VRChatの楽しみ方は人の数だけあるような気がしますが、少なくとも私はそういった側面も楽しんでいます。VRChatは魔法を学べば魔法が使える世界なのです。

もし良かったらシェーダー触ってみませんか?私も教えられるほどわかっているなんて言えたものではありませんが、楽しいですよ。

この記事が気に入ったらサポートをしてみませんか?