入力アセンブラー ステージの基礎知識 (Direct3D 10)
入力アセンブラー (IA) ステージを初期化するにはいくつかの手順を実行する必要があります。たとえば、パイプラインで必要とされる頂点データでバッファー リソースを作成し、このバッファーの場所と含まれるデータの種類を IA ステージに伝え、このデータからアセンブルするプリミティブの種類を指定する必要があります。
ここでは、次の表に示す IA ステージの設定で実行する基本的な手順について説明します。
Step | 説明 |
---|---|
入力バッファーの作成 | 入力バッファーを作成し、入力頂点データを使用して初期化します。 |
入力レイアウト オブジェクトの作成 | 入力レイアウト オブジェクトを使用して、頂点バッファー データを IA ステージにストリーム出力する方法を定義します。 |
入力アセンブラー ステージへのオブジェクトのバインド | 作成したオブジェクト (入力バッファーと入力レイアウト オブジェクト) を IA ステージにバインドします。 |
プリミティブの種類の指定 | 頂点からプリミティブへアセンブルする方法を指定します。 |
描画メソッドの呼び出し | パイプラインを通じて、IA ステージにバインドされたデータを送信します。 |
これらの手順を理解したら、「システム生成値の使用 (Direct3D 10)」に進んでください。
入力バッファーの作成
入力バッファーには、頂点バッファーとインデックス バッファーの 2 種類があります。頂点バッファーは、IA ステージに頂点データを渡します。インデックス バッファーはオプションで、頂点バッファーから頂点へのインデックスを提供します。頂点バッファーは 1 つまたは複数作成できます。また、必要に応じて、インデックス バッファーを 1 つ作成できます。
バッファー リソースの作成後、IA ステージにデータ レイアウトを指定する入力レイアウト オブジェクトを作成してから、バッファー リソースを IA ステージにバインドする必要があります。シェーダーがバッファーを使用しない場合は、バッファーの作成やバインドは必要ありません。三角形を 1 つ描画する単純な頂点とピクセル シェーダーの例については、「バッファーなしの入力アセンブラー ステージの使用 (Direct3D 10)」を参照してください。
頂点バッファーの作成については、「頂点バッファーを作成する」を参照してください。インデックス バッファーの作成にについては、「インデックス バッファーを作成する」を参照してください。
入力レイアウト オブジェクトの作成
入力レイアウト オブジェクトは、IA ステージの入力ステートをカプセル化します。これには、IA ステージにバインドされた入力データの記述も含まれます。データはメモリーの 1 つまたは複数の頂点バッファーから IA ステージにストリーム出力されます。入力データの記述は、1 つまたは複数の頂点バッファーからバインドされた入力データを特定し、ランタイムでのシェーダー入力パラメーターの種類に対する入力データの種類の確認を可能にします。この種類の確認では、種類に互換性があるかだけでなく、シェーダーで必要とされる要素がバッファー リソースに存在するかどうかも検証されます。
入力レイアウト オブジェクトは、入力要素の記述の配列と、コンパイル済みシェーダーへのポインターから作成されます (「ID3D10Device::CreateInputLayout」を参照)。この配列には 1 つまたは複数の入力要素が含まれます。各入力要素は、1 つの頂点バッファーからの 1 つの頂点データ要素を表します。入力要素の記述全体は、IA ステージにバインドされるすべのて頂点バッファーにあるすべての頂点データ要素を表します。
次のレイアウトの記述は、3 つの頂点データ要素を含む 1 つの頂点バッファーを表しています。
D3D10_INPUT_ELEMENT_DESC layout[] = { { L"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 }, { L"TEXTURE0", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 }, { L"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 1, 20, D3D10_INPUT_PER_VERTEX_DATA, 0 }, };
入力要素の記述は、サイズ、種類、位置、目的など、頂点バッファー内の 1 つの頂点に含まれる各要素を表しています。各行はセマンティクス、セマンティクス インデックス、およびデータ フォーマットを使用して、データの種類を特定します。セマンティクスは、データの使用方法を表すテキスト文字列です。この例では、1 行目は 3 つの成分からなる位置データ (例 : xyz) を、2 行目は 2 つの成分からなるテクスチャー データ (例 : UV)、3 行目は法線データを表しています。
この入力要素の記述の例では、セマンティクス インデックス (2 番目のパラメーター) は、3 行すべてで 0 に設定されています。セマンティクス インデックスは、同じセマンティクスを使用する 2 つの行の区別するのに役立ちます。この例では、類似するセマンティクスは使用されていないので、セマンティクス インデックスは既定の値、つまり 0 に設定できます。
3 番目のパラメーターは、フォーマットです。フォーマット (「DXGI_FORMAT」を参照) は、1 要素あたりの成分数と、各要素のデータ サイズを定義するデータ型を指定します。リソースの作成時にこのフォーマットの型を完全に指定できるほか、DXGI_FORMATを使用してリソースを作成することもできます。後者の場合、要素内の成分数は定義しますが、データ型は未定義のままです。
入力スロット
データは、入力スロットと呼ばれる入力を通じて、IA ステージに入力されます。IA ステージは n 個の入力スロットを持ちます。これは入力データを提供する、最大 n 個の頂点バッファーに対応するように設計されています。頂点バッファーはそれぞれ異なるスロットに割り当てる必要があります。この情報は、入力レイアウト オブジェクトの作成時に、入力レイアウト宣言に格納されます。また、各バッファーについて、先頭から、読み込みを行う最初の要素までのオフセットを指定することもできます。
図形 1. 入力アセンブラー ステージの入力スロット
次の 2 つのパラメーターは入力スロットと入力オフセットです。複数のバッファーを使用する場合、これらを 1 つまたは複数の入力スロットにバインドできます。入力オフセットとは、バッファーの先頭からデータの先頭までのバイト数です。
入力レイアウト オブジェクトの再利用
入力レイアウト オブジェクトは、シェーダー シグネチャに基づいて作成されます。これにより、API でシェーダー入力シグネチャに対して入力レイアウト オブジェクトを検証し、型とセマンティクスが正確に一致することを確認できます。複数のシェーダーのシェーダー入力シグニチャがすべて正確に一致している場合、これらに対して 1 つの入力レイアウト オブジェクトを作成できます。
入力アセンブラー ステージへのオブジェクトのバインド
頂点バッファー リソースと入力レイアウト オブジェクトの作成後、ID3D10Device::IASetVertexBuffers および ID3D10Device::IASetInputLayout を呼び出して、これらを IA ステージにバインドできます。次の例は、1 つの頂点バッファーと入力レイアウト オブジェクトを IA ステージにバインドしています。
UINT stride = sizeof( SimpleVertex ); UINT offset = 0; g_pd3dDevice->IASetVertexBuffers( 0, // the first input slot for binding 1, // the number of buffers in the array &g_pVertexBuffer, // the array of vertex buffers &stride, // array of stride values, one for each buffer &offset ); // array of offset values, one for each buffer // Set the input layout g_pd3dDevice->IASetInputLayout( g_pVertexLayout );
入力レイアウト オブジェクトをバインドするために必要なものは、オブジェクトへのポインターのみです。
前の例では、1 つの頂点バッファーがバインドされていますが、ID3D10Device::IASetVertexBuffers を 1 回呼び出すだけで複数の頂点バッファーをバインドすることができます。次のコードは、このような 1 回の呼び出しで、3 つの頂点バッファーをバインドしています。
UINT strides[3]; strides[0] = sizeof(SimpleVertex1); strides[1] = sizeof(SimpleVertex2); strides[2] = sizeof(SimpleVertex3); UINT offsets[3] = { 0, 0, 0 }; g_pd3dDevice->IASetVertexBuffers( 0, //first input slot for binding 3, //number of buffers in the array &g_pVertexBuffers, //array of three vertex buffers &strides, //array of stride values, one for each buffer &offsets ); //array of offset values, one for each buffer
インデックス バッファーは、ID3D10Device::IASetIndexBuffer を呼び出すことにより、IA ステージにバインドします。
プリミティブの種類の指定
入力バッファーのバインド後、IA ステージで頂点をプリミティブへアセンブルする方法を指定する必要があります。これには、ID3D10Device::IASetPrimitiveTopology を呼び出して、プリミティブの種類を指定します。次のコードは、この関数を呼び出して、隣接性を持たないトライアングル リストとしてデータを定義しています。
g_pd3dDevice->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
その他のプリミティブの種類については、「D3D10_PRIMITIVE_TOPOLOGY」を参照してください。
描画メソッドの呼び出し
パイプラインへの入力リソースのバインド後、アプリケーションでは描画メソッドを呼び出して、プリミティブをレンダリングします。次の表にあるように、描画メソッドには数種類あります。インデックス バッファーを使用するものもあれば、インスタンス データを使用するものもあります。また、入力アセンブラー ステージへの入力として、ストリーム出力ステージのデータを再利用するものもあります。
描画メソッド | 説明 |
---|---|
ID3D10Device::Draw | インデックス付けおよびインスタンス化されていないプリミティブを描画します。 |
ID3D10Device::DrawInstanced | インデックス付けされていないが、インスタンス化されているプリミティブを描画します。 |
ID3D10Device::DrawIndexed | インデックス付けされているが、インスタンス化されていないプリミティブを描画します。 |
ID3D10Device::DrawIndexedInstanced | インデックス付けおよびインスタンス化されているプリミティブを描画します。 |
ID3D10Device::DrawAuto | ストリーム出力ステージからの入力データである、インデックス付けおよびインスタンス化されていないプリミティブを描画します。 |
描画メソッドはそれぞれ 1 つのトポロジ タイプをレンダリングします。レンダリング中、不完全なプリミティブ (頂点の数が足りないもの、インデックスのないもの、部分的なプリミティブなど) は自動的に破棄されます。