OpenGL ES2.0模型视图矩阵2D

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中获得相同的功能,但是所有矩阵操作都必须手动执行。

这个链接中,我发现正确的乘法顺序应该是((缩放 * 旋转) * 平移)

在此基础上,我提出了一个单矩阵公式,将所有这些内容组合在一起,因为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调用与实际乘法不同?

谢谢,这篇文章真的让我开始了! - dac2009
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;

1
在glPushMatrix、glTranslatef、glScalef、glRotatef和glPopMatrix之后,您将获得推送到堆栈中的矩阵。因此,它几乎什么都没有做。
但是无论如何,如果您想要复制以这个顺序执行的xform的矩阵(glTranslatef、glScalef、glRotatef),则需要按相同顺序进行乘法操作(translation * scale)* rotation

我注意到你在翻译缩放时加了括号,但这可能会有一点误导,因为它们并不是必需的。 (AB)C 和 A(BC) 以及 AB*C 是相同的。 - Tim
抱歉,我应该更清楚地表达,我在这里省略了我的绘图调用,以减少混乱,但是我在弹出矩阵之前绘制每个对象(或精灵)。 - user1137704

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接