4

从 OpenGL ES1.1 迁移到 2.0 用于 2D 目的(正交),我在弄清楚如何应用转换(矩阵乘法顺序)时遇到了一些麻烦。我只需要在 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;

无论相机矩阵本身的顺序如何,我都认为这是不正确的(我尝试了多种方法,但都没有正确)。我相信所有相机和对象模型视图转换都必须编译成一个模型视图矩阵(每个矩阵乘以最后一个,从相机转换开始,然后是对象,但显然是按特定顺序)。这种操作顺序是我感到困惑的地方,尤其是因为它与 ES1.1 中的正常工作不匹配。

有人可以解释正确的顺序,以及为什么 gl 调用与实际乘法不同吗?

4

2 回答 2

5

如果这在 OpenGLES 1.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 之后,您将获得推入堆栈的矩阵。所以它几乎什么也没做。

但是无论如何,如果您想要以这种顺序(glTranslatef、glScalef、glRotatef)重新生成 xforms 的矩阵,您需要以相同的顺序相乘(平移 * 比例)* 旋转

于 2012-09-06T22:27:53.600 回答