【VRChat】オクリュージョンカリングでワールドの描画負荷を下げる

# 概要
ここでは描画負荷を下げるための手法の一つである**「オクリュージョンカリング」**について解説します。VRChatのワールド制作向けに書いてはいますが、VRChat以外でも使用できる手法です。
あくまでも「ワールドの**描画負荷を下げる**手法」であって、「ワールドの**容量を減らす**手法」ではないのでそこだけは注意してください。

## 環境
・Unity2018.4.20f1を使用
・VRCSDK2-2020.11.16.12.43_Publicを使用

※Unity側の機能しか使用していないので、VRCSDKのバージョン・種類に関わらず実装できるはずです。

# オクリュージョンカリングとは
**あるオブジェクトが他のオブジェクトに隠されてカメラに映らないときに、隠れているオブジェクトのレンダリングを無効にする機能**です。
「壁の後ろにあるものはどうせ見えないんだから、描画しないで処理を軽くしちゃおー」って感じ。
ただし、なんでもかんでもオクリュージョンカリングを適応してしまうと、逆にオクリュージョンカリングの処理で重くなり、本末転倒になってしまうので適切に設定しましょう。

# 1. オクリュージョンカリングについて
## 1-1. 前準備
### カメラの設定
カメラの`Occlusion Culling`にチェックが入っているか確認しましょう。デフォルトで入っているので恐らく大丈夫なはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1303641/020952ff-bcee-87ae-d94a-e69ec64e1ba8.png)

### オクリュージョンカリングを行うウィンドウ
`Window` → `Rendering` → `Occulusion Culling` でオクリュージョンカリングの設定を行うウィンドウを出すことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1303641/aa909353-f06d-af56-a413-65b69b39a4c7.png)

## 1-2. オクリュージョンカリングの設定について
まず初めに遮蔽物となるオブジェクトと遮蔽物に隠れると描画されなくなるオブジェクトの設定をそれぞれ行います。
設定は各オブジェクトの`Inspector`の右上の`Static`設定で行います。
その中の**`Occluder Static`**と**`Occludee Static`**の2つがオクリュージョンカリングの設定に関わってきます。
それぞれチェックマークを入れることで、そのオブジェクトにオクリュージョンカリングを適用できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1303641/dbdd6daf-fd50-a468-aab5-a07cbda87fc6.png)

両方とも似たような名前で分かりにくいと思うのでそれぞれ説明していきます。

| 名称 | 説明 |
|:--|:--|
|Occluder Static   |他のオブジェクトを遮蔽するオブジェクト。**「隠す方」**   |
|Occludee Static   |他のオブジェクトから遮蔽されるオブジェクト。**「隠される方」**   |

## 1-3. どんなものに設定するのか
基本的には、静的オブジェクト（動かないオブジェクト）にしか設定しません。
以下に、どの対象物にどのように設定するのがオススメなのかまとめます。

| 設定対象 | 設定するもの |
|:--|:--|
|動的オブジェクト（PickUpできるもの等）|共に設定しない  |
|家の壁や塀   |Occluder Static・Occludee Staticともに設定する。|
|家具や小物類   |Occludee Staticのみを設定する。|

# 2. オクリュージョンカリングを実践する
## 2-1. ベイク
以上のことを元にオブジェクトに`Occluder Static`と`Occludee Static`の設定を行いましょう。地道にﾎﾟﾁﾎﾟﾁと。
設定が終わったら早速オクリュージョンカリングを適用させていきます。
`Occulusion`のウィンドウを開き、右下にある`Bake`を押しましょう。ワールド規模にもよりますが遅くても5～10秒ほどでベイクが完了します。データ容量自体は多くても50KB辺りになると思います。
せっかく設定してもベイクをしないと意味がないので忘れないようにしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1303641/0009bd46-af63-4cc9-be2b-d639da9ea33a.png)

:::note warn
オクリュージョンカリングを設定したオブジェクトを移動させるなどした場合は、そのたびに再度Bakeし直しましょう。
そうしないと、視界内のオブジェクトがﾁﾗﾁﾗと消えたり現れたりする原因となります。
:::

## 2-2. それぞれのタブの説明
`Occulusion`のウィンドウにそれぞれ`Object`・`Bake`・`Visualization`の3つのタブがあると思います。それぞれ説明していきます。
### `Objectタブ`
選択中のオブジェクトのOccluder Staticと・Occludee Staticを行う場所です。
先ほど説明したInspectorのStatic設定と同様のことが行えます。

### `Bakeタブ`
オクリュージョンカリングのBake設定を行う場所。
以下、説明。

| 名称 | 説明 |
|:--|:--|
|Smallest Occluder|この値よりも大きいオブジェクトが遮蔽物(Occluder)として見なされる。  |
|Smallest Hole   |この値よりも小さな隙間は視線を通さないと見なされ、奥にあるオブジェクトは遮蔽される。|
|Backface Threshold   |値を100未満に設定するとオブジェクトの見えない裏側のメッシュの描画を省略して、データを小さくする。|


### `Visualizationタブ`
シーンでオクリュージョンカリングの状態を確認する場所。
このタブを選択した状態でカメラを動かしてみると……

（赤色が遮蔽物 / 青色が遮蔽されるオブジェクト）
![Videotogif (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1303641/2d02a6a1-c78c-f488-f876-9b0c7755ec84.gif)

ただし、カメラがこの青いセルの範囲外にでるとオクリュージョンカリングが効かなくってしまいます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1303641/8488507c-9637-4813-e204-215f35db370f.png"width=70%>

そういうときには**Occulusion Area**というものを使います。

## 2-3. Occulusion Area
まず、`Create` → `CreateEmpty` で空のオブジェクトを作成し、`AddComponent`から`Occulusion Area`を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1303641/ae94cd56-13dd-052d-54bc-ada6345fcc9b.png)

そして範囲を設定します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1303641/c8809d84-6cfd-1693-a502-f4c57ab7998e.png"width=70%>

この状態のまま再びベイク。すると…
先ほどは範囲外だった遠い位置からでもオクリュージョンカリングが効いてることが分かるかと思います。(分かりづらいけれど)
![Videotogif (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1303641/95cfd080-a7a1-8836-0f39-c28c8d12eb75.gif)

説明は以上となります。

# 参考記事
・[UnityDocumention オクリュージョンカリング](https://docs.unity3d.com/ja/2018.4/Manual/OcclusionCulling.html)