1. 序論:リアルタイムレンダリングにおける計算ボトルネックの変遷
リアルタイム3Dグラフィックスの歴史は、ハードウェアの物理的制約と描画アルゴリズムの最適化の歴史そのものです。初期のプログラマブルシェーダー時代(DirectX 9世代)における最大のボトルネックは「ピクセルシェーダーの命令数(ALU負荷)」でしたが、解像度の向上(4K/8K)、膨大な動的光源、そして数千万〜数億ポリゴンに及ぶ高精細アセットをリアルタイム処理する現代のゲームエンジンでは、課題は「メモリ帯域幅(Bandwidth)」「ジオメトリ処理の固定機能オーバーヘッド」「CPU側のドローコール発行コスト」へと移行しました。
本稿では、シェーディングパイプライン(ForwardからDeferred、そしてForward+ / Clusteredへ)とジオメトリパイプライン(固定頂点パイプラインからメッシュシェーダー、GPU Driven Renderingへ)の進化の系譜を数理的・構造的観点から包括的に解説します。
2. シェーディングパイプラインのアーキテクチャ比較と進化
2.1. 伝統的Forward Renderingの原理と限界
Forward Renderingでは、シーン内の各ジオメトリを描画する際、頂点変換に続いて即座にピクセルシェーダーで影響を受けるすべての光源のライティング計算(BRDF評価)を行います。
・計算量:オブジェクト数を O、光源数を L とした場合、最悪計算量は O(O × L) に達します。
・長所:半透明オブジェクト(Alpha Blending)の描画が自然に行え、ハードウェアMSAA(Multi-Sample Anti-Aliasing)がそのまま利用可能。マテリアルごとに異なる複雑なシェーダーを自由に適用可能。
・短所:オクルージョン(手前の物体に遮蔽されて最終的に見えなくなるピクセル)によって上書きされる無駄なライティング計算(オーバードロー:Overdraw)が大量に発生し、多数の動的光源を扱うことが構造的に困難。
2.2. Deferred Shading(遅延レンダリング)の革命とトレードオフ
Deferred Shadingは、ジオメトリ処理とライティング処理を完全に2つのパスに分離します。
・Geometry Pass:オブジェクトを描画し、ライティングを行わずにサーフェス情報(World Normal, Albedo/Roughness/Metallic, Depth, Specularなど)を複数のテクスチャバッファ(G-Buffer: Geometry Buffer)に書き出します。
・Lighting Pass:G-Bufferを読み込み、画面空間(Screen Space)の各ピクセルに対してのみライティングを計算します。
・計算量:画面解像度のピクセル数を P とすると、計算量は O(O + P × L) となり、光源数に対する依存性が大幅に緩和されます。
・トレードオフ:G-Bufferの多重読み書きによるメモリ帯域幅(Bandwidth)の激しい消費、半透明描画が原則不可(Forwardパスを別途併用する必要がある)、MSAAの適用が極めて困難、マテリアル種別がG-Bufferのチャンネル数に制約される(Uber-Shader化の必要性)。
2.3. Forward+(Tiled Forward)とClustered Shading
現代のゲームエンジン(Unreal Engine, Unity, 各種内製エンジン)で主流となったのが、Forwardの柔軟性とDeferredの光源処理能力を融合させたアプローチです。
・Forward+(Tiled Forward):画面を例えば 16×16 ピクセルの2Dタイルに細分化。深度プリパス(Depth Pre-pass)後に、Compute Shaderで各タイルの視錐台(Tile Frustum)と各点光源/スポットライトのバウンディングボリュームの交差判定を一括実行。タイルごとに影響を与える「光源インデックスリスト」を作成し、その後のForwardパスで該当タイルの光源のみをループ評価します。
・Clustered Shading:Forward+をさらに3次元(XYのタイルに加え、Z軸方向も対数スケールでスライスした3Dボクセル状の「クラスター」)に拡張した手法。奥行き方向の光源カリングが極めて高精度に行えるため、複雑な深度差を持つ屋内シーンやオープンワールドでも数千個の動的光源を安定したフレームレートで処理できます。
3. ジオメトリパイプラインの刷新:Mesh ShaderとTask Shader
3.1. 従来の頂点パイプラインのボトルネック
Direct3D 11以前の伝統的パイプライン(Input Assembler → Vertex Shader → Hull Shader → Tessellator → Domain Shader → Geometry Shader → Rasterizer)は、頂点インデックスのフェッチや三角形の組み立てがGPU内の固定機能ハードウェア(Fixed-Function Units)に強く依存していました。プリミティブの動的な生成・カリングの自由度が低く、高密度ジオメトリを扱う際の並列実行効率(Wavefront / Warpの稼働率)が低下する課題がありました。
3.2. メッシュシェーダー(Mesh Shader / Task Shader)の仕組み
DirectX 12 UltimateおよびVulkan 1.3で標準化されたMesh Shaderパイプラインは、ジオメトリ処理をCompute Shaderと同様の「スレッドグループ協調モデル」に完全再設計したものです。
・Meshlet(メッシュレット):巨大な3Dメッシュを、オフラインまたはエンジンロード時に「最大64頂点 / 126プリミティブ」程度の小さな独立した塊(Meshlet)に細分化してパッケージングします。
・Task Shader(Amplification Shader):Meshlet単位のバウンディングボックス/コーンを評価し、視錐台カリング(Frustum Culling)、オクルージョンカリング(Occlusion Culling)、背面カリング(Back-face Cone Culling)、LOD判定をCompute並列で実行。可視と判定されたMeshletのみを後続のMesh Shaderへ向けてディスパッチ(増幅/破棄)します。
・Mesh Shader:Task Shaderから渡されたMeshletの頂点とインデックスをスレッドグループ内の共有メモリ(LDS)を用いて協調計算し、ラスタライザへ直接プリミティブを出力します。
これにより、不要なジオメトリがパイプラインの最上流で高速に間引かれ、数億ポリゴン規模のジオメトリ処理が極限まで効率化されます(Epic GamesのNanite技術もこの概念を極限まで推し進めたものです)。
4. GPU Driven Rendering:CPUオーバーヘッドの完全排除
4.1. 伝統的レンダリングループの課題
従来のパイプラインでは、CPUがシーン内のシーングラフを巡回し、錐台判定を行い、マテリアルごとにステートを変更して DrawIndexed() などのドローコールを毎フレーム数千〜数万回GPUに送信していました。このCPU-GPU間の同期とドライバオーバーヘッドが、描画オブジェクト数の上限を決定づけていました。
4.2. GPU Drivenパイプラインのアーキテクチャ
GPU Driven Renderingでは、シーンの全オブジェクトデータ(トランスフォーム行列、バウンディングボックス、マテリアルID、LOD情報など)をGPU側のグローバルストレージ(Structured Buffer / ByteAddressBuffer)に常駐させます。
1. GPU Culling Pass:Compute Shaderが全インスタンスに対して並列に、前フレームの深度バッファから構築した階層的Zバッファ(Hi-Z Buffer: Hierarchical-Z)を用いたオクルージョン判定および視錐台判定を実行。
2. Indirect Argument Generation:可視と判定されたオブジェクトの描画引数(Draw Parameters)を、GPUメモリ上の Indirect Draw Buffer に直接書き込み。
3. MultiDrawIndirect / ExecuteIndirect:CPUは単一の DrawIndexedInstancedIndirect() コマンドを発行するのみで、GPU自身が生成したコマンドリストに基づいて全描画を一括実行。
これにより、シーン内に数十万個のインスタンスが存在しても、CPU負荷をほぼゼロ(1ms未満)に抑え込むことが可能となります。
5. 総括と今後の展望
リアルタイムグラフィックスは、ハードウェアの進化に伴い「CPUが指示を出しGPUが受動的に描画するモデル」から「シーン全体をデータ構造としてGPUに配置し、GPUが自律的にカリング・LOD選択・シェーディングを完結させるデータ指向モデル」へと完全に移行しました。Forward+/Clusteredによる柔軟な多光源処理と、Mesh ShaderおよびGPU Driven Renderingによるジオメトリ処理の組み合わせは、次世代のゲームエンジンにおける基盤アーキテクチャとして不可欠な知識となっています。
コメント (0)