テクスチャ専用機能
今パートではテクスチャの専用機能について見ていきます。
サンプラによるデータの読み込みもバッファとの違いになりますが、テクスチャの配列を作れたり、ミップマップと呼ばれる低解像度のデータを1つのテクスチャにまとめて使えたりとデータ構造もバッファとは違ってきます。
3DCGではこの機能を活かした技法もありますので、簡単な使い方を覚えておくと理解が早くなるのではないでしょうか。
ドキュメント:Direct3D 11 のテクスクチャーの概要
(日本語)
(英語)
概要
それではテクスチャの専用機能について見ていきましょう。
対応するプロジェクトはPart16_Texture2になります。
ミップマップ
まず、ミップマップについて見ていきます。
ミップマップは元となるテクスチャのサイズを半分に縮小したものになります。
普通のテクスチャと比べますとメモリ量が増えますが、テクスチャを縮小してサンプリングするときにはより自然な見た目になったり、ミップマップの個々のテクスチャは解像度が小さくなるのでメモリアクセスが速度が速くなったりします。
詳しい説明はWikipedeiaとこちらのドキュメントを参照してください。
ここではミップマップを持つテクスチャの作成と書き込み、読み込みについて説明していきます。
作成
ミップマップを持つテクスチャを作るときはD3D11_TEXTURE2D_DESCのMipLevelsに必要となるミップマップの数を指定します。
その他は今までのテクスチャの作成と同じです。
ちなみにミップマップの各要素をミップレベルと呼びます。
GPUに設定するときもシェーダリソースビューやアンオーダードアクセスビューを使用します。
ただし、アンオーダードアクセスビューを使うときはミップレベルの数分用意する必要があるので忘れないで下さい。
シェーダリソースビューは1つのビューで全ミップレベルにアクセスできますが、作成時の設定で1つのミップマップにしかアクセス出来ないようにしたり、最大レベルを指定したり出来ます。
ID3D11DeviceContext::GenerateMips
サンプルではアンオーダードアクセスビューを使って各ミップレベルの内容を書き込んでいました。
ですが、ID3D11DeviceContext::GenerateMipsを使用すると、最上位のミップレベルの内容をもとに下層のミップレベルを自動生成することが出来ます。
機能レベルによっては対応していないフォーマットがあるので注意してください。
ID3D11DeviceContext::GenerateMipsを使用するときはBindFlagsにD3D11_BIND_RENDER_TARGETとD3D11_BIND_SHADER_RESOURCEを指定した上でMiscFlagsにD3D11_RESOURCE_MISC_GENERATE_MIPSを設定する必要があります。
ドキュメント:ID3D11DeviceContext::GenerateMips
(日本語)
(英語)
書き込み
各ミップレベルへの書き込みを行うシェーダは以下のようになります。
と言いましても、今までのRWTexture2Dと変わりません。
GPUへの設定も変わりません。書き込みたいミップレベルのアンオーダードアクセスビューを設定するのを忘れないようにするだけです。
読み込み
ミップマップの読み込みは少し異なります。
サンプラを使う場合はSampleLevelの第3引数に読み込みたいミップレベルを指定します。
添字を使った場合はmips.Operator[][]を使用します。
使い方は下のコードを参考にしてください。
ドキュメント:
Texture2D
(日本語)
(英語)
配列
次は配列について見ていきます。
この配列は文字通りの配列で、テクスチャは配列を作ることが出来ます。
作成
配列を持つテクスチャを作るにはD3D11_TEXTURE2D_DESCのArraySizeに配列の要素数を指定するだけできます。
配列でないテクスチャを作るときは必ず1を指定してください。
後、ミップマップと異なりアンオーダードアクセスビューは1つで全要素にアクセスできます。
シェーダリソースビューはミップマップと同じで1つで全要素にアクセス可能です。
補足ですが、配列とミップマップは同時作成することが可能ですので必要に応じて設定を行ってください。
書き込み
配列に書き込む際は座標に加えて書き込み先の要素の添字を指定します。
例えばRWTexture2Dの場合ならuint3を使ってアクセスします。
uint3.xyでテクスチャの座標を、uint3.zで配列の添字を指定します。
読み込み
配列の読み込みも書き込みと同じく、座標と配列の添字を指定することでアクセスできます。
キューブマップ
次はキューブマップについて見ていきます。
キューブマップは環境マッピングという鏡などの映り込みや周囲の環境光を再現するときによく使われるものです。
キューブマップ自体のデータ構造はテクスチャ配列と変わりません。ですがデータの並びに意味があります。
0番目はX軸方向の環境を,1番目は-X軸方向の環境,2番目はy軸方向の環境を…といった感じです。
もちろんキューブマップも配列やミップマップを持つことができます。
作成
キューブマップを作成するときはArraySizeに6を指定します。
配列の場合は6の倍数になるようにします。
書き込み
書き込みにはアンオーダードアクセスビューを使うことも出来ますが、サンプルではグラフィックスパイプラインを利用して書き込んでいます。
グラフィックスパイプラインを利用することでリアルタイムに周囲の環境を保存することができます。
ただ、それだと処理負荷が高くなるので、事前に描画した結果をファイルに保存し、実行時にそれを読み込むといった使い方もあります。
どちらにせよ、グラフィックスパイプラインを利用すると楽に周囲の環境を書き込むことが出来ます。
上のSV_RenderTargetArrayIndexがもっとも重要な部分になります。
レンダーターゲットにはテクスチャ配列を指定することが出来ますが、何もしなければ0番目の要素にしか書き込みができません。
それを防ぐためにSV_RenderTargetArrayIndexを指定した変数に書き込みたい要素の添字を指定します。
ドキュメント:SV_RenderTargetArrayIndex
(日本語)
(英語)
読み込み
キューブマップの読み込みは他のものとは大きく異なります。
読み込みはサンプラのみで、UV座標ではなく方向を表すfloat3でサンプリングする場所を指定します。
このことからキューブマップを環境マッピングを行うのに特化したものといえるでしょう。
マルチサンプリング
次はマルチサンプリングテクスチャです。
マルチサンプリングはMSAAというアンチエイリアスの1手法で使われるもので、ポリゴンのギザギザを滑らかにするために使われます。
マルチサンプリングテクスチャはテクセル1つにつき複数のサンプリングポイントを内部に持つものになります。
サンプリングポイントはテクセル内全体にまんべんなく配置されていて、ラスタライズの際にサンプリングポイントの1つでもプリミティブの内部にあるなら描画されます。
作成
マルチサンプリングテクスチャの作るにはD3D11_TEXTURE2D_DESCのSampleDescを使用します。
SampleDescはメンバにCount(サンプリング数)とQuality(品質)の2つ持っています。
QualityはGPUによっては使用できる値が異なりますので、必ずID3D11Device::CheckMultisampleQualityLevelsで使えるか確認してください。
ドキュメント:ID3D11Device::CheckMultisampleQualityLevels
(日本語)
(英語)
作成後、アンチエイリアスを適応するにはID3D11DeviceContext::ResolveSubresourceを使用し他のマルチサンプリングではないテクスチャへコピーを行います。
ドキュメント:ID3D11DeviceContext::ResolveSubresource
(日本語)
(英語)
まとめ
テクスチャの専用機能については以上です。
バッファかテクスチャどちらを使うかはこれらの機能を見て決めるといいでしょう。
補足
サブリソースの添字について
ID3D11DeviceContextのコピー関数のいくつかやマップ関数にサブリソースを指定する引数がありました。
サブリソースはメインのリソースと今回見てきたミップマップや配列の各要素を指します。
サブリソースも添字でアクセスし、その並び順はミップマップを優先したものとなりますので使うときは注意してください。