Memo of "Intersecting Lights with Pixels Reasoning about Forward and Deferred Rendering" SIGGRAPH 2012

Reference

Memo in Japanese

  • "Intersecting Lights with Pixels Reasoning about Forward and Deferred Rendering" SIGGRAPH 2012 のメモです.
  • 個人用メモなので, 内容はざっくりとしたものになっています.
ライトのカリングとは ?
  • 可視性は衝突判定の問題であり, 三角形と交差しているピクセルを求めるものです.
  • ラスタライズやレイキャストによって交差を求めることができます.

  • ライトのカリングも衝突判定の問題の一種で, ピクセルと交差しているライトを求めます.
  • 従って, 一般的な衝突判定のアルゴリズムを適用することができます.
  • 但し, カリングのコストの方がライトのコストよりも低くなければなりません.

  • ピクセルを何らかの衝突判定用のデータ構造に入れて, ライトも何らかの衝突判定用のデータ構造に入れて, これらを使って交差判定をすれば良いということになります.


(a) フォワードレンダリングでの古典的なライトカリング
  • オブジェクトのバウンディングボックスと, ライトボリュームの交差判定をします.
  • その結果を元に, オブジェクト単位でそれに適用するライトのリストを求めます.
  • しかし, この方法はあまり効率的なライトのカリング方法ではないです.
  • 理由はライト・オブジェクトが画面に対して近い場合には該当するピクセルの範囲が大きくなるので, もっと細かく(ピクセル単位)カリングすべきです.
  • 逆に, ライト・オブジェクトが画面に対して遠い時には該当するピクセルの範囲が小さくなるので, もっと粗くカリングするすべきです.

(b) ディファードパスでライトボリュームを塗るタイプ
  • G-Buffer を作ってから, ライトボリュームを描画してラスタライズされたライトのピクセルごとに G-Buffer の値を読み込んで, そのライティング結果をライトバッファに加算描画します.
  • この方法だと 1 ピクセルに複数のライトが影響している場合, ライトごとに G-Buffer を読み込んでから, ライティング計算をしてライトバッファに加算する形になるのであまり効率的ではないです.
  • 本当は 1 ピクセルごとの計算では 1 回だけ G-Buffer を読み込んで, そのピクセルに影響するライトごとのライティングを計算して, その合計値を 1 回だけライトバッファに書き込む方が効率的です.



(c) タイルベースのライトカリング
  • タイルベースのライトカリングでは, ピクセルを一様なグリッドとしてタイルに分割します.
  • 一方で, ライトの方は特に何もしないです.
  • そして, タイルごとにそのタイルと交差するライトのリストを求めます.

  • タイル・フォワードの場合, 「1. Z プリパスでのジオメトリのサブミット」,「 2. タイルベースのライトのカリング」, 「3. ジオメトリを再サブミットして該当するタイルのライトリストを使ってシェーディング」という流れになります.

  • タイル・ディファードの場合, 「1. G-Buffer 構築のためのジオメトリのサブミット」, 「2. タイルベースのライトのカリング」,「3. ピクセル単位で, それが該当するタイルのライトリスト・G-Buffer を読み込んでシェーディングしてライトバッファに書き込む」という流れになります.

  • 「タイル・フォワード」と「タイル・ディファード」の違いは初回のパスで書き込むもの(G-Buffer または ジオメトリを再サブミット)やシェーディングのスケジューリング(フォワードシェーディング/ディファードシェーディング)の違いです.

応用
  • 応用としてライトの方もデータ構造化する提案があり, 下図のようにライトを Quad-Tree 化したり, 3d のデータ構造にする方法があります.