水面を表す三角形のストリップで単純な 2D グリッドを生成します。最初に生成された頂点の位置は [0,0] で、最後の頂点の位置は [1,1] です。私の水のシミュレーションでは、頂点の現在の位置をテクスチャに保存し、次のフレームでテクスチャからこれらの値をサンプリングして、水面の以前の状態を取得する必要があります。
ということで、頂点サイズのテクスチャを作成しました。たとえば、10x10 の頂点グリッドがある場合、10x10 ピクセル (1 つの頂点データに対して 1 ピクセル) のテクスチャを使用します。そして、このテクスチャをレンダー ターゲットとして設定し、すべての頂点データをレンダリングします。
これによると: MSDN Coordinate Systems、グリッド内の頂点の現在の位置を使用する場合 ([0;0] で左下、[1;1] で右上)、レンダリングされたテクスチャは次のようになります。
そのため、NDC に変換する必要があります。次のように頂点シェーダーに変換します。
[頂点.x * 2 - 1; 頂点.y * 2 - 1]
次の 3x3 グリッドを考えてみましょう。
これで、グリッドがテクスチャ全体のサイズに引き伸ばされました。テクスチャ座標は NDC とは異なり、(変換前の) グリッドの元の座標を使用して、テクスチャから値をサンプリングし、頂点の以前の値 (位置) を取得できるようです。
これが私の頂点/ピクセル シェーダー コードのサンプルです。
この頂点シェーダーは座標を変換し、それを SV_POSITION セマンティクス (ピクセル位置を記述) でピクセル シェーダーに送信します。
struct VertexInput
{
float4 pos : POSITION;
float2 tex : TEXCOORD;
};
struct VertexOutput
{
float4 pos : SV_POSITION;
float2 tex : TEXCOORD;
};
// convertes coordinates from 0,0 origin to -1,-1, etc.
float2 toNDC(float2 px)
{
return float2(px.x * 2 - 1, px.y * 2 - 1);
}
VertexOutput main( VertexInput input )
{
VertexOutput output;
float2 ndc = toNDC(float2(input.pos.x, input.pos.z));
output.pos = float4(ndc, 1, 1);
output.tex = float2(input.pos.x, input.pos.z);
return output;
}
そして、定義されたピクセル位置 (SV_POSITION) で頂点シェーダーから値を保存するピクセル シェーダーを次に示します。
struct PixelInput
{
float4 pos : SV_POSITION;
float2 tex : TEXCOORD;
};
float4 main(PixelInput input) : SV_TARGET
{
return float4(input.tex.x, input.tex.y, 0, 1);
}
そして、ついに私の問題に取り掛かります!Visual Studio 2012 でグラフィック デバッガーを使用すると、レンダリングされたテクスチャとその値を確認できます。ピクセル位置 [0,1] (テクセル座標系) は値 [0,0] (RGBA 形式の場合、正確には [0,0,0,1]) であると予想されますが、最終ピクセルの値が 3 つの頂点間で補間され、指定された頂点の値が間違っています。
VS グラフィック デバッガーのスクリーンショット:
レンダリングされた 3x3 テクスチャ (テクセル座標系の [0;1] 位置):
頂点およびピクセル シェーダーからの値:
特定のピクセルの頂点シェーダーからテクスチャに正確な値をレンダリングする方法は? 私はコンピューター グラフィックスと Direct3D 11 にかなり慣れていないので、私の欠点を許してください。