遅延シェーディング ”Deferred Shading Tutotrial”の概要

遅延シェーディングのチュートリアルである"Deferred Shading Tutotrial"を復習したので, その概要について書かせていただきます.

複数のオブジェクト(objects)と複数の光源(lights)があり, そのシーンをZバッファ法でポリゴンを描画する場合, 以下のような描画ループになります.

  for object in objects:
     for light in lights:
        frame_buffer = draw(object, light);

この描画方法の問題点は, Zバッファを使った深度テストをパスするフラグメントは一部なのですが, 深度テストをパスしない隠れる面のシェーディングの計算まで行ってしまう点です.

そこで遅延シェーディングは1度だけシーンのオブジェクト(objects)の幾何情報をサブミットし, 照明計算に必要なピクセル単位の情報を複数のテクスチャとしてG-bufferに蓄積しておきます. 複数のLightによる照明計算については, そのLightの影響範囲の2Dの長方形を描画して, その範囲内にあるピクセルだけ照明計算を行います.

   // Create G-Buffer
   for object in objects:
     draw(object)
   
   for light in lights:
     light_rectangle_2d = getLightRectangle2d(light)
     frame_buffer += drawWithG_Buffer(light_rectangle_2d, G_Buffer)

遅延シェーディングは以下の4つのステージから構成されていますが, ここでは1と2だけ扱います.

1. G-Bufferの構築 (Depth Pass, Material Pass)
2. Lightingの計算 (Ambient Pass, Illumination Pass)
3. Post-Processing [省略]
4. FinalStage [省略]


1. G-Bufferの構築 (Depth Pass, Material Pass)

  1. 最初のDepth Passでは, デプスバッファの各ピクセルの最も手前にある面を先に決めてしまい, その後の深度テストをクリアしたフラグメントだけに対して複雑な計算を行うことにします (Early Z culling). 具体的にはカラーマスクを一時的に有効にして, 照明計算を行わずにシーン中のオブジェクトを描画します.
  2. 次のMaterial Passでは, 各ピクセルの照明計算に必要なピクセル単位の情報を4枚のテクスチャに格納した"G-Buffer"を構築します. 4枚のテクスチャの内訳は, 視点座標系の法線を格納するcolorテクスチャ, テクスチャカラーとマテリアルカラーを乗算したものを格納するdiffuseテクスチャ, マテリアルのspecular成分を格納するspecularテクスチャ, 深度情報を格納したdepthテクスチャです.

1パスで, 4枚のテクスチャから成るG-Bufferを構築するためには, Multiple Render Target(MRT)を使います. 各テクスチャをレンダリングターゲットとしてバインドしてから, フラグメントシェーダで大まかに以下のような感じでテクスチャに値を出力します.

  struct f2s_mrt
  {
    float3 color0 : COLOR0; // MRT colorテクスチャ
    float3 color1 : COLOR1; // MRT diffuseテクスチャ
    float3 color2 : COLOR2; // MRT specularテクスチャ
    float3 color3 : COLOR3; // MRT depthテクスチャ
  };

   // フラグメントシェーダ
   f2s_mrt mrt_normal(...)
   {
      f2s_mrt OUT;
      ...
      OUT.color0 = normal;
      OUT.color1 = texture_color * material_diffuse.xyz;
      OUT.color2 = material_specular;
      OUT.color3 = depth;
      ...
   }


2. Lightingの計算 (Ambient Pass, Illumination Pass)

  1. Ambient Passでは, Ambient colorを設定してG-Bufferのうちのcolorバッファをテクスチャとしてバインドしてから, 2Dのスクリーンサイズの長方形を描画します. この結果として環境光以外の光源の影響を受けていないオブジェクトのフラグメントが描画されます.
  2. Illumination Passでは, 各ライトのシーン中における影響範囲を2Dの長方形で表したものを求めて, 光源のパラメータの設定してからそれを描画し, フラグメントシェーダでG-Bufferを使った照明計算を行います.