ikoan unity 開発メモ

Unityに関するアレコレを日々つづっていこうと思います

【番外】レンダリング基礎

概要

Unityも大分高機能になり、もともとCommandBufferを使用してレンダーパイプラインに特殊効果を追加する、というものが、もはやレンダリングパイプラインを自分で書いてね!というレベルまで到達してしまった。
ちょっともうここら辺をスルーするわけにはいかなくなってきたので、基礎から学び始めようかと思います。

参考図書

普通に数学の勉強にもなるのでオススメです。
クオータニオンとか難しいです。
今回は「8.3 グラフィックスパイプライン」について、備忘録を兼ねてまとめていきたいと思っています。

ざっとした描画フロー

下記のようになる。

  1. CPUがドローコールを作成
  2. 頂点シェーダーの処理
  3. プリミティブアセンブリ
  4. ラスタライズ
  5. フラグメントシェーダの処理
  6. ROP処理
  7. フレームバッファへの書き出し

1. CPUがドローコールを作成
現在のシーンの状況(ポリゴンやマテリアルの情報)に対応したドローコールをCPUが描画前準備として作成する。
送るものは、頂点情報やUV情報、ある場合は法線情報や頂点カラー情報、接戦情報もそれに当たるでしょう。

2. 頂点シェーダーの処理
頂点シェーダーでは、CPUから渡された頂点の情報をもとに、ビュー空間、プロジェクション空間への変換を行います。ここら辺の説明は、参考資料の別章または他のサイトさんを参考にしていただければと思います。
また、各頂点の情報をここでいじったりもできます。例えばモデルの中心を基準に2倍に拡大したりなど。

3. プリミティブアセンブリ
頂点シェーダーの出力である頂点情報などをもとに、空間上にどのような図形があるかを構築します。
構築された図形群がカメラ内に収まっているかを判定し、収まっていないなら、その図形情報や頂点情報を捨てます。
図形はカメラ内だが一部頂点のみカメラ外の場合、カメラ表示空間に沿って新しく頂点が追加されるようです。
その後、このタイミングでカリングが行われることとなります。

4. ラスタライズ
ラスタライズとは先ほど作成されたプリミティブの情報をセル(四角)単位に落とし込むことです、
各セルには位置情報や色情報、UV情報や深度情報が、関連頂点から補間され、保持されることになります。

5. フラグメントシェーダの処理
先ほどラスタライズした、各セルに対して、プログラマブルな処理を行います。
ここで色情報を変換したり、色を表示しなかったり、などなど、多くのことが行えます。
その反面、各セルごとに処理が行われるため、解像度が高い端末に多くの描画情報があった場合、一気にここの負荷が高くなりますので要注意です。

6. ROP処理
5で処理した各フラグメント(セル)に対して、最終的な描画チェックを行います。
描画矩形内に収まっているのか、ステンシルチェック、デプスチェックなどのことです。
上記チェックを行い、実際に描画されると判断されたら、フレームバッファ内に存在している対応ピクセルの色とブレンディングが行われます。アルファ合成だったり、加算合成だったりですね。
また、OpenGL ES2.0ではこのタイミングでMSAA(マルチサンプリアンチエイリアシング)という、簡単にいうと表示を滑らかにする処理が行われます。ただ、この処理は解像度を数倍の大きさにしたバッファに一度書き出し、最終的にバッファに書き込むときに周囲数ピクセルブレンドする、という処理なので、滑らかにしようとすればするほどメモリを多く必要としますし、描画コストももちろん高くなります。

7.フレームバッファへの書き出し
フレームバッファとは、いわゆる画面に描画されるものそのもののことです。
このフレームバッファ内に保持されている情報がスクリーンに描画されることとなります。

まとめ

以上が実際にスクリーンにレンダリングされるまでの一連の流れとなります。
私自身、まだ全容を把握できていないので、間違いがあるかもしれません。その場合は指摘していただけると助かります。