4

2D目的(正投影)でOpenGL ES1.1から2.0に移行しますが、変換の適用方法(行列の乗算順序)を理解するのに少し問題があります。Z軸での回転と、常に同じ値であるXとYでのスケーリングのみが必要なので、これにより、処理が大幅に簡素化されます。完璧に機能する私の現在の方法(ES1.1)には、オブジェクトと同じ絶対座標空間に配置された仮想カメラがあります。

各フレームの開始時に、最初にを呼び出してカメラの変換を行います

    glRotatef(angle, 0.0f, 0.0f, 1.0f);
    glScalef(zoom, zoom, 0.0f);
    glTranslatef(-pos.x, -pos.y, 0.0f); // negative position to shift everything back to the center of the view

オブジェクトの場合、次のようになります(テクスチャと描画の呼び出しを省略します)。

   glPushMatrix(); // to preserve camera transform
   glTranslatef(pos.x, pos.y, 0.0f);
   glScalef(scale, scale, 0.0f);
   glRotatef(angle, 0.0f, 0.0f, 1.0f);
   // drawing done here
   glPopMatrix();

ES2.0でこれと同じ機能を取得しようとしていますが、すべてのマトリックス操作を手動で実行する必要があります。

このリンクから、乗算の適切な順序は((Scale * Rotation)* Translation)である必要があることがわかりました。

その後、2Dの方がはるかに単純なので、これらすべてを組み合わせた単一の行列式を思いつきました。正射影行列も含めました。テストシェーダーの場合、私はこれを持っています:

   attribute vec4 position;
   attribute vec4 color;

   varying vec4 colorVarying;

   uniform vec2 translate;
   uniform float rotate;
   uniform float scale;
   uniform vec4 camera; // x, y, z = angle, w = zoom

   void main()
   {

        const float w = 3.2;
        const float h = 4.8;

        mat4 projection = mat4(1.0/w, 0.0, 0.0, 0.0,
                       0.0, 1.0/h, 0.0, 0.0,
                       0.0, 0.0, -1.0, 0.0,
                       0.0, 0.0, 0.0, 1.0);

        float s1 = scale * sin(rotate);
        float s2 = scale * cos(rotate);

        mat4 m = mat4(s2, s1, 0.0, 0.0,
              -s1, s2, 0.0, 0.0,
              0.0, 0.0, 1.0, 0.0,
              translate.x, translate.y, 0.0, 1.0);

        gl_Position = projection * m * position;

        colorVarying = color;
  }

これは、あらゆる自由度に対して想定されているのと同じように機能します。しかし、カメラの組み込み方がわかりません。シェーダーでの行列の乗算の順序がgl呼び出しの順序と一致しないため、カメラ呼び出しを乗算に変換する方法がわかりません。最初は、カメラの個別の変換マトリックスを計算して、次のように最終的な位置を設定しようとしていました。

    gl_Position = projection * cam * m * position;

カメラマトリックス自体の順序に関係なく、これは正しいとは思いません(私は複数の方法を試しましたが、どれも正しく機能しませんでした)。すべてのカメラとオブジェクトのmodelview変換は、単一のmodelviewマトリックスにコンパイルする必要があると思います(各マトリックスに最後の行列を掛け、カメラの変換から始まり、オブジェクト、そして明らかに特定の順序で)。この操作の順序は、特にES1.1で正しく機能していたものと一致しないため、私が混乱しているものです。

誰かが正しい順序を説明できますか、そしてなぜgl呼び出しが実際の乗算と異なるのですか?

4

2 に答える 2

5

これがOpenGLES1.1で機能している場合

glRotatef(angle, 0.0f, 0.0f, 1.0f); //camera
glScalef(zoom, zoom, 0.0f);         //camera
glTranslatef(-pos.x, -pos.y, 0.0f); //camera

glTranslatef(pos.x, pos.y, 0.0f);   //model
glScalef(scale, scale, 0.0f);       //model
glRotatef(angle, 0.0f, 0.0f, 1.0f); //model

その場合、OpenGLES 2.0での同等の操作は(すべて同じ順序で)次のようになります。

modelViewMatrix = camRotate * 
                  camScale * 
                  camTranslate * 
                  objTranslate * 
                  objScale * 
                  objRotate;

それに射影行列を追加するには、左側に追加するだけです。

mvpMatrix = proj * modelViewMatrix;

頂点を変換するには、右側で乗算します。

transformed = mvpMatrix * in_vert;
于 2012-09-06T22:26:27.710 に答える
1

glPushMatrix、glTranslatef、glScalef、glRotatef、glPopMatrixの後に、スタックにプッシュしたマトリックスを取得します。したがって、それはほとんど何もしません。

しかし、とにかく、この順序で実行されるxforms(glTranslatef、glScalef、glRotatef)を再現する行列が必要な場合は、同じ順序で乗算する必要があります(変換*スケール)*回転

于 2012-09-06T22:27:53.600 に答える