Deferred Renderingの強み

## 概要
Deferred Renderingを詳しくしりたい
ついでにUnityでサンプルを作って負荷比較しました

## サンプル
とりあえず効果がわかりやすいケースでForwardとDeferredで比較します

| Forward Rendering | Deferred Rendering  |
|:-:|:-:|
| ![WorldProject_Daily5_ForwardRendering.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7680/567b65c0-e8f8-8f44-ccae-89af3a1244e1.png) | ![WorldProject_Daily5_DefferedRendering.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7680/47a9c34d-b366-6b5e-a0c3-af366fd89b4c.png) |

効果がない

それはそう。なぜならDeferred Renderingの強みを活かせてないから。
本命はこっち

| Forward Rendering | Deferred Rendering  |
|:-:|:-:|
| ![WorldProject_Nightly6_ForwardRendering.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7680/4e8f1683-8fda-0c8e-0a5c-d40961074989.png) | ![WorldProject_Nightly6_DeferredRendering.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7680/96c5119d-ea2d-ba11-0002-dde20b689546.png) |

SetPassがForwardだと10倍以上増えてるのに、Deferredだと2倍ぐらいしか増えてない！
FPSには露骨な差がでてます

違いはDirectional Lightに追加して街灯に2個ずつ計4個のPoint Lightを設置しただけ

Deferred Renderingは**複数の光源がある場合**に負荷を大きく減らすことができます
（限定的な影響範囲の光源が多く、かつ近くに複雑なメッシュがあるとより効果が大きい）


## 技術解説
一般的なレンダリングでは
スクリーン座標変換 → ラスタライズ → ライティング → レンダリング結果
が行われる

Deferred Renderingで高速になるのは「ライティング」の処理



### Forward Renderingのライティング

1. オブジェクトのバウンティングボックスを元に影響のあるライトを探索
1. オブジェクトの全ピクセルにライティング処理
1. スクリーンスペースに変換してレンダリング

これには計算の無駄が多い
・ライト範囲外のピクセルにも計算してる
・スクリーンスペースに変換すると描写されないピクセルも計算してる

### Deferred Renderingのライティング
ラスタライズ後に**ジオメトリ情報をG-Bufferにキャッシュ**
G-Bufferを元にライティングする考えがDeferred（遅延） Rendering

1. スクリーンスペース変換されたG-Bufferに位置・法線・色を書き込み
1. ライト範囲内のピクセルのみライティング計算
1. レンダリング

Forward Renderingと比べて効率的なのがわかる
しかもライトが多くライト範囲外のピクセルが多いほどキャッシュ利用頻度が高くなり効果が大きくなる

![解説.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7680/2ae0fd5d-76b7-1667-60e1-324424987a85.png)

## Deferred Renderingの苦手なこと
- 半透明のオブジェクトを処理できない
    - G-BufferにAlpha情報を保持できない。保持しようと思うとメモリが必要になる
    - 代わりにForward Renderringを使うのが一般的
- ライトの数には強いけど距離が長いのは苦手？
    - 苦手というか強みが薄れる。Directional LightのみならForward Renderingと大差ない
- Unityでは平行投影でのDeferred Renderingはサポートされてない
    - 理由不明
    - でも平行投影カメラで複数ライトが必要なケースが思いつかないしいいか

## 利用ケースの考察
・PBRでライティングが変わる想定でモデリング
・広めのマップ
・光源を複数おく
などのリッチな絵作りが必要なら試す価値がありそうです

夜の街を歩くマップなら効果が大きそう

## サポート端末
Deferred RenderingにはMRT（Multi-Render-Target）が必須となる
MRT（Multi-Render-Target）とは一度のレンダリングパスで複数バッファに異なる値を同時出力する機能。
これがないとG-Bufferで位置・法線・色をバッファに書き込めず、ライティングを効率化できない。

ほとんどの PC グラフィックスカードはディファードシェーディングをサポート
モバイル：最低 OpenGL ES 3.0 を実行するすべてのデバイスでサポート

## 参考文献
https://www.slideshare.net/SatoshiKodaira/ss-69311865

↑レンダリング基礎をわかりやすく教えてもらえる。おすすめ度◎

https://docs.unity3d.com/ja/2019.4/Manual/RenderTech-DeferredShading.html

↑Unity公式ドキュメント。Deferred Rendering自体はあまり説明してくれない。
あくまでUnityの実装について簡単に書いてるだけ

https://qiita.com/r-ngtm/items/a78ca2f72a36e2005da3

https://game.watch.impress.co.jp/docs/series/3dcg/125909.html

https://esprog.hatenablog.com/entry/2016/03/17/142939#:~:text=G%2DBuffer%E3%81%AF%E3%83%86%E3%82%AF%E3%82%B9%E3%83%81%E3%83%A3%E3%81%A8%E3%81%97%E3%81%A6,%E3%83%86%E3%82%AF%E3%82%B9%E3%83%81%E3%83%A3%E3%83%90%E3%83%83%E3%83%95%E3%82%A1%E3%81%AB%E6%9B%B8%E3%81%8D%E8%BE%BC%E3%81%BF%E3%81%BE%E3%81%99%E3%80%82

https://qiita.com/y_UM4/items/7647fd9fc19e60ec5822