22

我目前正在将 OpenGL 驱动的渲染器实现到 2D 游戏引擎中。

因为 OpenGL 屏幕坐标空间是 [-1,1],我对它应该如何与通用的笛卡尔 2D 世界坐标系进行交互有点困惑。

假设我的世界中的视口是 [-500,-500] 到 [1200, 1200],其中 [0, 0] 是世界的原点。我只需要翻译和缩小到-1和1之间的坐标吗?还是需要执行其他形式的转换?

您如何计算在屏幕上在您自己的坐标系中定义了位置的对象的绘制位置?

我会很感激有和没有 glOrtho 的解释(所以我们也可以使用 Z 轴来实现透视效果)。

4

3 回答 3

19

首先,OpenGL使用多个坐标系,所以没有“ OpenGL坐标系”。您指的是标准化设备坐标 (NDC),其中所有三个坐标都在 [-1, 1] 范围内。不同的坐标系及其名称“9.011 如何转换坐标?有哪些不同的坐标空间?”一节中进行了解释。1)

其次,为避免混淆,在 OpenGL 中,术语“视口”指的是您要渲染到的窗口部分,它位于窗口坐标中。在您的问题中,您使用它来描述您想要渲染的世界的部分 (l,r,t,b)=(-500, -500, 1200, 1200),它位于世界坐标中。

您问如何“计算在屏幕上绘制对象的位置”。您需要做的是定义一个从一个坐标系映射到另一个坐标系的变换(一个 4x4 矩阵)。您的 2D 世界以世界坐标给出,因此您需要定义一个将世界坐标转换为 NDC 的矩阵,即投影矩阵。然后,在您的着色器中,您只需将顶点与此投影矩阵相乘,即可获得 NDC。glm::ortho/glOrtho计算这样一个投影矩阵。至于透视投影,不清楚你想做什么,但你应该试验一下glm中的perspectiveandlookat函数。

为了清楚起见,您可以在任何您想要的坐标系(称为世界坐标系)中定义顶点,然后简单地绘制这些顶点。您的顶点着色器的工作是应用您定义的转换。

另请注意,您指定了一个正方形,通常这不是您想要的。监视器和大多数窗口都不是正方形的,因此如果您将该正方形映射到一个典型的视口上,您会得到一个扭曲的世界视图。您需要考虑视口的纵横比(宽度:高度)。我试图在这里解释。


1) 作为旁注,FAQ 相当陈旧,指的是 OpenGL 的古老版本。如今,人们期望并鼓励程序员自己管理模型视图和投影矩阵,因为您需要在着色器中使用它们。我强烈推荐glm,它只是标题,因此非常容易集成,并且具有反映 GLSL 的漂亮语法。

于 2013-06-09T13:34:29.007 回答
2

在投影矩阵上使用glOrtho,然后正常绘制。对于你的例子,我猜你想要 glOrtho(0, 1000, 0, 3000, -1, 1) 这会给你一个宽度为 1000 单位和高度为 3000 单位的视口

于 2013-04-21T11:43:04.023 回答
0

将您的场景放置在您想要的任何坐标系中。我建议使用 glm ( http://glm.g-truc.net/ ) 来初始化矩阵和执行数学运算等。所以你可能有一个场景图引擎,你可以在其中管理 2D/3D 世界中的所有对象。只需在 glm 中正确设置视图和投影。实际上,您不应该需要任何图形管道实现细节——因此您的游戏引擎中可能存在错误的设计决策。

于 2013-05-13T17:56:40.833 回答