use*_*704 4 camera matrix model-view opengl-es-2.0 opengl-es-1.1
为了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
Run Code Online (Sandbox Code Playgroud)
对于对象,它看起来像这样(省略纹理和绘图调用).
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();
Run Code Online (Sandbox Code Playgroud)
我试图在ES2.0中获得相同的功能,但所有矩阵操作都必须手动执行.
从这个链接我发现多种选择的正确顺序应该是((Scale*Rotation)*翻译)
接下来,我提出了一个结合所有这些的单矩阵公式,因为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;
}
Run Code Online (Sandbox Code Playgroud)
它的工作原理就像它应该适用于各种自由度.但是,我无法弄清楚如何合并相机.着色器中矩阵的乘法顺序与gl调用的顺序不匹配,因此我不确定如何将我的相机调用转换为乘法.起初我还试图为相机计算一个单独的转换矩阵,并设置最终位置,如下所示:
gl_Position = projection * cam * m * position;
Run Code Online (Sandbox Code Playgroud)
无论相机矩阵本身的顺序如何,我认为这是不对的(我试过多种方式,没有一种方法正常).我相信所有相机和对象模型视图变换必须编译成单个模型视图矩阵(每个矩阵乘以最后一个,从相机变换开始,然后是对象,但显然按特定顺序).这种操作顺序是我很困惑的,特别是因为它与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
Run Code Online (Sandbox Code Playgroud)
那么OpenGLES 2.0中的等效操作将是(所有内容都以相同的顺序):
modelViewMatrix = camRotate *
camScale *
camTranslate *
objTranslate *
objScale *
objRotate;
Run Code Online (Sandbox Code Playgroud)
要为其添加投影矩阵,只需将其添加到左侧:
mvpMatrix = proj * modelViewMatrix;
Run Code Online (Sandbox Code Playgroud)
要转换顶点,请将其乘以右侧:
transformed = mvpMatrix * in_vert;
Run Code Online (Sandbox Code Playgroud)