【Unity】オクルージョンカリングを使って遮蔽されたオブジェクトをカリングして処理負荷を小さくする

Unityのオクルージョンカリング機能についてまとめました。

Unity2019.2.10

オクルージョンカリング?

いま、以下のようにカメラとオブジェクトA、Bが配置されているとします。

f:id:halya_11:20191101005448p:plain

ここで、オブジェクトBはオブジェクトAに隠れているのでカメラに映りません。
つまり、理論上は描画処理をスキップして処理負荷を減らすことができます。

f:id:halya_11:20191101005655p:plain

オクルージョンカリングを使うと、このように遮蔽されているオブジェクトを描画対象から外すことができます。

オクルージョンカリングを行うにはカリングのための情報を事前に用意しておく必要があります。
この記事ではその手順を紹介します。

ベイクする

それではオクルージョンカリングを行うための準備としてベイクを行っていきます。
まず、テスト用に以下のようなシーンを用意します。

f:id:halya_11:20191101010428p:plain

次にこれらのオブジェクトのInspectorから、Occluder StaticとOccludee Staticにチェックを入れます。
Occluderは他のオブジェクトを遮蔽するもの、Occludeeは他のオブジェクトから遮蔽されるものという意味です。

f:id:halya_11:20191101010518p:plain

次にWindow > Rendering > Occlusion Cullingから設定ウィンドウを開きます。
そしてBakeタブを選択します。

f:id:halya_11:20191101010810p:plain

次に、遮蔽物の最小値をSmallest Occluderに設定します。
ここに設定した値よりも小さいオブジェクトはOcculuder Staticだったとしても遮蔽物としてみなされません。
つまり、そのようなオブジェクトは他のオブジェクトを遮蔽しません。

f:id:halya_11:20191101011154p:plain

この値を小さくするとより遮蔽の精度は上がるものの、ベイク後のデータサイズが大きくなります。

次に、以下のようにオブジェクトとオブジェクトの隙間から向こう側を覗けるような配置を考えます。

f:id:halya_11:20191101011654p:plain

この隙間の大きさをSmallest Holeに入力すると、向こう側にあるオブジェクトがカリングされずに見えます。

f:id:halya_11:20191101011919p:plain

ただしこの値を小さくしすぎるとデータサイズが大きくなります。

Backface Thresholdは背面ポリゴンをデータに含めるかどうかの設定です。
両面描画など、背面を描画してそれが遮蔽に関わるようなケースでは100にしておくとよさそうです。
それ以外のケースでは値を小さくするほどデータ容量削減につながります。

f:id:halya_11:20191101012314p:plain

さてここまで設定が終わったらBakeボタンを押下します。
以下のように青いボックスが多数表示されれば準備完了です。

f:id:halya_11:20191101012512p:plain

これらはオクルージョンカリング用の空間データで、その容量はBakeタブの最下部に表示されます。

f:id:halya_11:20191101012602p:plain

カリングの挙動を確認する

それでは前節でベイクしたデータを使ったオクルージョンカリングの挙動を確認してみます。
まずOcculusion CullingウィンドウのVisualizationタブを表示します。

f:id:halya_11:20191101012834p:plain

そしてこの状態でシーンビューを表示しながらメインカメラを動かします。

f:id:halya_11:20191101013222g:plain

オクルージョンカリングが行われ、遮蔽されたオブジェクトが非表示になっている様子が確認できました。
ちなみにこの表示は、オクルージョンカリングだけでなくフラスタムカリングも適用された状態となっています。

StaticではないGameObjectをオクルージョン

さてここまでは遮蔽するオブジェクトも遮蔽されるオブジェクトもStaticなオブジェクトでした。
実は動的なオブジェクトも、静的なオブジェクトから遮蔽された場合にカリングすることができます。

設定としてはMesh RendererのDynamic Occlusionにチェックを入れるだけです。

f:id:halya_11:20191101013900p:plain

カメラが動きうる範囲にはOcclusion Areaを設定する

さて、今下図のようにオクルージョンのデータが作られているとします。

f:id:halya_11:20191101014201p:plain

ここで気を付けなければならないのは、カメラがこの範囲内から出るとオクルージョンカリングが効かなくなってしまうという点です。

f:id:halya_11:20191101014234g:plain

しかしこれでは遠くから映したいときにカリングがされず処理負荷が大きくなってしまいます。
このようなケースでは、まず空のGameObjectを生成し、Occulusion Areaをアタッチします。

f:id:halya_11:20191101014438p:plain

Is View Volumeにチェックを付け、ベイクされていないがカメラが動きうる範囲にSizeとCenterを設定します。

f:id:halya_11:20191101014555p:plain

そしてこの状態で再びベイクします。

f:id:halya_11:20191101014619p:plain

するとカメラを移動してもしっかりカリングが効いていることが確認できました。

f:id:halya_11:20191101014750g:plain

参考

docs.unity3d.com