OpenGL ES2.0 Modelview矩阵2D

时间:2012-09-06 22:13:18

标签: matrix camera opengl-es-2.0 model-view opengl-es-1.1

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

this link我发现多重选择的正确顺序应为((比例*旋转)*翻译)

接下来,我想出了一个结合了所有这些的单矩阵公式,因为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调用与实际的乘法不同?

2 个答案:

答案 0 :(得分: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 :(得分:1)

在glPushMatrix,glTranslatef,glScalef,glRotatef,glPopMatrix之后你会得到你推到堆叠的矩阵。所以它什么都没做。

但是无论如何你想要按照这个顺序重新执行xforms的矩阵( glTranslatef,glScalef,glRotatef )你需要以相同的顺序乘以(translation * scale)* rotation