
マイケル
みなさんこんにちは!
マイケルです!
マイケルです!

エレキベア
こんにちクマ〜〜〜

マイケル
今日は前回から引き続き、DirectX12を触っていきます!
前回はポリゴン表示まで行ったので、続きとしてDirectXTexというライブラリを使用してテクスチャ描画するところまで進めていこうと思います。
前回はポリゴン表示まで行ったので、続きとしてDirectXTexというライブラリを使用してテクスチャ描画するところまで進めていこうと思います。

エレキベア
ポリゴンにテクスチャを貼り付けるクマね

マイケル
実装方法については公式のサンプルと下記の書籍を参考にさせていただきました!
この記事を読むことで、サンプルのコードの内容も大体理解できるようになると思います。
この記事を読むことで、サンプルのコードの内容も大体理解できるようになると思います。
GitHub – microsoft / DirectX-Graphics-Samples (HelloTexture)
↑公式のサンプル
DirectX 12の魔導書 3Dレンダリングの基礎からMMDモデルを踊らせるまで

エレキベア
日本語の書籍はありがたいクマ〜〜〜

マイケル
なお、今回作ったサンプルについてはGitHubに上げていますので、
全体の実装についてはこちらをご参照ください!
全体の実装についてはこちらをご参照ください!
GitHub – masarito617/cpp-dx12-sample-texture
↑今回作ったサンプル

エレキベア
前回作ったのをベースに実装を加えたものクマね
シェーダーにUV値を渡す

マイケル
それではコードを書いていきますが、前回作ったポリゴン描画のコードを修正する形で進めていきます。
DirectX12の基本についても含めて、前回の記事をご参照下さい!
DirectX12の基本についても含めて、前回の記事をご参照下さい!

エレキベア
ポリゴン描画しただけの状態からテクスチャ描画まで進めていくクマね

マイケル
テクスチャを描画する前に、まずはUV値を渡せるようシェーダー周りを修正していきましょう!
シェーダーの修正

マイケル
頂点シェーダー、ピクセルシェーダーで受け渡すパラメータとして構造体を使用するため、hlsliファイルを追加します。
今回はBasicType.hlsliとして作成し、頂点座標とUV値をまとめたものを構造体として定義しました。
今回はBasicType.hlsliとして作成し、頂点座標とUV値をまとめたものを構造体として定義しました。

エレキベア
この情報をシェーダー間で受け渡しするクマね

マイケル
頂点シェーダー、ピクセルシェーダーは下記のように修正します。
ピクセルシェーダーに関しては、一旦UV値をそのまま色として出力するようにしています。
ピクセルシェーダーに関しては、一旦UV値をそのまま色として出力するようにしています。
↑確認のためUV値を色としてそのまま出力

エレキベア
最終的に渡したUV値が色として出力されたら成功クマね
シェーダーにUV値を渡す

マイケル
それでは実際にUV値を渡してみます。
C++側も頂点シェーダーへ渡す型定義としてVertex構造体を定義します。
C++側も頂点シェーダーへ渡す型定義としてVertex構造体を定義します。
↑頂点シェーダーに渡す構造体を定義

マイケル
そして頂点座標を渡している箇所にUV値も追加します。
元々XMFLOAT3型として渡していた箇所をVertex型へ変更するのも忘れないようにしましょう。
元々XMFLOAT3型として渡していた箇所をVertex型へ変更するのも忘れないようにしましょう。
↑UV値を渡すよう修正

マイケル
後は今回、構造体ファイルをシェーダーファイル内でincludeするようになったため、
D3D_COMPILE_STANDARD_FILE_INCLUDE フラグも指定するようにすれば完了です!
D3D_COMPILE_STANDARD_FILE_INCLUDE フラグも指定するようにすれば完了です!
↑D3D_COMPILE_STANDARD_FILE_INCLUDEフラグを設定する

エレキベア
ここまでは簡単クマね
頂点レイアウトの修正

マイケル
最後に、パイプラインステートに渡している頂点レイアウトにもUV値を追加しておきます。
TEXCOORDがUVを表すセマンティクスになります。
TEXCOORDがUVを表すセマンティクスになります。
↑頂点レイアウトにも追加
実行!

マイケル
この状態で実行すると、下記のように左上が青(0,0,1,1)、右下が白(1,1,1,1)で表示されることが確認できるはずです!

エレキベア
これだけでも結構綺麗クマ〜〜〜
コードで書いたテクスチャを描画する

