【Unity】Shader Graphでインテリアマッピング

2018-09-23

ツイッターのタイムラインでなんかスパイダーマンのゲームがすごそうだと話題になってるなーと眺めている中で、大前さんのツイート

でインテリアマッピングというのを初めて知った。 面白そうなので試してみた。

先に結果画面

リポジトリ:https://github.com/tyfkda/InteriorMapping

![interiormapping](/assets/interiormapping.jpg)

ビルは単なる立方体をスケールした6面の箱で、シェーダーで内部に部屋があるように見せかけているところが面白い。

準備:Scriptable Render Pipelineの導入

Unityでシェーダー使う場合にGUIで簡単に扱えるような環境ないかな…と思ってググってみると、Shader Graphというのがあるらしい。 Unity2018以降で使えるというのでそれにしてみた。

Shader Graphを使うにはデフォルトのレンダリング方式ではなく、Scriptable Render Pipelineというものを使う必要がある。 high-definitionとlightweightの2種類があって、名前からしてhigh-definitionのほうがいいのかと思って最初そちらを入れたのだけど入れただけでエラーが吐かれてしまいうまく動かないので、lightweightを使うのがよさそう。 Core Libraryというのと合わせてインストールする。

パイプラインをAssets > Create > Rendering > Lightweight Pipeline Asset で作成、 それをEdit > Project Settings > GraphicsのScriptable Render Pipeline Settingsという項目に指定することで使えるようになる。

Shader Graph

Shader Graphもパッケージからインストールする。 Assets > Create > Shaderに「ほにゃらら Graph」という3項目が追加されるので、とりあえず「PBR Graph」でわけもわからず作ってみる。 (あとから考えるとインテリアマッピングではジオメトリの法線とは全く違う内容が必要なので、ライティングを行わない「Unlit」のほうがいいのではないかと思う)。

作成されたアセットをダブルクリックまたは「Open Shader Editor」でシェーダーグラフのエディタが開くので、ノードを作成したりつないでやったりして作っていく。 ノードベースのシェーダー作成は初体験だけど、結構直感的にそのまま使えてすごい。

しかし「PBR Master」や右下のプレビューに何も表示されない。 中間のノードやPreviewノードで見れるとはいえ、 いちいち「Save Asset」で保存してシーンで確認する必要があって不便だ。

作成したシェーダーグラフをマテリアルに指定して、それをメッシュレンダラに指定することで実際の画面に反映される。

Interior Mapping: 部屋の描画

Interior Mapping自体は2008年頃に発表されたものとのこと。 それまでゲームに出てくるビルというと窓枠が不透明で中が見えなかったがそれだと見栄えがよくないので中に部屋があるようにジオメトリを使わずにシェーダーで描画してやろう、という内容。

ビルの内部の部屋の描画は、部屋がXYZ軸に平行な固定のグリッドで部屋分けされているものとして、視線がXYZの各平面のどこにヒットするかをそれぞれ調べて一番近い点に対応する面のテクスチャを参照することで実現する。 視線方向がプラスとマイナスの方向があるのでそれらの場合分けも必要。

Shader Graphで実装する際には、以下のようなノードを組み合わせて作った:

やりたい内容 対応するノード
ベクトルを各要素に分解して参照 Split
判定 Comparison
条件分岐 Branch
座標系の変換 Transformation Matrix
ノイズの生成 Simple Noise

交点がグリッド内のどこに位置するかの計算にModuloを使おうとしたが負の場合に結果も負になってしまう?のかうまくいかないのでFractionで対処した。

![interiormapping](/assets/interiormapping_shadergraph.jpg)

頂点シェーダーとフラグメントシェーダーの差を全然意識しないんだけどどうなってるんだろう?

Interior Mapping: その他

論文では部屋の描画以外にもいくつか項目が書かれている:

  • 外壁のデカールや窓枠の反射
  • 内部に家具や人を平面として配置
  • 部屋の電気がついているか、また部屋のテクスチャをランダムに変える
  • 部屋のサイズを変える

このあたりは試してなくて、今後の課題ということで…。

Reference