【Unity】レンダリング／カリング／ライティングについてまとめてみた

# Unity で画面がレンダリングされる仕組み

### 1. 描画するオブジェクトの判別

- CPUがシーン内全てののオブジェクトをチェック
    - レンダリングするべきか判別する
    - オブジェクトのバウンディングボックスの一部がカメラの視錐台内になることが必要
- レンダリングされないオブジェクトは**カリング**という

### 2. ドローコール

- CPUはレンダリングされる全てのオブジェクト情報を収集
  - 収集したデータ（オブジェクト1つ1つに対して）は**ドローコール**と呼ばれる命令に分ける
- ドローコールには単一メッシュに関するデータと、そのメッシュがどのようにレンダリングされるべき（どのメッシュを使うか）かの情報が含まれている

### 3. バッチを作成

- CPUはドローコールごとに**バッチ**と呼ばれるデータのパケットを作成
  - バッチを作成する処理のことを**バッチング**と呼ぶ


### 4. ドローコールを送信
- CPUはドローコールを含む全てのバッチに対してGPUにドローコールを送信
    - レンダリング環境に変更がかかる場合のみ**セットパスコール**というコマンドが呼ばれる
- GPUがセットパスコールを受け取ったらレンダリング環境を更新
- GPUがドローコールを受け取ったらバッチを元にオブジェクトを描画し始める

### 5. 描画する

- GPUのタスクがセットパスコールならば、レンダリング環境を更新
- GPUのタスクがドローコールならば、メッシュをレンダリングする
  - 頂点シェーダーがGPUにメッシュの頂点を処理する方法を決定
  - 頂点が決まったらフラグメントシェーダーがGPUに1ピクセルごとの描画方法を決定
- CPUから送られたすべてのドローコールが処理されたらレンダリング完了

# カリングについて

## 視錐台カリング（フラスタムカリング）

- 常に自動で行われる機能
- カメラの視錐台の中に入っているものは描画、入っていないものは描画しないというもの
- `Near clipping plane` と `Far clipping plane` の間を結ぶ台形が視錐台と呼ばれる部分のこと

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233011/283d5f28-8ee0-9fc0-8f55-bd971c48a052.png)
[視錐台を理解する - Unity公式](https://docs.unity3d.com/ja/current/Manual/UnderstandingFrustum.html) の画像

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

- あるオブジェクトが他のオブジェクトに隠されていて現在カメラに映らないときに、オブジェクトのレンダリングを無効にする機能
  - GPUの負荷は軽減できるが、遮蔽判定をするためCPUの負荷は増加
  - 遮蔽判定を負荷が⼤きすぎるため、
「セル」と呼ばれる⽴⽅体の範囲単位で事前に遮蔽判定の
計算をしておく

##### オクルージョンカリングの使い方は参考文献を見ると分かりやすいと思います。

# Unity のライティング

- オブジェクトのシェーディングを計算するためには、そのオブジェクトに当たる光の強度、方向、色の情報が必要

## ライティングの種類

- 「リアルタイム」なものと「事前計算」によるものがある
- どれを使うかは、使用するプロジェクトと対象のプラットフォームによって異なる

## リアルタイムレンダリング

- シーン内のオブジェクトをライティングする最も基本的な方法
    - キャラクターなどの動くジオメトリを照らすのに向いている
    - Unityのリアルタイムライトは反射しない

## ライトマップのベイク

- 静的で複雑なライティング効果を計算可能
    - 計算結果はライトマップと呼ばれる参照テクスチャマップに保存
    - この計算プロセスを**ベイク（焼き付け）**という
- サーフェスを直に照らす直接光と、シーン内にある他のオブジェクトから跳ね返ってくる間接光のどちらも含めることが可能
- ゲーム中にライトを自由に動かせなくなる代わりに、モバイル端末のような非力なハードウェアでもパフォーマンスを出せる

## 事前計算されたリアルタイムグローバルイルミネーション

- シーンの複雑なライティングをインタラクティブに更新する方法
    - 間接光によるグローバルイルミネーションを使ってライティングされた環境を生成しつつ、リアルタイムでライティングの変更が可能
    - 時刻によって光源の色と位置が変化するのを表現するのが良い例

# レイヤー

- スプライトやUIの重ね合わせを制御する技術
    - スプライトを表示する順番は Sorting Layer を使って制御
    - UIの場合は Hierarchy で上に表示されているものが画面奥、下に表示されているものは画面手前に表示
        - Hierarchy で表示順と異なる順番で表示したい場合は、 Canvas で順番を設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233011/0b4d0c11-c2e6-fe08-996d-161902653357.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233011/5e5612ec-0cdf-b550-4c26-b643e18909fd.png)
- 特定のゲームオブジェクトのみ表示したりできる
- グループ単位でゲームオブジェクトを分けたりできる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233011/657e35a3-026b-150e-e437-013db9de9a1b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233011/25bba3ec-0ff5-a525-330f-3acc0c50ca63.png)


# 参考文献

https://techblog.gracetory.co.jp/entry/2020/06/18/132219

https://learn.unity.com/tutorial/fixing-performance-problems#5c7f8528edbc2a002053b596

https://docs.unity3d.com/ja/2018.4/Manual/OcclusionCulling.html

https://monolizm.com/sab/pdf/%E7%AC%AC50%E5%9B%9E_%E3%83%97%E3%83%AC%E3%82%BC%E3%83%B3%E8%B3%87%E6%96%99(%E3%80%9C%E3%82%AA%E3%82%AF%E3%83%AB%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%AB%E3%83%AA%E3%83%B3%E3%82%B0%E3%82%92%E8%A9%A6%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B%E3%80%9C).pdf

https://docs.unity3d.com/ja/2018.4/Manual/LightingInUnity.html