首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从OpenGL ES开始。使用像素绘制

从OpenGL ES开始。使用像素绘制
EN

Stack Overflow用户
提问于 2012-02-19 19:46:00
回答 3查看 3K关注 0票数 2

我开始学习使用java在android (GL10)中使用open GL,我还学习了一些绘制正方形、三角形等的教程。

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

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

代码语言:javascript
运行
复制
(-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?

对于我糟糕的英语,真的很感谢和抱歉。谢谢

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-02-19 20:51:33

为什么是全屏?OpenGL坐标的中心不是在左上角(0,0)吗?为什么使用顶点绘制是正确的?看起来中心实际上是屏幕的中心,宽度和高度是-1...1,但我并不是真的理解它,因为我以为中心在左上角……

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

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

代码语言:javascript
运行
复制
[-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首先将所有变换设置为identity,这意味着您通过的顶点坐标将直接到达NDC空间,并按如下方式解释。但是,在OpenGL中,大部分时间都是应用于连续的转换:

  • modelview

  • projection

模型视图变换用于在静止的眼睛/相机(始终位于(0,0,0))前面的世界中移动。放置相机只是意味着,添加一个额外的整个世界的变换(视图变换),这与你在世界中放置相机的方式完全相反。固定函数OpenGL将其称为MODELVIEW矩阵,如果矩阵模式已设置为GL_MODELVIEW,则可以访问该函数。

投影变换是一种OpenGL的透镜。您可以使用它来设置它是宽角度还是小角度(在透视的情况下),或者长方体的边缘(正交投影),或者甚至是不同的东西。固定函数OpenGL将其称为投影矩阵,如果矩阵模式已设置为GL_PROJECTION,则可以访问该函数。

在剪切投影基元之后,如果应用了透视投影,则应用所谓的同质分割,这将产生实际的透视效果。

此时,顶点已转换到NDC空间,然后将其映射到视口,如开头所述。

关于您的问题:您需要的是将顶点坐标1:1映射到视口像素的投影。很简单:

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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);
}
票数 9
EN

Stack Overflow用户

发布于 2012-02-19 19:57:51

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

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

你可以使用GL_POINTS给屏幕上的一些像素上色,但如果你需要绘制物体/网格,如茶壶,立方体等,那么你应该使用三角形。

票数 2
EN

Stack Overflow用户

发布于 2012-02-19 19:59:45

你需要多读一点,才能看得更清楚。在openGL中,可以指定视口。此视口是您的OpenGL空间视图,因此,如果您将其设置为屏幕中心位于屏幕中央,并且视图从-1延伸到1,则这是您的OpenGL透视全视图。不要把它和Android中的屏幕坐标混在一起(这些坐标的原点在左上角,就像你提到的那样)。您需要在这些坐标之间进行转换(例如,对于touchevents )来匹配另一个坐标系。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9348856

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档