4

このサイトから: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だけではありませんか?

4

3 に答える 3

10

遠近法の計算には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メジャー行列を使用していることに注意してください。列の主要な行列が入れ替わります。

于 2009-10-22T08:25:09.833 に答える
5

回転は3次元行列で指定され、平行移動はベクトルで指定されます。両方の変換を単一の4x3マトリックスに結合することにより、「単一の」操作で両方の変換を実行できます。

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

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

0   0   0   1

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

ゴズが彼の答えで「1」を非同一性の値にすることによって説明しているように、マトリックスは遠近法の変換になります。

于 2009-10-22T08:21:58.667 に答える
1

クリッピングは、ジオメトリに何が起こるかを視覚化するのに役立つため、このプロセスの重要な部分です。クリッピングステージは、基本的に、原点を中心とする2単位立方体の外側にあるプリミティブ内のポイントを破棄します(OK、部分的にクリッピングされたプリミティブを再構築する必要がありますが、ここでは問題ありません)。

ワールドスペースの座標をそのような立方体に直接マッピングするマトリックスを作成することは可能ですが、遠い平面から近い平面への段階的な移動は線形になります。つまり、視聴者から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について通知しないと、すべての情報が得られません。

于 2009-10-22T09:22:00.077 に答える