85

行列の定義について完全に混乱しています。float[16]次の観察に基づいて、行優先であると仮定した を保持する行列クラスがあります。

float matrixA[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
float matrixB[4][4] = { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 }, { 12, 13, 14, 15 } };

matrixAどちらもメモリ内に同じ線形レイアウトをmatrixB持っています (つまり、すべての数字が順番に並んでいます)。http://en.wikipedia.org/wiki/Row-major_orderによると、これは行優先のレイアウトを示します。

matrixA[0] == matrixB[0][0];
matrixA[3] == matrixB[0][3];
matrixA[4] == matrixB[1][0];
matrixA[7] == matrixB[1][3];

したがって、matrixB[0]= 行 0、matrixB[1]= 行 1 などです。繰り返しますが、これは行優先のレイアウトを示します。

私の問題/混乱は、次のような翻訳マトリックスを作成すると発生します。

1, 0, 0, transX
0, 1, 0, transY
0, 0, 1, transZ
0, 0, 0, 1

これは、 としてメモリに配置されます{ 1, 0, 0, transX, 0, 1, 0, transY, 0, 0, 1, transZ, 0, 0, 0, 1 }

次に、glUniformMatrix4fvを呼び出すときに、転置フラグを GL_FALSE に設定して、列優先であることを示す必要があります。そうしないと、変換やスケールなどの変換が正しく適用されません。

転置が GL_FALSE の場合、各行列は列優先順で提供されると想定されます。転置が GL_TRUE の場合、各行列は行優先順で提供されると想定されます。

行優先のように見える行列を列優先として OpenGL に渡す必要があるのはなぜですか?

4

4 に答える 4

73

OpenGL ドキュメントで使用されている行列表記は、OpenGL 行列のメモリ内レイアウトを記述していません。

「行/列優先」全体を削除/忘れると簡単になると思います。これは、行/列優先に加えて、表記法に加えて、プログラマーがメモリ内でマトリックスをどのようにレイアウトするか (隣接する要素が行または列を形成するかどうか) を決定できるためです。

OpenGL マトリックスは、directx マトリックスと同じメモリ レイアウトを持ちます。

x.x x.y x.z 0
y.x y.y y.z 0
z.x z.y z.z 0
p.x p.y p.z 1

また

{ x.x x.y x.z 0 y.x y.y y.z 0 z.x z.y z.z 0 p.x p.y p.z 1 }
  • x、y、z は、マトリックス座標系 (グローバル座標系に対するローカル座標系) を表す 3 成分ベクトルです。

  • p は、マトリックス座標系の原点を表す 3 成分ベクトルです。

つまり、翻訳行列は次のようにメモリに配置する必要があります。

{ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, transX, transY, transZ, 1 }.

そのままにしておくと、残りは簡単なはずです。

---古いopengl faqからの引用--


9.005 OpenGL 行列は列優先ですか、それとも行優先ですか?

プログラミングの目的で、OpenGL 行列は 16 値の配列であり、基本ベクトルがメモリ内に連続して配置されます。変換コンポーネントは、OpenGL 2.1 仕様のセクション 2.11.2 で説明されているように、16 要素の行列の 13 番目、14 番目、および 15 番目の要素を占めます。インデックスには 1 から 16 までの番号が付けられます。

列優先と行優先は、純粋に表記規則です。列優先の行列を事後乗算すると、行優先の行列を事前に乗算した場合と同じ結果になることに注意してください。OpenGL 仕様と OpenGL リファレンス マニュアルの両方で、列優先の表記法が使用されています。明確に記載されている限り、任意の表記法を使用できます。

悲しいことに、仕様とブルー ブックでの列優先形式の使用は、OpenGL プログラミング コミュニティに終わりのない混乱をもたらしました。列優先の表記法は、プログラマが期待するように行列がメモリに配置されていないことを示唆しています。


于 2013-07-18T08:30:57.583 に答える
16

あなたは2つの別々の問題に取り組んでいます。

まず、あなたの例はメモリレイアウトを扱っています。[4][4] 配列は、線形配列と一致するように C 多次元配列によって確立された規則を使用したため、行優先です。

2 番目の問題は、プログラム内で行列を解釈する方法に関する規則の問題です。glUniformMatrix4fvは、シェーダー パラメーターを設定するために使用されます。変換が行ベクトルまたは列ベクトル変換のどちらで計算されるかは、シェーダー コードでマトリックスをどのように使用するかによって異なります。列ベクトルを使用する必要があると言うので、シェーダー コードは行列Aと列ベクトルxを使用してx' = A xを計算すると仮定します。

glUniformMatrixのドキュメントは紛らわしいと思います。転置パラメータの説明は、行列が転置されているか、転置されていないかを示すための非常に回りくどい方法です。OpenGL自体は、そのデータをシェーダーに転送しているだけです。転置するかどうかは、プログラムで確立する必要がある慣習の問題です。

このリンクには、さらに詳しい議論があります: http://steve.hollasch.net/cgindex/matrix/matrix/column-vec.html

于 2013-07-18T08:45:20.070 に答える