我正在将OpenGL ES1.1迁移到2.0,用于2D目的(正交),但我在弄清如何应用变换(矩阵乘法顺序)方面遇到了一些问题。我只需要绕Z轴旋转,以及在X和Y上缩放,这两个值始终相同,因此这应该会显着简化事情。
我的当前方法(ES1.1)完美地工作,有一个虚拟摄像机,位于与物体相同的绝对坐标空间中。
在每个帧的开始时,我首先通过调用摄像机的变换来进行变换。
对于对象,看起来像这样(省略纹理和绘制调用)。
我认为无论相机矩阵本身的顺序如何(我尝试了多种方式,都没有正确工作),所有相机和对象模型视图变换必须编译到单个模型视图矩阵中(每个矩阵乘以最后一个,从相机变换开始,然后是对象,但显然是按特定顺序)。 这个操作顺序让我感到困惑,特别是它与ES1.1中正常工作的情况不符。 有人能解释一下正确的顺序吗?为什么gl调用与实际乘法不同?
我的当前方法(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调用与实际乘法不同?