从OpenGL ES开始。使用像素绘图

时间:2012-02-19 11:46:00

标签: java android opengl-es vertex

我开始使用java在android(GL10)中学习开放GL,我按照一些教程来绘制正方形,三角形等。

现在我开始画出一些想法,但我真的很困惑屏幕的绘图顶点。当我使用openGL ES绘制一些东西时,我必须指定我想要绘制的屏幕部分和纹理相同...

所以我开始做一些测试,并用这个顶点打印了一个全屏纹理:

(-1, -1, //top left
 -1, 1, //bottom left
 1, -1, //top right
 1, 1); //bottom right

为什么这是全屏? OpenGL坐标的中心不是左上角(0,0)?为什么这个顶点的绘制是正确的?看起来中心真的是屏幕的真正中心,宽度和高度是-1 ... 1,但我真的不明白,因为我认为中心位于左上方......

另一个问题......我阅读了许多使用像素打印的c ++代码。在使用像素的电子游戏中似乎非常必要,因为需要事物的确切位置,并且-1 ... 1我不能非常精确。如何使用像素而不是-1 ... 1?

非常感谢和抱歉我的英语不好。感谢

3 个答案:

答案 0 :(得分:9)

  

为什么这是全屏? OpenGL坐标的中心不是左上角(0,0)?为什么这个顶点的绘制是正确的?看起来中心真的是屏幕的真正中心,宽度和高度是-1 ... 1,但我真的不明白,因为我认为中心位于左上方......

有三件事情在一起。所谓的视口,即所谓的规范化设备坐标(NDC),以及从模型空间到眼睛空间到剪裁空间到NDC空间的投影。

视口选择窗口中NDC范围

的部分
[-1…1]×[-1…1]

映射到。函数签名为glViewport(x, y, width, height)。 OpenGL假定一个坐标系统,NDC x坐标上升,向右移动,NDC y坐标上升。

因此,如果您调用glViewport(0, 0, window_width, window_height),这也是OpenGL上下文第一次绑定到窗口后的默认值,NDC坐标(-1,-1)将位于左下角和NDC中窗口右上角的坐标(1,1)。

OpenGL以所有转换设置为标识开始,这意味着您通过的顶点坐标正好通过NDC空间并被解释为这样。但是,大多数情况下,在OpenGL中,您将应用于连续转换:

  • 模型观察

  • 投影

模型视图转换用于在静止的眼睛/摄像机(始终位于(0,0,0))前方移动世界。放置相机只是意味着,增加了对整个世界的额外转换(视图转换),这与您将相机放置在世界中的方式完全相反。 固定功能OpenGL将 MODELVIEW矩阵称为,如果矩阵模式已设置为 GL_MODELVIEW,则会访问

投影变换是OpenGL的一种镜头。您可以使用它来设置是宽角度还是小角度(如果是透视)或长方体(正投影)的边缘,甚至是不同的角度。 固定功能OpenGL将 PROJECTION矩阵称为,如果矩阵模式已设置为 GL_PROJECTION,则被访问。

在剪切投影图元之后,如果应用了透视投影,则应用所谓的均匀划分,这将创建实际的透视效果。

此时顶点已经转换为NDC空间,然后按照开头的说明将其映射到视口。


关于你的问题:你想要的是一个投影,它将顶点坐标1:1映射到视口像素。很容易:

glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if( origin_lower_left ) {
    glOrtho(0, width, height, 0, -1, 1);
} else {
    glOrtho(0, width, 0, height, -1, 1);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

现在顶点坐标映射到视口像素。


更新:按三角形绘制完整视口纹理四边形:

OpenGL-2.1和OpenGL ES-1

void fullscreenquad(int width, int height, GLuint texture)
{
    GLfloat vtcs[] = {
      0, 0,
      1, 0,
      1, 1,
      0, 1
    };

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glVertexPointer(2, GL_FLOAT, 0, vtcs);
    glTexCoordPointer(2, GL_FLOAT, 0, vtcs);

    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, 1, 0, 1, -1, 1);

    glMatrixMode(GL_MODELVIEW);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texture);
    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}

答案 1 :(得分:2)

默认情况下,opengl相机放置在指向负z轴的原点。 无论飞机附近的投影是什么,都可以在屏幕上看到。 因此,屏幕的中心对应于(0,0)

根据您想要绘制的内容,您可以选择使用GL_POINT,GL_LINE和GL_TRIANGLE进行绘制。

您可以使用GL_POINTS为屏幕上的某些像素着色,但是如果您需要绘制对象/网格(如茶壶,立方体等),则应该使用三角形。

答案 2 :(得分:2)

您需要阅读更多信息以使事情更清晰。在openGL中,指定一个视口。此视口是您对OpenGL空间的视图,因此如果您将其设置为使屏幕中心位于屏幕中间并且视图从-1扩展到1,那么这是您对OpenGL的全面了解。不要将它与Android中的屏幕坐标混合(这些坐标的原点位于左上角,如上所述)。您需要在这些坐标之间进行转换(例如,对于touchevents)以匹配其他坐标系。