マイケル
次に、コードで仮のテクスチャを定義して描画してみます。
前回軽く紹介した通り、テクスチャ等の情報をCPUとGPU間でやり取りする場合にはディスクリプタテーブルを使用してレジスタを関連付ける必要があります。
この辺りが少し複雑なので注意しましょう!
前回軽く紹介した通り、テクスチャ等の情報をCPUとGPU間でやり取りする場合にはディスクリプタテーブルを使用してレジスタを関連付ける必要があります。
この辺りが少し複雑なので注意しましょう!
ダミーのテクスチャ

マイケル
ダミーのテクスチャは下記にように定義しておきます。
格子状に白黒が描画されるテクスチャになります。
格子状に白黒が描画されるテクスチャになります。
↑格子状のテクスチャをコードで書いたもの
↑ヘッダファイルの定義

マイケル
これは公式サンプルのHelloTextureリポジトリ内にあるコードをそのまま拝借したものになります。
ロード処理は一旦後回しにしてこのコードをテクスチャと想定して描画してみましょう!
ロード処理は一旦後回しにしてこのコードをテクスチャと想定して描画してみましょう!
GitHub – microsoft / DirectX-Graphics-Samples (HelloTexture)
↑公式のサンプル

エレキベア
公式サンプルだと画像を読み込まずにコードで描画しているクマね
ピクセルシェーダーの修正

マイケル
そしてUV値を出力していただけのピクセルシェーダーを下記のように修正します。
register(t0)、register(s0)等の部分は、登録したレジスターの0番目から情報を取得している処理になります。
register(t0)、register(s0)等の部分は、登録したレジスターの0番目から情報を取得している処理になります。
↑レジスタからテクスチャ情報を取得して描画

エレキベア
これからこのレジスタにテクスチャの情報を登録して渡すクマね
ヘッダーファイルの修正

マイケル
ヘッダーファイルには、テクスチャバッファーとシェーダーリソースビュー(SRV)というディスクリプタヒープを追加します。
SRVはテクスチャ情報をまとめたビューで、シェーダーのレジスタとディスクリプタテーブルで紐づけることでシェーダー側から参照できるようにします。
SRVはテクスチャ情報をまとめたビューで、シェーダーのレジスタとディスクリプタテーブルで紐づけることでシェーダー側から参照できるようにします。
↑テクスチャバッファーとSRVを定義

エレキベア
ややこしいクマ・・・・
ディスクリプタテーブルの生成

マイケル
複雑になってきたので、改めて関連する用語についてまとめておきます。
ディスクリプタテーブルはディスクリプタヒープとシェーダーのレジスタを関連づけたもの、そしてディスクリプタテーブルをまとめるのがルートシグネチャになります。
ディスクリプタテーブルはディスクリプタヒープとシェーダーのレジスタを関連づけたもの、そしてディスクリプタテーブルをまとめるのがルートシグネチャになります。
用語 | 概要 |
---|---|
ディスクリプタ | GPUに送るリソースの仕様について示したもの。 |
ディスクリプタヒープ | ディスクリプタをまとめたもの。 |
ディスクリプタテーブル | ルートシグネチャ内で設定し、ディスクリプタヒープとシェーダーのレジスタを関連付けたもの。 |
ルートシグネチャ | ディスクリプタテーブルをまとめたもの。 |

マイケル
前回は空のルートシグネチャを作成していましたが、今回はディスクリプタテーブルを作成してルートシグネチャに設定する必要があります。
ディスクリプタテーブルの実体であるルートパラメータとサンプラーを生成し、それらを元にルートシグネチャを生成します。
ディスクリプタテーブルの実体であるルートパラメータとサンプラーを生成し、それらを元にルートシグネチャを生成します。
↑ルートシグネチャの生成

エレキベア
あ、頭が痛いクマ・・・
テクスチャバッファ、シェーダーリソースビューの生成

マイケル
次にテクスチャバッファ、シェーダーリソースビューの生成を行います。
まずはディスクリプタヒープの初期化処理にシェーダーリソースビューも追加しましょう。
まずはディスクリプタヒープの初期化処理にシェーダーリソースビューも追加しましょう。
↑シェーダーリソースビューをディスクリプタヒープとして初期化

マイケル
そして冒頭で載せたダミーのテクスチャを読み込み、それを元にテクスチャバッファ、シェーダーリソースビューを生成します。
↑テクスチャバッファ、シェーダーリソースビューの生成

エレキベア
これでテクスチャのデータ自体は出来たクマね
テクスチャバッファの転送処理

マイケル
テクスチャデータの場合、パイプラインの外から設定されるデータのため、CPUからGPUへ転送を行う必要もあります。
アップロード用バッファの生成と、実際に転送を行う処理は下記になります。
アップロード用バッファの生成と、実際に転送を行う処理は下記になります。

