おもちゃバコ

中身スカスカ♡

「DirectX12の魔導書」を読んだ

こんにちは

「DirectX12の魔導書」を読んだ備忘録,感想,レビュー的なのです.

2年前に買って何回か読んで放置していたのですが,今なら理解できると思ってリベンジしました.

あと,積み本消化も兼ねて。

Amazon



類似書籍

DirectX12を勉強する際に以下の書籍も読みました.

技術同人誌です.
初心者でも分かりやすく解説されており,お値段も安いのでおススメです.
slash-labo.booth.pm

DirectX12というよりシェーダに特化した内容の書籍です.
エンジンコードにDirectX12が使用されているので参考になるかも.

洋書です.
英語が読めるならば一番良い書籍です.
(自分は何となくしかわかりませんでした.)

対象

  • DirectX12を触りたいけど何すればいいかわからない人。
  • DirectXについて知りたい人。
  • グラフィックエンジンを開発したい人。

忖度なく書きますが,本書は間違いが多いので丸写しでは動作しないと思った方が良いです。

お値段も高いので類似書籍が出ている現在(20220718)では少し微妙かも。。。
ただ,エフェクトやモデル読み込み回りも解説されているので,DirectX12を学ぶついでにその辺も勉強したい人はオススメ。

人を選ぶ内容だと感じたので,気になった人は書店で雰囲気を見てから購入するのを進めます。


メモ

メモは読みながら記述したものなので,清書はされておらず勘違いが含まれるかもしれないので注意.
実行結果はサンプルをちょっと変えたもの。

スペック

・Windows10 21H1
Intel Core i7-10700 2.90GHz
・RAM 16.0GB
NVIDIA GeForce GTX 1660 SUPER
・Direct3D12 12_1
Visual Studio 2019

Chapter 1 前提となる知識とDirectX12の概略

数学やレンダリングの基礎解説が主で,DirectX12の実装は次の章から.
DirectXの歴史が筆者の感想を交えて解説されていて面白い.

DirectX12の要素簡易まとめ
ディスクリプタ
 GPUに送信したデータをシェーダで使用するための仕様書.
ディスクリプタヒープ
 ディスクリプタ置き場.
ディスクリプタテーブル
 ディスクリプタヒープとシェーダのレジスタを関連付けるテーブル.
・ルートシグネチャ
 ディスクリプタテーブルをまとめる.
・パイプラインステート
 表示までの流れ.
・コマンドリスト/コマンドキュー
 字面通り.
・フェンス
 画面フリップを描画コマンドが完了するまで待つ仕組み.
・バリア
 コマンドを投げた時,リソースが何用途で使用されるか設定するもの.

Chapter 2 グラフィックスパイプラインとさまざまなシェーダー

グラフィックスパイプラインやHLSLについて。

・グラフィックスパイプラインの各ステージ
1. IA -> VS -> RS -> PS -> 出力
2. IA -> VS -> GS -> RS -> PS -> 出力
3. IA -> VS -> HS -> TS -> DS -> RS -> PS -> 出力
4. IA -> VS -> HS -> TS -> DS 0> GS -> RS -> PS -> 出力
の大体4パターン。

・セマンティクス
パイプラインに流すデータの使用目的をシステムに通知するもの。
しぇーだからは型や定数に見える(POSITIONやTEXCOORDとか)。

・レンダーターゲット
描画先。

Chapter 3 初期化から画面クリアまで

いよいよDirectX12のプログラムを書き始める。
git clone https://github.com/boxerprogrammer/directx12_samples.git
でサンプルコードは取得できるはず。

サンプルを動かしたいだけの人はDx12BookSamples.slnを開いて,Chapterに合わせてターゲットを右クリックで変更すれば良い。
実践派なのでメモはほどほどに,ここからは結果だけ。

出力は出来たけど,プログラム終了時にコンソール出力にWARNINGが出てた。

