今回は、HLSLシェーダーの魔導書について学習の記録を残していきます。
CPUとGPU
CPUはキャラクターの移動や音楽の再生など、ゲーム進行に必要な処理を行います。
GPUはCPUからの指示を受けて画面描画を行う。描画は高速で行う必要があるため、多数のコアを扱います。
コア
コアはデータを処理する演算・制御を行います。
-
CPUのコア
- 高速かつ複雑な処理が可能です。
- しかし大量に搭載することはできないため、大規模処理には不向きです。
-
GPUのコア
- 構造はシンプルで処理速度は遅めです。
- 大量に搭載できるため、並列処理で大量の計算を処理できます。
3Dモデルを表示するために
3Dモデルを描画するには、大量の単純な計算が必要になります。
Vector4 convertedVertex[1000000];
for(int vertexNo=0; vertexNo<1000000; vertexNo++)
{
convertedVertex[vertexNo] = worldMatrix * vertex[vertexNo];
convertedVertex[vertexNo] = viewMatrix * convertedVertex[vertexNo];
convertedVertex[vertexNo] = projectMatrix * convertedVertex[vertexNo];
}
このように大量の計算をCPU一つで行うのは大変です。
大量のコアを持つGPUに任せることで、高速に処理できるようになります。
メインメモリとグラフィックスメモリ
-
メインメモリ(CPU側)
ゲームキャラクターの体力・攻撃力・守備力などの制御データを記憶する。 -
グラフィックスメモリ(GPU側)
3Dモデルの頂点データやテクスチャデータを記憶する。
メモリ転送
GPUが直接アクセスできるのはグラフィックスメモリのみです。
そのためCPUはDMAコントローラーなどを用いて、メインメモリのデータをグラフィックスメモリにコピーをすることでデータを渡すことが出来ます。
例:
- 3Dモデルの頂点データ
- テクスチャ
これらは一旦メインメモリにロードされ、GPU用にコピーされます。
なぜメモリが分かれているのか?
-
メインメモリ
汎用性が高く、ゲーム以外にも利用される → 複雑な要件が求められます。 -
グラフィックスメモリ
グラフィックス専用 → 大量のデータ転送を高速で行えるよう特化しています。
この要件の違いにより、メモリは分かれています。
ユニファイドメモリアーキテクチャ
CPUとGPUのメモリが分かれていると、プログラムは複雑になり可読性が下がります。
これを解決する仕組みが ユニファイドメモリアーキテクチャです。
これに関しては別の記事で調べようと思います。
絵が表示されるまでの仕組み
- CPUがGPUに対して DrawCall を発行します。
- 頂点情報やテクスチャ情報を渡します。
- GPUが描画を開始をします。
レンダリングパイプライン
CPUがDrawCallを行うと、GPUは決められた手順で描画を進める。
これを レンダリングパイプライン という。
最小限のレンダリングパイプライン
-
入力アセンブラー
VRAMから頂点バッファー、インデックスバッファーを取得 -
頂点シェーダー
頂点データをスクリーン空間に変換 -
ラスタライズ
描画範囲を判定し、ピクセルを決定 -
ピクセルシェーダー
ピクセルのカラーを決定
👉 頂点シェーダーやピクセルシェーダーは プログラマブルステージ(自由にプログラム可能)。
👉 入力アセンブラーやラスタライズは 固定機能ステージ(あらかじめ決まった処理のみ)。
各ステージの詳細
◇ 入力アセンブラー
CPUからのドローコールを受け、最初に処理するステージ。
頂点バッファーやインデックスバッファーをVRAMから取得し、GPUのレジスタへ渡す。
※レジスタは超高速にアクセス可能なメモリ。
◇頂点シェーダー
プログラマブルステージ。
主に「3Dモデルをスクリーン空間に変換する処理」を実装する。
例:
CEDEC2025のカプコン講演では、花を咲かせる表現を頂点シェーダーで実装していた。
◇ラスタライズ
ポリゴンが画面上のどの画素に描画されるかを決定。
固定機能ステージだが、塗りつぶし方法やカリング設定が可能。
◇ピクセルシェーダー
ラスタライズで決定されたピクセルに対して、最終的なカラーを決定する。
グラフィックスアルゴリズムの中核であり、シェーダープログラムの花形。
まとめ
今回は 『HLSLシェーダーの魔導書』第1章 をまとめた。
ここで登場した概念はレンダリングの基礎であり、今後の学習でも重要になります。