OpenGL:调整显示大小和glOrtho / glViewport


16

我已经从多个来源研究了这个问题,但还没有找到一个明确的答案,说“是的,这是正确的想法”或“否,这是怎么做的”。

我正在尝试确保OpenGL渲染的分辨率独立性。我认为应该采用的方法是使用glOrtho我想要的世界坐标系来创建投影。例如,glOrtho(-50.0, 50.0, -50.0, 50.0, 1.0, -1.0)。接下来,将视口设置为屏幕分辨率,即- glViewport(0, 0, 800, 600)。最后,每当调整窗口大小时,以glViewport更新的屏幕分辨率进行调用。这将扩展您的数字。

这是确保模型在不同分辨率下占据相同比例的屏幕空间的正确方法吗?我是否也应该使用与分辨率相等的投影?我发现一些答案说glOrtho应该使用窗口的分辨率,而其他人则说应该/可以不同。

有什么想法吗?

Answers:


20

您所描述的完全足够且适当地提供了分辨率独立性。实际上,您绘制的任何东西都将始终占据窗口的相同比例。

但是,如果您仅执行此操作,将出现纵横比问题。例如,给定您所输入的数字,如果您画一个圆,它将被挤压-宽于高,因为水平比例为800 /(50 + 50)= 8而垂直比例为600 /(50+ 50)= 6。

没有任何自动解决这个问题的方法 ; 您将必须选择所需的图形结果,并考虑其对游戏玩法的影响。一些常见的例子:

  • 在没有HUD的透视投影3D游戏中,通常的简单解决方案(在OpenGL中可用gluPerspective)是相对于垂直尺寸固定投影的视场。这意味着在这样的游戏中,如果您水平调整窗口大小,将看到或多或少的场景,并且图像的中间部分完全不会改变。

    同样的想法也可以应用于2D / 2.5D视图。

    (请注意,这允许玩家通过制作宽阔但不高的窗口来水平扩大视野。这在竞争性多人游戏中可能是不需要的。)

  • 如果您的视口填充图形具有固定的宽高比(例如,非滚动2D地图或装饰性边框),或者如果您无法更改布局,则必须执行以下操作:在两个填充未使用的空间。

    或者,您可以制作图形,这些图形的边缘具有主题一致的填充材料,可以对其进行裁剪以适合显示效果而不会损害游戏性。

  • 如果在其他图形之上有HUD,则可以确定每个HUD元素都固定在窗口的一部分(左上角,底部中心等)并计算其坐标;HUD元素之间的“空白”吸收了宽高比不同的“拉伸”。

关于此事的特定数学,假设您要进行分辨率独立性测试,那么您需要开始的只是长宽比,一个数字:width / height。例如,如果窗口是正方形,它将为1;否则,窗口将为1。如果是800 x 600,则为800/600 = 4/3 =1.333̅。

例如,假设您希望编写的正投影在窗口扩大时在左侧和右侧获得更多空间。您可以这样做:

float aspect = width / height;
glViewport(0, 0, width, height);
glOrtho(-50.0 * aspect, 50.0 * aspect, -50.0, 50.0, 1.0, -1.0);

这样可以保证,对于至少与它们一样高的窗户,您在x和y坐标范围为-50到50之间绘制的任何内容都是可见的。

另一方面,如果窗口窄于高,则-50至50的范围将被切除。假设您要确保它始终可见(如果窗口为正方形,则内容为最大尺寸,否则为较小尺寸);在这种情况下,您只需要对高度而不是宽度做同样的事情。

float aspect = width / height;
glViewport(0, 0, width, height);
if (aspect >= 1.0)
  glOrtho(-50.0 * aspect, 50.0 * aspect, -50.0, 50.0, 1.0, -1.0);
else
  glOrtho(-50.0, 50.0, -50.0 / aspect, 50.0 / aspect, 1.0, -1.0);

请注意,在第二种情况下,我们除而不是乘。这仅仅是因为我们将宽高比计算为width / height而不是height / width; 如果您更容易理解这种方式,请采取互惠的态度。

同样,这不是管理长宽比的唯一方法;这只是确保您的内容不被压缩或切断的非常简单的方式。弄清楚当您的窗户变宽,太高或任何其他形状想要发生什么。然后算出它的数学。


感谢您非常有见地的回复。超出了我的回答范围。
克里斯·亨德森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.