OpenGL以像素为单位定义顶点位置

时间:2011-09-11 11:29:31

标签: c++ opengl

我一直在用OpenGL / C ++编写2D基本游戏引擎,并在我学习的过程中学习一切。我仍然对定义顶点及其“位置”感到困惑。也就是说,我仍然试图理解OpenGL的顶点到像素转换机制。可以简单解释一下,或者有人指出一篇文章或其他可以解释这一点的内容。谢谢!

5 个答案:

答案 0 :(得分:27)

这是相当基本的知识,你最喜欢的OpenGL学习资源应该教你作为第一件事之一。但无论如何标准的OpenGL管道如下:

  1. 顶点位置从对象空间(局部到某个对象)转换为世界空间(相对于某些全局坐标系)。此转换指定对象(顶点所属的对象)在世界中的位置

  2. 现在世界空间位置转变为相机/视野。此变换由您通过其观看场景的虚拟摄像机的位置和方向确定。在OpenGL中,这两个转换实际上组合成一个模型视图矩阵,它直接将顶点从对象空间转换为视图空间。

  3. 接下来应用投影变换。虽然模型视图变换应该仅包括仿射变换(旋转,平移,缩放),但是投影变换可以是透视变换,其基本上扭曲对象以实现真实的透视图(具有更远的对象更小)。但在你的2D视图的情况下,它可能是一个正交投影,只做翻译和缩放。此变换由OpenGL通过投影矩阵表示。

  4. 在这3(或2)次变换之后(然后是w分量的透视除法,实际上实现了透视失真,如果有的话)你所拥有的是归一化的设备坐标。这意味着在这些变换之后,可见对象的坐标应该在[-1,1]范围内。超出此范围的所有东西都被剪掉了。

  5. 在最后一步中,应用视口转换并将坐标从[-1,1]范围转换为[0,w]x[0,h]x[0,1]多维数据集(假设glViewport(0, w, 0, h)调用),这是顶点在帧缓冲区中的最终位置,因此也就是它的像素坐标。

  6. 使用顶点着色器时,步骤1到3实际上是在着色器中完成的,因此可以以您喜欢的任何方式完成,但通常一个符合此标准模型视图 - >投影管道也是。

    要记住的主要事情是,在模型视图和投影变换之后,每个顶点都会被[-1,1]范围之外的坐标剪掉。因此,[-1,1] - 框会在这两次转换后确定您的可见场景。

    所以根据你的问题,我假设您想要使用具有像素单位的2D坐标系来进行顶点坐标和变换?在这种情况下,最好使用glOrtho(0.0, w, 0.0, h, -1.0, 1.0) wh作为视口的尺寸。这基本上会对视口转换进行计数,从而将顶点从[0,w]x[0,h]x[-1,1] - 框转换为[-1,1] - 框,然后视口转换会转换回[0,w]x[0,h]x[0,1] - 框。

    这些是非常普遍的解释,没有提到实际的变换是通过矩阵向量乘法完成的,并且没有谈论同质坐标,但它们应该已经解释了基本要素。这个documentation of gluProject也可能会给你一些见解,因为它实际上为单个顶点建模转换管道。但在本文档中,他们实际上忘记在v" = v' / v'(3)步骤之后提及w组件(v' = P x M x v)的划分。

    编辑:不要忘记查看epatel答案中的first link,这解释了转换管道更加实用和详细。

答案 1 :(得分:12)

它被称为转型。

顶点在3D坐标中设置,并转换为视口坐标(进入窗口视图)。可以以各种方式设置该转换。正交变换最容易理解为启动器。

http://www.songho.ca/opengl/gl_transform.html

http://www.opengl.org/wiki/Vertex_Transformation

http://www.falloutsoftware.com/tutorials/gl/gl5.htm

答案 2 :(得分:3)

首先要注意OpenGL不使用标准像素坐标。我的意思是特定分辨率,即。 800x600你没有水平坐标在0-799范围内或1-800步进一个。您的坐标范围从-1到1稍后发送到图形卡栅格化单元,然后匹配特定分辨率。

我在这里省略了一步 - 在所有你有一个ModelViewProjection矩阵(或在一些简单的情况下的viewProjection矩阵)之前,所有这些将你用于投影平面的坐标。默认使用它是实现一个转换世界3D空间的摄像机(用于将摄像机放置到正确位置的视图和用于将3d坐标投射到屏幕平面的投影。在ModelViewProjection中,它也是将模型放置在世界中正确位置的步骤)。

另一种情况(你可以用这种方式使用Projection矩阵来实现你想要的)就是使用这些矩阵将一系列分辨率转换成另一种分辨率。

你需要一个技巧。如果你想认真对待,你应该在openGL中阅读有关modelViewProjection矩阵和相机的内容。但是现在我会告诉你,使用适当的矩阵你可以将自己的坐标系(也就是使用范围0-799 horizo​​ntaly和0-599 verticaly)转换为标准化的-1:1范围。这样你就不会看到底层的openGL api使用他自己的-1对1系统。

实现这一目标的最简单方法是glOrtho功能。这是文档的链接: http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml

这是正确使用的示例:  glMatrixMode(GL_PROJECTION)  glLoadIdentity();  glOrtho(0,800,600,0,0,1)  glMatrixMode(GL_MODELVIEW)

现在你可以使用自己的modelView矩阵了。用于平移(移动)对象,但不要触摸您的投影示例。此代码应在任何绘图命令之前执行。 (如果你不使用3d图形,可以在初始化opengl之后)。

这是一个有效的例子:http://nehe.gamedev.net/tutorial/2d_texture_font/18002/

只需绘制数字而不是绘制文字。还有另一件事 - 用于选择矩阵的glPushMatrix和glPopMatrix(在此示例中为投影矩阵) - 在将3d与2d渲染结合使用之前,不要使用它。

你仍然可以使用模型矩阵(即用于在世界某处放置切片)和视图矩阵(例如缩放视图或滚动浏览世界 - 在这种情况下,你的世界可能比分辨率大,你可以裁剪视图通过简单的翻译)

在看了我的答案后,我发现它有点乱,但如果你感到困惑 - 只需阅读有关模型,视图和投影的标题,并尝试使用glOrtho的例子。如果你仍然感到困惑,请随时提出。

答案 3 :(得分:1)

MSDN有一个很棒的explanation。它可能与DirectX有关,但OpenGL或多或少相同。

答案 4 :(得分:-3)

谷歌的“opengl渲染管道”。前五篇文章都提供了很好的论述。

从顶点到像素的键转换(实际上是片段,但如果您认为“像素”,则不会太远)在光栅化阶段,这是在所有顶点从世界坐标转换为屏幕坐标和剪辑。