頂点シェーダーワールド変換、なぜ4次元ベクトルを使用するのですか?

StackOverflow https://stackoverflow.com/questions/1605703

  •  05-07-2019
  •  | 
  •  

質問

このサイトから: http://www.toymaker.info/Games/html /vertex_shaders.html

次のコードスニペットがあります:

// transformations provided by the app, constant Uniform data
float4x4 matWorldViewProj: WORLDVIEWPROJECTION;

// the format of our vertex data
struct VS_OUTPUT
{
  float4 Pos  : POSITION;
};

// Simple Vertex Shader - carry out transformation
VS_OUTPUT VS(float4 Pos  : POSITION)
{
  VS_OUTPUT Out = (VS_OUTPUT)0;
  Out.Pos = mul(Pos,matWorldViewProj);
  return Out;
}

私の質問は、構造体VS_OUTPUTがその位置として4次元ベクトルを持っているのはなぜですか? x、y、zだけではないですか?

役に立ちましたか?

解決

遠近法の計算にはw座標が必要なので。 DirectXよりも頂点シェーダーから出力した後、wで除算することにより、パースペクティブ除算を実行します。

基本的に、出力頂点位置として32768、-32768、32768、65536がある場合、wを除算すると0.5、-0.5、0.5、1になります。この時点で、wは不要になったため破棄できます。次に、この情報はビューポートマトリックスを介して渡され、使用可能な2D座標に変換されます。

編集:射影行列を使用して行列の乗算がどのように実行されるかを見ると、値が正しい場所に配置される方法を確認できます。

D3DXMatrixPerspectiveLHで指定された投影行列を取得する

2*zn/w  0       0              0
0       2*zn/h  0              0
0       0       zf/(zf-zn)     1
0       0       zn*zf/(zn-zf)  0

そして、ランダムなx、y、z、1に適用します(頂点位置wが常に1になることに注意してください)。頂点入力値は次のようになります

x' = ((2*zn/w) * x) + (0 * y) + (0 * z) + (0 * w)
y' = (0 * x) + ((2*zn/h) * y) + (0 * z) + (0 * w)
z' = (0 * x) + (0 * y) + ((zf/(zf-zn)) * z) + ((zn*zf/(zn-zf)) * w)
w' = (0 * x) + (0 * y) + (1 * z) + (0 * w)

すぐに、wとzが異なることがわかります。 w座標には、投影行列に渡されたz座標のみが含まれるようになりました。 zにはもっと複雑なものが含まれています。

したがって、入力位置が(2、1、5、1)で、zn(Z-Near)が1、zf(Z-Farが10)、aw(幅)が1であると仮定します。およびah(高さ)1。

取得してこれらの値を渡す

x' = (((2 * 1)/1) * 2
y' = (((2 * 1)/1) * 1
z' = ((10/(10-1)  * 5 + ((10 * 1/(1-10)) * 1)
w' = 5

その後取得することを展開

x' = 4
y' = 2
z' = 4.4
w' = 5

次に、最終的な遠近法の分割を実行し、取得します

x'' = 0.8
y'' = 0.4
z'' = 0.88
w'' = 1

これで、最終的な座標位置ができました。これは、xとyの範囲が-1〜1で、zの範囲が0〜1であることを前提としています。ご覧のとおり、頂点は画面上にあります。

奇妙なボーナスとして、| x '|または| y '|または| z '| | w '|よりも大きいまたは、z 'が0より小さい場合、頂点はオフスクリーンです。この情報は、画面に三角形をクリップするために使用されます。

とにかく、それはかなり包括的な答えだと思う:D

Edit2:ROWメジャーマトリックスを使用しています。列の主行列は転置されます。

他のヒント

回転は3次元の行列で指定され、平行移動はベクトルで指定されます。 「単一」で両方の変換を実行できます。それらを単一の4 x 3行列に組み合わせて操作します。

rx1 rx2 rx3 tx1
ry1 ry2 ry3 ty1
rz1 rz2 rz3 tz1

ただし、これは正方形ではないため、実行できないさまざまな操作があります(1つの反転)。余分な行を追加する(何もしない):

0   0   0   1

これらすべての操作が可能になります(簡単でない場合)。

Gozが彼の答えで「1」を作ります行列が非恒等値の場合、透視変換になります。

クリッピングは、ジオメトリに何が起こるかを視覚化するのに役立つため、このプロセスの重要な部分です。クリッピングステージは、基本的に、原点を中心とする2ユニットキューブの外側にあるプリミティブのすべてのポイントを破棄します(部分的にクリップされているが、ここでは関係ないプリミティブを再構築する必要があります)。

ワールド空間座標をそのような立方体に直接マッピングするマトリックスを構築することは可能ですが、遠方の平面から近方の平面への緩やかな動きは線形になります。つまり、視聴者から1マイル離れたときに1フィート(視聴者に向かって)移動すると、カメラから数フィート離れたときに1フィート移動するのと同じサイズになります。

ただし、ベクトル(w)に別の座標がある場合、ベクトルをコンポーネント単位でwで除算できます。プリミティブは上記の動作を示しませんが、2の内部に配置することはできます。 -上記のユニットキューブ。

詳細な説明については、 http://www.opengl.orgを参照してください。 /resources/faq/technical/depthbuffer.htm#0060 および http:// en .wikipedia.org / wiki / Transformation_matrix#Perspective_projection

簡単な答えは、wが何であるかをパイプラインに伝えなければ、投影に関する十分な情報を与えていないということです。これは、パイプラインがそれで何をするかを理解することなく直接検証できます...

ご存知のように、4x4マトリックスは各部分の機能に基づいて部分に分割できます。回転または拡大縮小操作を行うと、左上の3x3マトリックスが変更されます。 4番目の列は、翻訳を行うと変更されます。パースペクティブマトリックスを検査すると、マトリックスの最下行が変更されます。次に、マトリックスとベクトルの乗算がどのように行われるかを見ると、マトリックスの一番下の行のみが、ベクトルの結果のwコンポーネントに影響することがわかります。したがって、wについてパイプラインに伝えないと、すべての情報が得られません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top