为了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中获得同样的功能,但所有的矩阵运算都必须手动执行。
从这个链接中,我发现多丙交酯的正确顺序应该是((缩放*旋转)*平移)
之后,我提出了一个单一的矩阵公式,将所有这些结合在一起,因为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调用与实际的乘法不同?
如果这在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;
在glPushMatrix、glTranslatef、glScalef、glRotatef、glPopMatrix之后,您将得到推送到堆栈的矩阵。所以它几乎没有任何作用。
但无论如何,如果您希望矩阵按此顺序(glTranslatef、glScalef、glRotatef)生成xforms,则需要按相同顺序相乘(平移*缩放)*旋转