5

OpenGL での回転と変換に関しては、私は少し立ち往生しています。

投影、ビュー、モデルの 3 つのマトリックスを取得しました。

私の頂点シェーダー:

gl_Position =  projection * model * view * vec4(vertexData, 1);

オブジェクトを移動および回転する最良の方法は何ですか?

モデル マトリックスに平行移動または回転マトリックスを掛けるか、データ (回転と平行移動) をシェーダーとそこの数学に渡しますか?

また、マウスピッキングの実装のために「最終的なオブジェクトの位置」を知る必要があります。

私がこれまでに行ったことは、次のようなものでした。

object.Transformation = Matrix.CreateTransLation(x,y,z) * Matrix.CreateRotation(x,y,z);

...

ForEach object to Draw
{
    modelMatrix.Push();

    modelMatrix.Mult(object.Transformation); // this also updates the matrix for the shader

    object.Draw();

    modelMatrix.Pop();
}

これは機能しますが、気分が良くありません。これを行う最善の方法は何ですか?

4

1 に答える 1

16

これ

gl_Position =  projection * model * view * vec4(vertexData, 1);

間違っている。行列の乗算は可換ではありません。つまり、演算の順序が重要です。頂点の位置の変換は次のとおりです。

  • モデル
  • 見る
  • 投影

OpenGL で使用される列ベクトルの行列乗算は、左結合です。つまり、右から左に進みます。したがって、ステートメントの R 側の式は次のようになります。

gl_Position =  projection * view * model * vec4(vertexPosition, 1);

ただし、ビューとモデル変換を複合モデルビュー (最初のモデル、次にビュー) 変換に縮小できます。これにより、完全な行列乗算が節約されます

gl_Position =  projection * modelview * vec4(vertexPosition, 1);

他のシェーディング ステップでは、投影が適用されていない結果である頂点の視点空間位置が必要になる場合があるため、投影は個別に保持する必要がありますmodelview * position

ところで:データではなく、頂点の位置を変換しています。頂点は (位置だけでなく) より多くの属性で構成されているため、「データ」と呼ぶのは意味的に間違っています。

オブジェクトを移動および回転する最良の方法は何ですか?

これらはモデルビュー変換の一部です。CPU で変換行列を1回だけ作成し、それを GPU に渡す必要があります。シェーダーでこれを行うと、GPU は頂点ごとに計算全体をやり直すことになります。あなたはこれをしたくありません。

コメントがあったので更新

私の→linmath.hを使用しているとしましょう。次に、描画関数で、シーンの足場を設定します。つまり、ビューポートを設定し、投影とビュー マトリックスを作成します。

#include <linmath.h>

/* ... */

void display(void)
{
     mat4x4 projection;
     mat4x4 view;

     glClear(…),
     glViewport(…);

     mat4x4_frustum(projection, …);

     // linmath.h doesn't have a look_at function... yet
     // I'll add it soon
     mat4x4_look_at(view, …);

次に、オブジェクトごとに位置と向き (平行移動と回転) を設定します。向きはクォータニオンに格納するのが最も便利ですが、ベクトルを処理するには行列表現の方がうまく機能します。そのため、シーン内のオブジェクトを反復処理します

     for(int i_object = 0; i_object < scene->n_objects; i++) {
         Object * const obj = scene->objects + i;

         mat4x4 translation, orientation, model_view;

         mat4x4_translate(translation, obj->pos.x, obj->pos.y, obj->pos.z);
         mat4x4_from_quat(orientation, obj->orientation);
         mat4x4_mul(model_view, translation, orientation);

model_viewモデルマトリックスが含まれるようになりました。次にview行列を掛けます。行列の乗算は右から左に行われることに注意してください (mat4x4_mul は入力オペランドの 1 つに出力できます)。

         mat4x4_mul(model_view, view, model_view);

model_view完全なコンパウンド モデルの向きと変換およびビュー マトリックスが含まれるようになりました。あとは、オブジェクトに使用するシェーダー プログラムをバインドするだけです。

         glUseProgram(obj->shader->program);

ユニフォームをセット

         glUniformMatrix4f(obj->shader->location.projection, 1, GL_FALSE, projection);
         glUniformMatrix4f(obj->shader->location.modelview,  1, GL_FALSE, model_view);
         // and a few others...

そして、オブジェクトを描画します

        object_draw(obj);
    }

/* ... */

}
于 2012-12-29T17:40:25.870 に答える