D3D12 WARNING: Process is terminating. Using simple reporting. Please call ReportLiveObjects() at runtime for standard reporting. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Producer at 0x000001D2E97825A8, Refcount: 15. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2EB9594F0, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2EB978C60, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2EB97E5B0, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2EB75B480, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2EB88AC60, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2EB754190, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2EB7543E0, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F220D670, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F223F930, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F2241E50, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F22AD310, Refcount: 7. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F2402D00, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F245B910, Refcount: 2. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F2352330, Refcount: 2. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F245E210, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F245E460, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F245E970, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F24ADDF0, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F24B4770, Refcount: 2. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F24B44C0, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F24B5720, Refcount: 2. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F24B5470, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F24BC440, Refcount: 2. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F227C970, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F24C06A0, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F2548FB0, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2F24E50B0, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING:  Live Object at 0x000001D2EB680100, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live                         Object :     28 [ STATE_CREATION WARNING #0: UNKNOWN]
DXGI WARNING: Live Producer at 0x000001D2E971AD68, Refcount: 8. [ STATE_CREATION WARNING #0: ]
DXGI WARNING:   Live Object at 0x000001D2E971D400, Refcount: 1. [ STATE_CREATION WARNING #0: ]
DXGI WARNING:   Live Object at 0x000001D2E97209C0, Refcount: 1. [ STATE_CREATION WARNING #0: ]
DXGI WARNING:   Live Object at 0x000001D2F245C800, Refcount: 1. [ STATE_CREATION WARNING #0: ]
DXGI WARNING:   Live Object at 0x000001D2F24B0DE0, Refcount: 1. [ STATE_CREATION WARNING #0: ]
DXGI WARNING:   Live Object at 0x000001D2F24B1270, Refcount: 1. [ STATE_CREATION WARNING #0: ]
DXGI WARNING: Live                         Object :      5 [ STATE_CREATION WARNING #0: ]

おそらくメモリ解放忘れ。
自分はComPtrでメモリ解放をシステムに任せたら出なくなった。

気になる人はエラーログの通りReportLiveObjects()を呼べば詳細が見れると思う。↓
多分1つ1つRelease()してけば直ると思う。

D3D12 WARNING: Live ID3D12Device at 0x00000288EF0E6C58, Refcount: 15 [ STATE_CREATION WARNING #274: LIVE_DEVICE]
D3D12 WARNING:  Live ID3D12RootSignature at 0x00000288EF11E890, Refcount: 0, IntRef: 2 [ STATE_CREATION WARNING #577: LIVE_ROOTSIGNATURE]
D3D12 WARNING:  Live ID3D12PipelineState at 0x00000288F11A8FD0, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #572: LIVE_PIPELINESTATE]
D3D12 WARNING:  Live ID3D12PipelineState at 0x00000288F13FE130, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #572: LIVE_PIPELINESTATE]
D3D12 WARNING:  Live ID3D12Resource at 0x00000288F13092D0, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING:  Live ID3D12Heap at 0x00000288F1309020, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #579: LIVE_HEAP]
D3D12 WARNING:  Live ID3D12Fence at 0x00000288F11C75A0, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #580: LIVE_MONITOREDFENCE]
D3D12 WARNING:  Live ID3D12CommandQueue at 0x00000288F11C77F0, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #570: LIVE_COMMANDQUEUE]
D3D12 WARNING:  Live ID3D12Fence at 0x00000288F7C9BF50, Name: Internal D3D12 Debug Fence, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #580: LIVE_MONITOREDFENCE]
D3D12 WARNING:  Live ID3D12CommandAllocator at 0x00000288F7CD0220, Refcount: 1, IntRef: 2 [ STATE_CREATION WARNING #571: LIVE_COMMANDALLOCATOR]
D3D12 WARNING:  Live ID3D12GraphicsCommandList at 0x00000288F7CD2740, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #573: LIVE_COMMANDLIST12]
D3D12 WARNING:  Live ID3D12CommandQueue at 0x00000288F7D33F60, Refcount: 7, IntRef: 0 [ STATE_CREATION WARNING #570: LIVE_COMMANDQUEUE]
D3D12 WARNING:  Live ID3D12Fence at 0x00000288F7EB5700, Name: Internal D3D12 Debug Fence, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #580: LIVE_MONITOREDFENCE]
D3D12 WARNING:  Live IDXGISwapChain at 0x00000288F7EE68F0, Refcount: 2 [ STATE_CREATION WARNING #275: LIVE_SWAPCHAIN]
D3D12 WARNING:  Live ID3D12LifetimeTracker at 0x00000288F7DDCCD0, Refcount: 2, IntRef: 0 [ STATE_CREATION WARNING #1164: LIVE_LIFETIMETRACKER]
D3D12 WARNING:  Live ID3D12Fence at 0x00000288F7EE95C0, Name: Internal DXGI Fence, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #580: LIVE_MONITOREDFENCE]
D3D12 WARNING:  Live ID3D12CommandAllocator at 0x00000288F7EE9810, Name: Internal DXGI CommandAllocator, Refcount: 1, IntRef: 2 [ STATE_CREATION WARNING #571: LIVE_COMMANDALLOCATOR]
D3D12 WARNING:  Live ID3D12GraphicsCommandList at 0x00000288F7EE9D20, Name: Internal DXGI CommandList, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #573: LIVE_COMMANDLIST12]
D3D12 WARNING:  Live ID3D12GraphicsCommandList at 0x00000288F7F37350, Name: Internal DXGI CommandList (debug layer indirect), Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #573: LIVE_COMMANDLIST12]
D3D12 WARNING:  Live ID3D12Resource at 0x00000288F7F3EC20, Refcount: 2, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING:  Live ID3D12Heap at 0x00000288F7F3E970, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #579: LIVE_HEAP]
D3D12 WARNING:  Live ID3D12Resource at 0x00000288F7F3FBD0, Refcount: 2, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING:  Live ID3D12Heap at 0x00000288F7F3F920, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #579: LIVE_HEAP]
D3D12 WARNING:  Live ID3D12Fence at 0x00000288F7F468F0, Refcount: 2, IntRef: 0 [ STATE_CREATION WARNING #580: LIVE_MONITOREDFENCE]
D3D12 WARNING:  Live ID3D12DescriptorHeap at 0x00000288F7D07310, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #576: LIVE_DESCRIPTORHEAP]
D3D12 WARNING:  Live ID3D12Fence at 0x00000288F7F46C80, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #580: LIVE_MONITOREDFENCE]
D3D12 WARNING:  Live ID3D12CommandAllocator at 0x00000288F7FCB650, Name: Internal DXGI CommandAllocator, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #571: LIVE_COMMANDALLOCATOR]
D3D12 WARNING:  Live ID3D12CommandAllocator at 0x00000288F7F66EF0, Name: Internal DXGI CommandAllocator, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #571: LIVE_COMMANDALLOCATOR]
D3D12 WARNING:  Live ID3D12GraphicsCommandList at 0x00000288F8AA0850, Refcount: 0, IntRef: 1 [ STATE_CREATION WARNING #573: LIVE_COMMANDLIST12]

プログラム終了の前に下記コードを埋め込むと見れるよ。

    // 変数名はサンプルコードに合わせた。
    ID3D12DebugDevice* pDebugDevice = NULL;
    dev_->QueryInterface(&pDebugDevice);
    dev_->Release();
    pDebugDevice->ReportLiveDeviceObjects(D3D12_RLDO_DETAIL);
    pDebugDevice->Release();

Chapter 4 ポリゴンの表示

特に躓くとこは無いはず。

提示されているソースコードが微妙に間違っているぐらい?
(Githubのサンプルを見たほうが良い)

Chapter 5 ポリゴンにテクスチャを貼り付ける

シェーダをこねくりまわす回。
シェーダについて詳しく知りたい人はここを読み込むと良さそう。

DirectX Texが必要。
git clone https://github.com/microsoft/DirectXTex.git
本書では環境変数の書き換えで対応しているが,環境変数は汚したくないのでゴリ押した。

  1. git cloneかzipでDirectXTexを落として,DirectX12プロジェクト直下に配置。
  2. DirectXTex_Desktop_2019.slnを開いてビルド(DirectXTex.libを作るため)。
  3. DirectXTex/Bin/Desktop_2019/x64/DirectXTex.libをコピー。
    -> 人による(サンプルだと/directx12_samples/Chapter5/に配置でいけた)。
  4. 相対パスでincludeする。
    -> #include "../DirectXTex/DirectXTex/DirectXTex.h" な感じ。
    -> #pragma comment(lib, "DirectXTex.lib")も忘れずに。

Chapter 6 行列による座標変換

3DCGの基礎。
数学は軽く流して,データ設定のやり方解説がメイン。

d3dx12.hもここから使い始める。

実行結果は割愛。

Chapter 7 PMDの読み込みとモデル表示

3Dモデル表示(MMD)がメイン。
(MMDMikuMikuDanceの略らしい。)

.objなどの単純フォーマットを読み込みたい人はここを読み込むと良さそう。
法線ベクトルなどにも触れ始めてる。

Chapter 8 マテリアル(材質)

トゥーンシェーダにも触れ始める。
絵面的にも面白くなってくるころ。

Debug版でビルドしたらRuntimeLibraryが云々と言われた。

1>DirectXTex.lib(DirectXTexImage.obj) : error LNK2038: 'RuntimeLibrary' の不一致が検出されました。値 'MDd_DynamicDebug' が MTd_StaticDebug の値 'main.obj' と一致しません。

Visual Studio2019ならデバッグ>プロパティ>C/C++>コード生成>ランタイムライブラリを
マルチスレッド デバッグ DLL (/MDd)
に設定すればいけた。

Debug版なので構成タブはDebugにした。

(なんか違う気がする…)

Chapter 9 リファクタリング

ComPtrを使ってクラス化してたので特にすることは無かった。

本書のまま進んでた人はこのタイミングでライブラリを作ろう。

Chapter 10 スキニングとアニメーション

ここからDirectX12とゲーム開発の組み合わせが本格化する。
ボーン処理などの解説も少しある。

DirectX12よりはスキニングがメイン。

Chapter 11 インバースキネマティクス(IK)

ほぼIKの解説。
結構詳しく書いてあるのでこれのために本書を買うのもアリだと思う。

スクワットしてる。

Chapter 12 マルチパスレンダリング

ここからDirectX12の話に戻りつつある。

簡単なポストエフェクトを実装する。
絵面が変化するので面白い。

Chapter 13 影行列とシャドウマップ

ついに影を描写する。

先にレイトレを学んどくと理解が楽かも。

Chapter 14 マルチレンダーターゲットとその応用

だんだん実装が辛くなってくるころ(バグりまくる)。
被写界深度とかを実装する。

実装とは関係ないけど,HRESULTの結果も表示してくれるデバッガ凄い。
調べる必要ないじゃん。

Chapter 15 スクリーンスペースアンビエントオクルージョン(SSAO)

環境遮蔽の原理と実装。
DirectX12よりも数学が辛くなった。

ここはサンプルを実行だけしてスルーした。

Chapter 16 imguiの利用

昔OpenGL3.Xとimguiを使って簡単なモデルビュアー作ってたので馴染み深い。
(自分語り。↓が実行画面。)

簡単に使える+UE4などのゲームエンジンにも導入できるのでオススメのライブラリ。
github.com

FFVIIRemakeやFallout76などでも使われてるらしい。
github.com

Chapter 17 Effekseerライブラリの利用

3Dエフェクトを作成するためのツール。
結構使い方をプログラム目線から解説しているのは貴重な気がする。

Chapter 18 DirectXTexの利用(文字列表示)

日本語フォント表示などの解説。
フォントデータの読み込みなど。


感想

プログラム書くのが結構難しかったので,メモはかなり大雑把になったな~って感じ。

本文中のプログラムは結構間違えていますが, IKやimguiなどのゲーム開発に必要な脇道的な内容も載っているのでこれだけでも読み価値はあると思います。

グラフィックスプログラマを目指す人にはおススメの1冊だと思いました。
(小学生並の感想)