重要な API
バッファーとシェーダー オブジェクトを作成して構成するコードを移動したら、これらのシェーダー内のコードを OpenGL ES 2.0 の GL シェーダー言語 (GLSL) から Direct3D 11 の高レベル シェーダー言語 (HLSL) に移植します。
OpenGL ES 2.0 では、シェーダーは、gl_Position、gl_FragColor、gl_FragData[n] (n は特定のレンダー ターゲットのインデックス) などの組み込みを使用して、実行後にデータを返します。 Direct3D では、特定の組み込み関数はなく、シェーダーはそれぞれの main() 関数の戻り値の型としてデータを返します。
頂点の位置や法線など、シェーダーステージ間で補間するデータは、varying 宣言を使用して処理されます。 ただし、Direct3D にはこの宣言はありません。代わりに、シェーダー ステージ間で渡すデータは、HLSL セマンティックでマークする必要があります。 選択された特定のセマンティックは、データの目的を示します。 たとえば、フラグメント シェーダー間で補間する頂点データを次のように宣言します。
float4 vertPos : POSITION;
又は
float4 vertColor : COLOR;
POSITION は、頂点位置データを示すために使用されるセマンティックです。 POSITION は特殊なケースでもあります。補間後はピクセル シェーダーからアクセスできないためです。 したがって、SV_POSITIONを使用してピクセル シェーダーへの入力を指定する必要があり、補間された頂点データがその変数に配置されます。
float4 position : SV_POSITION;
セマンティクスは、シェーダーの本体 (メイン) メソッドで宣言できます。 ピクセル シェーダーの場合、body メソッドにはレンダー ターゲットを示す SV_TARGET[n]が必要です。 (数値サフィックスのないSV_TARGETは、既定でターゲット インデックス 0 がレンダリングされます)。
また、SV_POSITIONシステム値セマンティックを出力するには、頂点シェーダーが必要であることにも注意してください。 このセマンティックは、頂点位置データを座標値に解決します。x は -1 と 1 の間、y は -1 から 1 の間、z は元の同質座標 w 値 (z/w) で除算され、w は元の w 値 (1/w) で 1 除算されます。 ピクセル シェーダーは、SV_POSITION システム値セマンティックを使用して画面上のピクセル位置を取得します。x は 0 からレンダー ターゲットの幅、y は 0 からレンダー ターゲットの高さ (各オフセットは 0.5) です。 9_x機能レベルのピクセルシェーダーは、SV_POSITION値を読み取ることができません。
定数バッファーは、cbuffer で宣言し、検索用の特定の開始レジスタに関連付ける必要があります。
Direct3D 11: HLSL 定数バッファー宣言
cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
matrix mvp;
};
ここで、定数バッファーはレジスタ b0 を使用してパックされたバッファーを保持します。 すべてのレジスタは、b# という形式で参照されます。 定数バッファー、レジスタ、およびデータ パッキングの HLSL 実装の詳細については、シェーダー定数 (HLSL)を参照してください。
インストラクション
手順 1: 頂点シェーダーを移植する
この単純な OpenGL ES 2.0 の例では、頂点シェーダーには、定数モデル ビュー プロジェクション 4x4 マトリックスと 2 つの 4 座標ベクトルの 3 つの入力があります。 これら 2 つのベクトルには、頂点の位置とその色が含まれています。 シェーダーは、位置ベクトルをパースペクティブ座標に変換し、ラスタライズ用のgl_Position組み込み関数に割り当てます。 頂点の色は、ラスタライズ中の補間のためにさまざまな変数にコピーされます。
OpenGL ES 2.0: キューブ オブジェクトの頂点シェーダー (GLSL)
uniform mat4 u_mvpMatrix;
attribute vec4 a_position;
attribute vec4 a_color;
varying vec4 destColor;
void main()
{
gl_Position = u_mvpMatrix * a_position;
destColor = a_color;
}
Direct3D では、定数モデル ビュー プロジェクション マトリックスはレジスタ b0 にパックされた定数バッファーに含まれており、頂点の位置と色は、それぞれ適切な HLSL セマンティクスである POSITION と COLOR で具体的にマークされます。 入力レイアウトはこれら 2 つの頂点値の特定の配置を示しているため、それらを保持する構造体を作成し、シェーダー本体関数 (main) の入力パラメーターの型として宣言します。 (2 つの個別のパラメーターとして指定することもできますが、面倒になる可能性があります)。また、補間された位置と色を含むこのステージの出力の種類を指定し、頂点シェーダーの body 関数の戻り値として宣言します。
Direct3D 11: キューブ オブジェクトの頂点シェーダー (HLSL)
cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
matrix mvp;
};
// Per-vertex data used as input to the vertex shader.
struct VertexShaderInput
{
float3 pos : POSITION;
float3 color : COLOR;
};
// Per-vertex color data passed through the pixel shader.
struct PixelShaderInput
{
float3 pos : SV_POSITION;
float3 color : COLOR;
};
PixelShaderInput main(VertexShaderInput input)
{
PixelShaderInput output;
float4 pos = float4(input.pos, 1.0f); // add the w-coordinate
pos = mul(mvp, projection);
output.pos = pos;
output.color = input.color;
return output;
}
出力データ型 PixelShaderInput は、ラスター化中に設定され、フラグメント (ピクセル) シェーダーに提供されます。
手順 2: フラグメント シェーダーを移植する
GLSL のフラグメント シェーダーの例は非常に単純です。補間されたカラー値をgl_FragColor組み込み関数に提供します。 OpenGL ES 2.0 では、既定のレンダー ターゲットに書き込まれます。
OpenGL ES 2.0: キューブ オブジェクトのフラグメント シェーダー (GLSL)
varying vec4 destColor;
void main()
{
gl_FragColor = destColor;
}
Direct3D は、ほぼ単純です。 唯一の大きな違いは、ピクセル シェーダーの body 関数が値を返す必要があるということです。 色は 4 座標 (RGBA) 浮動小数点値であるため、戻り値の型として float4 を指定し、既定のレンダー ターゲットをSV_TARGETシステム値セマンティックとして指定します。
Direct3D 11: キューブ オブジェクトのピクセル シェーダー (HLSL)
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float3 color : COLOR;
};
float4 main(PixelShaderInput input) : SV_TARGET
{
return float4(input.color, 1.0f);
}
位置のピクセルの色がレンダー ターゲットに書き込まれます。 次に、そのレンダーターゲットのコンテンツを描画して、画面に表示する方法を見てみましょう。
前の手順
頂点バッファーとデータ を移植する
次のステップ
注釈
HLSL セマンティクスと定数バッファーのパッキングを理解すると、デバッグの手間を省き、最適化の機会を提供できます。 チャンスがある場合は、変数構文 (HLSL)、Direct3D 11のバッファーの概要、および 方法: 定数バッファーを作成する方法を読んでください。 そうでない場合は、セマンティクスと定数バッファーに関する最初のヒントをいくつか次に示します。
- 定数バッファーの構造体が HLSL の cbuffer 構造体宣言と一致していること、およびコンポーネントスカラー型が両方の宣言で一致することを確認するには、レンダラーの Direct3D 構成コードを必ず再確認してください。
- レンダラーの C++ コードで、定数バッファー宣言 DirectXMath 型を使用して、適切なデータパッキングを確保します。
- 定数バッファーを効率的に使用する最善の方法は、シェーダー変数を更新頻度に基づいて定数バッファーに整理することです。 たとえば、フレームごとに 1 回更新される一定のデータと、カメラが移動したときにのみ更新されるその他の均一データがある場合は、そのデータを 2 つの個別の定数バッファーに分割することを検討してください。
- 適用を忘れたセマンティクスや正しく適用しないセマンティクスは、シェーダー コンパイル (FXC) エラーの最も早いソースになります。 それらを再確認してください。 古いページやサンプルが Direct3D 11 より前のさまざまなバージョンの HLSL セマンティクスを参照するため、ドキュメントは少し混乱する可能性があります。
- 各シェーダーを対象とする Direct3D 機能レベルがわかっていることを確認します。 機能レベル 9_* のセマンティクスは、11_1 のセマンティクスとは異なります。
- SV_POSITIONセマンティックは、関連付けられた補間後の位置データを座標値に解決します。x は 0 とレンダー ターゲットの幅の間、y は 0 からレンダー ターゲットの高さの間、z は元の同質座標 w 値 (z/w) で除算され、w は元の w 値 (1/w) で 1 除算されます。
関連トピック
方法: 単純な OpenGL ES 2.0 レンダラーを Direct3D 11 に移植する
頂点バッファーとデータ を移植する