HLSLWithoutFX10 サンプル

HLSLwithoutEffects は、エフェクト インターフェイスを使用せずに、HLSL を使用して頂点シェーダーとピクセル シェーダーを記述する方法を示しています。HLSL は、構文や構造が C 言語に非常によく似た言語です。

Ee416414.d3d10_sample_HLSLWithoutFX(ja-jp,VS.85).jpg

パス

ソース SDK ルート\Samples\C++\Direct3D10\HLSLWithoutFX10
実行可能ファイル SDK ルート\Samples\C++\Direct3D10\Bin\x86 または x64\HLSLWithoutFX10.exe

サンプルが動作するしくみ

このサンプルでレンダリングするシーンは、XZ 平面にある複数の三角形の正方形グリッドで構成されています。各フレームでは、原点までの距離と時間の関数に基づいて、このグリッドの頂点が Y 方向に沿って上下に移動します。頂点はまた、距離と時間の別の関数を使用してライティングされます。時間はフレームごとに増分されます。頂点の Y 座標と色はフレームごとに生成されるため、格納する必要はありません。したがって、頂点の宣言には X および Z 座標の D3DXVECTOR2 のみを記述します。

初期化では、D3DX10CompileShaderFromFile を呼び出して、ファイルからシェーダー関数を読み取り、それをバイナリ シェーダーにコンパイルします。この処理が終了すると、ID3D10Blob にシェーダー バイナリが追加されます。次に、サンプルは、シェーダー コードを使用して CreateVertexShader または CreatePixelShader を呼び出し、デバイスに渡すことのできる ID3D10Device オブジェクトを取得します。

FrameMove では、シェーダーのビュー + 射影トランスフォームと時間パラメーターを更新するために、ID3D10Buffer インターフェイスを使用して、シェーダーのグローバル変数 mViewProj および fTime を設定します。レンダリング時は、VSSetShader および PSSetShader を呼び出して、後続のレンダリング呼び出しに使用する頂点シェーダーとピクセル シェーダーを設定します。GSSetShader は、ジオメトリ シェーダーを NULL または未使用として設定するのに使用します。この後で DrawIndexed を呼び出すと、頂点が処理されるたびに一度ずつ頂点シェーダーが呼び出されます。ピクセル シェーダーは、ピクセルがラスター化されるたびに呼び出されます。

アプリケーション コード内のシェーダー定数を定義する構造体 (VS_CONSTANT_BUFFER) がシェーダー内の定数バッファー (cbuffer cb0) と確実に一致するよう、定数の手動パッキングが使用されます。Direct3D 10 では、デフォルトで、可能な限り多くの変数が float4 にパッキングされます。これは、Visual Studio で #pragma pack(16) を使用する場合と似ていますが、HLSL コンパイラでは、実際には複数の変数が 1 つの float4 にパッキングされます。たとえば、2 つの float2 変数は、デフォルトで、HLSL の場合は 4 個分の浮動小数点位置を占めますが、Visual Studio の場合は 8 個分の位置を占めます。変数が一定の方法でパッキングされるようにするには、packoffset キーワードを使用して、定数バッファー内の各変数の配置位置を手動で確認できます。シェーダーで packoffset キーワードを使用する方法は、次のとおりです。

//-----------------------------------------------------------------------------// Global variables//-----------------------------------------------------------------------------cbuffer cb0{    row_major float4x4 mWorldViewProj : packoffset(c0);     // World * View * Projection transformation    float fTime :                       packoffset(c5.y);   // Time parameter. This keeps increasing                                                            // Notice, that this parameter is placed in c5.y.                                                            // If it were packed by the default packing rules,                                                             // it would be placed in c4.x};

packoffset(c0) は、mWorldViewProj 行列の最初のエントリを c0 に配置します。これにより、定数 c0、c1、c2、c3 はこの行列内の要素によって確実にカバーされます。fTime は c5.y に配置されます。デフォルトのパッキング規則では、fTime 変数は c4.x に配置されます。この手法は、定数バッファー内の変数を非常に特殊なパターンで配置する場合に使用できます。たとえば、fTime 変数を c4.z に配置すると、mWorldViewProj と fTime の間に浮動小数点 2 個分のスペースが残ります。同様に、シェーダーが想定する位置に fTime 変数を確実に配置するには、定数バッファー内の fTime の配置位置をアプリケーションで変更する必要があります。

サンプルでは、頂点シェーダーは HLSLwithoutEffects10.vsh というテキスト ファイルに記述されます。このファイルには、2 つのグローバル変数と、Ripple というシェーダー関数が含まれます。Ripple は、1 つの float2 を頂点の X および Z の入力として受け取り、スクリーン空間の位置と頂点色を表す 2 つの float4 を出力します。Y 座標は次の式で生成されます。

Y = 0.1 * sin( 15 * L * sin(T) );

L は、Y を調整する前の頂点から原点までの距離です。頂点は XZ 平面にあるため、L の値は sqrt(X2 + Z2) になります。T は、fTime グローバル変数です。

頂点は、次の式に基づいて、ややグレーがかった色になります。

C = 0.5 - 0.5 * cos( 15 * L * sin(T) );

C は、赤、緑、青、アルファのすべてに使用される 0 ~ 1 の値になり、頂点に黒から白までの色を付けます。結果は、後方と前方とで幅が狭くなったり広くなったりしながら、傾斜に応じて適切に陰影が付けられた波紋のようになります。