Primer 03 でシェーダーが1ピクセルの色を計算するのを見ました。ではライトが100個ある夜景を、全部の面×全部のライトで計算したら? ── 破綻します。UE の既定デファードシェーディングは、いったん「素材の情報だけ」を画面に書き出し(G-Buffer)、そのあとで光をまとめて一度だけ計算します。その分業を、実際にチャンネルを分解して見ていきます。
素直なやり方(フォワード)は、面を描くたびにその面に当たる全ライトを計算します。分かりやすいけれど、面の数 × ライトの数で計算量が膨らみ、しかも奥の面を手前が上書きすると、その光の計算は丸ごと無駄になります。デファードは「まず見えている面の素材だけ確定させ、光はそのあと画面一回ぶんだけ」に変えて、この掛け算を足し算に近づけます。
デファードの中間画像=G-Bufferは、1枚の絵ではなく複数のチャンネルの束です。下のシーン(床+球3つ)を各チャンネルに切り替えてみてください。アルベド・法線・深度・粗さは、まだ光を当てていない材料です。「合成」を押すと、これらを使って光を1回計算した最終結果になります。
UEでは Viewmode → Buffer Visualization や Base Color / World Normal 表示で、これと同じチャンネルを実機で覗けます。バグ調査(法線が裏返る、粗さがおかしい等)は、まずこの分解表示で原因のチャンネルを特定するのが定石です。
G-Buffer が揃うと、各ライトは「自分が照らす画面の範囲」についてだけ、そこに既に書いてある素材情報を読んで光を足します。面の三角形を描き直す必要がないので、追加コストはおおむねライトが画面を覆う面積で決まります。小さな点光源を大量に置いても、それぞれが画面のごく一部しか触らなければ安い ── これがデファードの勝ち筋です。
半透明(ガラス・煙)が「奥の一枚」に畳めないのは、複数の面の色が重なって見えるから。だからデファードでも半透明だけはフォワードで別に描きます。「半透明が多いと重い」と言われる背景がこれです。
UEの1フレームは、ここで見た Base Pass / Lighting のほかに、シャドウ・SSAO・SSR・半透明・ポストと何十ものパスが積み重なっています。どのパスが重いかは実測でしか分かりません。下は最初に触るツールです。
Primer 01 で「レンダースレッドがGPUに命令を積む」と言いました。その命令列の正体が、この描画パスの連なりです。4本を通して、ゲームスレッド→レンダースレッド→GPU→テクスチャ→マテリアル→描画パス、と一周したことになります。