​テクスチャの描画

 四角形の板を一枚用意して、そこに画像を貼り付けます(テクスチャマッピング)。四角形の板は、「面の描画」で用いたものと同じです。そこへ画像を一枚用意して、取り込み、描画を行います。画像の取り込みには、WIC(Windows Imaging Component)を使いました。これにより、BMPをはじめ、PNG、JPEG等、主要なファイル形式の画像を簡単に読み込むことができます。これで、画像ファイルの取り込みについては問題がなくなりましたが、もう一点気をつけなければならない事があります。それは画像のサイズです。基本的にDirectXで使われる画像のサイズは、縦横それぞれ、2の冪乗(32、64、1024、...)でなければなりません。色々な画像のサイズで試してみましたが、とりあえず横の長さが2の冪乗になっていれば、縦の長さは任意で大丈夫でした。

 テクスチャをポリゴンに張り付けるためには、ポリゴンの各頂点に頂点座標の他に、その頂点がテクスチャ上のどの点に対応するのか、テクスチャ上の座標情報も持たせる必要があります。テクスチャ上の座標は、UV座標と言い、左上が原点O(0, 0)になります。UV座標の各成分は0.0~1.0で表現されます。なので、右上の座標は(1.0, 0.0)、左下の座標は(0.0, 1.0)、右下の座標は(1.0, 1.0)になります。頂点以外の部分における座標の計算はDirectXが勝手にやってくれます。座標計算は勝手にやってくれますが、テクスチャには勝手にアクセス出来ないので、テクスチャとピクセルシェーダとを橋渡するためのビューの設定と作成を行います。これでピクセルシェーダからテクスチャを読み込むことが出来るようになります。シェーダからテクスチャを読み込み、どうやって色を抽出するのかは、サンプラに定義します。ピクセルシェーダにて、サンプラで定義された内容に沿って、指定された座標の色の抽出を行い、その色をピクセルシェーダの戻り値としています。

 テクスチャマッピングを行うにあたって、頂点情報内の座標情報の他に、テクスチャ上のUV座標を保持するメンバを一つ追加します。このメンバの追加と頂点レイアウトの変更は、「シェーディング」や「頂点カラー」の項目で説明されている内容と同じため、省略します。

​コード解説

① 画像ファイルの読み込み
 WICを使った画像ファイルの読み込みを行います。PNG、JPEG等の主要なファイルを以下のコードで扱うことができます。

1行目でCOMライブラリの初期化を行っています。7行目にて、読み込むファイル名の指定を行っています。10行目で1ドットの色情報(RGBの3バイト)をRGBAの4バイトになるように変換を行ています。13行目で読み込んだ画像の縦、横の長さを取得しています。画像の読み込みに関しては、上記のコードを定型文として使用出来ると思います。

② 画像の転送とビューの作成
 画像を送る前に、送る画像の設定の定義をD3D11_TEXTURE2D_DESC構造体で行うのですが、メンバの内容はこれまで見てきた頂点バッファ作成時のD3D11_BUFFER_DESC構造体と似ているので省略します。違いとしては、送る画像の縦、横の大きさなどの記述が増えています。その他はあまり変わりありません。下記のコードは、画像を送る部分と、シェーダから画像をアクセスするためのビューの作成を行っています。

1行目から4行目で画像を送っています。見た目がメインループ内で定数をシェーダに送っている所とほとんど一緒です。メインループでは、memcpy_s関数を使って値のコピーを行ていますが、ここでは、IWICFormatConverterのCopyPixels関数を使って画像データのコピーを行っています。

​6行目から9行目で画像へアクセスするビューの設定を行っています。10行目でビューと画像との関連付けを行い、11行目でビューとシェーダとの関連付けを行っています。11行目の第一引数は、画像データのやり取りを行うためのスロット番号を指定しています。

サンプル​コード

< 動作確認環境 >
 ・Windows10 Pro
 ・Visual Studio Community 2017


基本的には空のプロジェクトを作ってもらい、以下のソースコードをコピペするだけでうまく実行できるかと思います。もしうまくいかない場合がありましたら、サンプルコードの実行に関する注意事項を一度参照してみてください。

③ シェーダ側の変更
 定数バッファ内のメンバに、画像の受け取りメンバと色の抽出方法を定義したサンプラのメンバの2つが増えました。また、ピクセルシェーダで実際に画像から色の抽出を行っています。

3行目のgtextureで画像を受け取っています。今回は画像が1枚だけだったため、シェーダ側でのスロット番号の指定を省略しました。4行目のgDefaultSamplerでは、画像からどのように色を抽出するのか、サンプラの定義を行っています。4行目ではただ宣言しているだけのように見えますが、この場合は​デフォルトの定義値が使われます。サンプラの定義方法及びデフォルト値は以下のようになっています。

テクスチャ (texture.png ※必ずこの名前で保存してください)

サンプラのメンバのそれぞれの意味は、以下のようになります。

  ・Filter    :サンプル時のフィルタリング方法を指定

  ・AddressU   :UV座標の0.0~1.0以外の時の値の扱い方を指定

  ・AddressV   :UV座標の0.0~1.0以外の時の値の扱い方を指定

  ・AddressW   :UV座標の0.0~1.0以外の時の値の扱い方を指定

  ・MinLOD    :ミップマップレベルの最小値

  ・MaxLOD    :ミップマップレベルの最大値

  ・MipMapLODBias :計算されたミップマップ レベルからのオフセット

  ・MaxAnisotropy :特定のフィルタ時に用いるクランプ値(1~16)

  ・ComparisonFunc:サンプリングデータの比較関数

  ・BorderColor  :D3D11_TEXTURE_ADDRESS_BORDERが指定されているときの境界色(0.0~1.0)

実際に色の抽出を行っているのは、ピクセルシェーダ内での一行です。Sample関数を使い、引数に、抽出方法と抽出場所の座標の指定を行っています。

ソースコード

シェーダのソースコード (shader.hlsl ※必ずこの名前で保存してください)