从OpenGL ES开始.使用像素绘制



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

现在我开始画一些我的想法,但我真的对屏幕的绘制顶点感到困惑。当我使用openGL ES绘制东西时,我必须指定我想要绘制的屏幕部分,纹理也是如此。。。

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

(-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?

真的很感谢,也很抱歉我英语不好。感谢

为什么这是全屏的?OpenGL的坐标中心不是在左上角吗(0,0)?为什么用那个顶点绘制是正确的?看起来中心确实是屏幕的真正中心,宽度和高度是从-1…1,但我真的不明白,因为我认为中心在左上角。。。

共有三件事。所谓的视口,所谓的归一化设备坐标(NDC),以及从模型空间到眼睛空间到剪辑空间到NDC空间的投影。

视口选择NDC范围所在的窗口部分

[-1…1]×[-1…1]

映射到。函数签名为glViewport(x, y, width, height)。OpenGL假设一个坐标系,其中上升的NDC x坐标向右,上升的NDCy坐标向上。

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

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);
}

默认情况下,opengl相机位于指向负z轴的原点。在飞机附近的相机上投影的东西就是在屏幕上看到的东西。因此,屏幕的中心对应于(0,0)

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

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

你需要多读一点才能更清楚。在openGL中,可以指定视口。此视口是OpenGL空间的视图,因此,如果将其设置为屏幕中心位于屏幕的中间,并且视图从-1扩展到1,则这是OpenGL预视图的完整视图。不要将其与Android中的屏幕坐标混淆(如您所述,这些坐标的原点位于左上角)。您需要在这些坐标之间进行转换(例如,对于触摸事件),以匹配其他坐标系。

最新更新