如何在OpenGL ES 2.0中实现glOrthof?

8

我正在尝试将我的OpenGL ES 1应用程序转换为OpenGL ES 2应用程序,以便能够使用着色器。现在,我使用glOrthof函数来拥有一个“实际大小的视口”,这样我就可以将顶点放置在OpenGL视图中的“实际”像素上。

glOrthof(0, _frame.size.width, _frame.size.height, 0, -1, 1);

我在 OpenGL ES 2 中遇到了一些困难,有没有人能向我展示如何做到这一点?

如果没有,是否有人可以提供一个好的 OpenGL ES 1 到 OpenGL ES 2 教程/解释的链接?

2个回答

12

glOrtho方法的作用是创建一个新的矩阵,并将当前投影矩阵乘以该矩阵。在OpenGL ES 2.0中,您需要自己管理矩阵。为了复制glOrtho的行为,您需要在顶点着色器中使用一个投影矩阵的uniform变量,并将其与顶点坐标相乘。通常情况下,您还需要模型矩阵和视图矩阵(或组合模型视图矩阵,就像在OpenGL ES 1中一样),在进行投影变换之前,需要将顶点坐标转换为这些矩阵的结果:

uniform mat4 projection;
uniform mat4 modelview;

attribute vec4 vertex;

void main()
{
    gl_Position = projection * (modelview * vertex);
}

你可以在这里找到glOrtho构建的具体投影矩阵。


你能向我展示如何创建/加载投影和模型视图吗? - Thizzer
@MrThys 如果您对此不确定,应该首先咨询一些关于OpenGL ES 2.0和GLSL着色器的学习资源。基本上,一旦您拥有相应的统一位置并且着色器程序已绑定/使用,您可以使用其中之一设置它们的值glUniform...调用,在矩阵的情况下,您将使用glUniformMatrix4fv - Christian Rau
@HaukeStrasdat 什么...你说得对!这样一个经典的参考资料怎么会失效呢?好吧,现在我们只剩下愚蠢的ES参考页面了。但是没关系,至少对于这个答案来说它们还是很合适的。 - Christian Rau
更新链接:https://www.khronos.org/opengles/sdk/1.1/docs/man/glOrtho.xml,但看起来文档转为HTML时丢失了必要的“/”和“()”。与Brad Larson的答案相比,文档可能试图表达 2/(right-left) 0 0 tx 0 2/(top-bottom) 0 ty 0 0 -2/(far-near) tz 0 0 0 1。其中 tx = -(right+left)/(right-left)ty = -(top+bottom)/(top-bottom)tz = -(far+near)/(far-near)。这与Larson的答案有一个差异:矩阵[10]是-2/(far-near),但Larson的答案没有负号2/f_n。因此z被反转了。尝试两种方式... - ToolmakerSteve
@ToolmakerSteve,减号应该在那里。由于眼空间中相机朝向-Z,但在NDC/窗口空间中+1表示远离,因此Z必须被反转。 - Christian Rau

10

如Christian所述,处理顶点的所有矩阵数学都由您完成,因此您必须复制glOrthof()创建的矩阵。在我的这里的回答中,我提供了以下用于生成正交投影矩阵的Objective-C方法:

- (void)loadOrthoMatrix:(GLfloat *)matrix left:(GLfloat)left right:(GLfloat)right bottom:(GLfloat)bottom top:(GLfloat)top near:(GLfloat)near far:(GLfloat)far;
{
    GLfloat r_l = right - left;
    GLfloat t_b = top - bottom;
    GLfloat f_n = far - near;
    GLfloat tx = - (right + left) / (right - left);
    GLfloat ty = - (top + bottom) / (top - bottom);
    GLfloat tz = - (far + near) / (far - near);

    matrix[0] = 2.0f / r_l;
    matrix[1] = 0.0f;
    matrix[2] = 0.0f;
    matrix[3] = tx;

    matrix[4] = 0.0f;
    matrix[5] = 2.0f / t_b;
    matrix[6] = 0.0f;
    matrix[7] = ty;

    matrix[8] = 0.0f;
    matrix[9] = 0.0f;
    matrix[10] = 2.0f / f_n;
    matrix[11] = tz;

    matrix[12] = 0.0f;
    matrix[13] = 0.0f;
    matrix[14] = 0.0f;
    matrix[15] = 1.0f;
}

这里使用的矩阵被定义为

GLfloat orthographicMatrix[16];

然后我在我的顶点着色器中使用类似以下的代码来应用矩阵:

gl_Position = modelViewProjMatrix * position * orthographicMatrix;

我的乘法顺序与Christian的不同,所以我可能在这里做了一些反向操作,但这是我在我的OpenGL ES 2.0应用程序中使用的处理方式(其源代码可以在此处找到:here)。


你的方法似乎完全符合glOrthof页面(例如http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml)给出的公式。 - Tommy
2
正交矩阵实际上是投影矩阵,但“modelViewProjMatrix”这个名称表明您有另一个投影矩阵,这在概念上有点奇怪(尽管有效,着色器无法实现)。但真正奇怪的是您将矩阵变换的左应用与右应用混合到向量中。这就是为什么您实际上在“loadOrthoMatrix”例程中创建转置矩阵的原因(以及为什么这个着色器代码应该对任何不太了解矩阵变换的人造成彻底的困惑的原因)。 - Christian Rau
@Christian - 你真的可以看出矩阵数学不是我的强项。着色器的命名是从另一个实现中留下来的,实际上应该只是第一个组件的模型视图矩阵。我想这是两个错误抵消的情况,但当我尝试时它确实起作用了,所以我从未质疑过为什么。感谢你指出这里的奇怪之处。 - Brad Larson
矩阵[10] = -2.0f / f_n; // 正确的减号已修正 - 请参阅文档 - Devon

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