マイケル
描画処理とは別に、ここでもコマンドリストに転送処理を格納して実行しています。
GPU側の処理になるため、フェンスでの待機処理を入れるのも忘れないようにしましょう!
GPU側の処理になるため、フェンスでの待機処理を入れるのも忘れないようにしましょう!

エレキベア
これでようやくGPU側でテクスチャが使えるようになるクマね
描画処理の修正

マイケル
最後に、描画処理でディスクリプタテーブルとシェーダーリソースビューを紐づければ完了です!!

エレキベア
長かったクマ〜〜〜〜
実行!

マイケル
ここで実行して下記のように表示されれば成功です!

マイケル
ダミーのテクスチャ部分を適当に変えて模様を変えてみるのも面白いですね

エレキベア
コードで書いていると模様を変えるのも楽クマね
DirectXTexで読み込んだテクスチャを描画する

マイケル
さあここまで来れば後一息!
DirectXTexというライブラリを使用して実際にテクスチャを読み込んで描画させてみます!
DirectXTexというライブラリを使用して実際にテクスチャを読み込んで描画させてみます!

エレキベア
やっとクマ〜〜〜!!
DirectXTexの導入

マイケル
DirectXTexはGitHubで公開されています。
こちらをローカル環境にクローンしましょう!
こちらをローカル環境にクローンしましょう!

マイケル
そして自身のVisualStudioのバージョンに合わせて DirectXTex_Desktop_XXX_Win10.sln となっているソリューションを開き、必要なプラットフォームでビルドします。

マイケル
ビルドすると [workspace]\DirectXTex\DirectXTex\Bin\Desktop_2022_Win10\x64\Debug といったフォルダの配下にlibファイルが出力されるため、こちらをincludeして使用します。

エレキベア
使用するために一度手元でビルドする必要があるのクマね

マイケル
そしてインクルードディレクトリ、ライブラリディレクトリにそれぞれ下記のパスを追加します。
・追加のインクルードディレクトリ
[workspace]\DirectXTex\DirectXTex
・追加のライブラリディレクトリ
[workspace]\DirectXTex\DirectXTex\Bin\Desktop_2022_Win10\x64\Debug
※x64、Debugビルドの場合

マイケル
[workspace]\DirectXTex\DirectXTex までの部分は環境変数として定義しておくと綺麗になるのでおすすめです。

マイケル
後は下記のようにインクルードを追加してみて、実行してエラーが出ていなければ導入完了です!
↑インクルードの追加

エレキベア
簡単クマ〜〜〜〜
テクスチャのロード処理の追加

マイケル
導入が完了したところで、今回は下記の適当に描いた画像をロードしてみます。

エレキベア
(マジで適当クマ・・・)

マイケル
ダミーのテクスチャを読み込んでいた箇所を下記のように修正します。
今回、画像は Assets/test_image.png というパスで格納しています。
今回、画像は Assets/test_image.png というパスで格納しています。
↑実際に画像を読み込んでみる

マイケル
そしてテクスチャバッファの生成、転送処理を読みこんだテクスチャに合わせて修正すれば完了です!
↑テクスチャバッファの生成、転送処理を一部修正

エレキベア
差し替えは楽だったクマね

マイケル
一点注意点として、LoadFromWICFile処理ではCoInitializeExを呼び出していることを前提としているようで、下記のように事前に呼び出し処理を記述しておかないとE_NOINTERFACEエラーになるようでした。
今回はmain.cppの頭に追加しています。
今回はmain.cppの頭に追加しています。
↑CoInitializeExを追加

エレキベア
これは思わぬ罠クマね〜〜
実行!

マイケル
ここまで実装したら実行!!
下記のように適当な画像が描画されれば成功です!!
下記のように適当な画像が描画されれば成功です!!

エレキベア
やったクマ〜〜〜〜
くだらない画像を出すために大変だったクマ〜〜〜〜
くだらない画像を出すために大変だったクマ〜〜〜〜
おわりに

マイケル
というわけで今回はDirectXTexを用いたテクスチャ描画でした!
どうだったかな??
どうだったかな??

エレキベア
テクスチャ一つ描画するだけで大変すぎるクマ・・・
Unity使いたいクマ・・・
Unity使いたいクマ・・・

マイケル
慣れもあるのかもしれないけど、やっぱり生のDirectXとなると大変だね・・・
とりあえず3Dモデル描画までは頑張ってみよう!!
とりあえず3Dモデル描画までは頑張ってみよう!!

マイケル
というわけで今回はこの辺で!!
アデューーー!!!
アデューーー!!!

エレキベア
クマ〜〜〜〜〜
【DirextX12】第二回 DirextX12を使ったゲーム開発 〜DirectXTexを用いたテクスチャ描画〜 〜完〜
※次回の記事はこちら!