在 Linux 上进行 OpenGL 编程

作者:Vincent S. Cojot

本文并非旨在成为 OpenGL 教程或入门指南。有许多人在这个领域比我更有能力,他们已经撰写了许多关于这个主题的文章甚至书籍。此外,即使本文中讨论的项目主要是使用 Xinside 的 OpenGL 编写和构建的,我也无意讨论任何 Linux OpenGL 端口或实现相对于其他端口或实现的优越性。本文讲述了一个关于使用 Linux 的有趣故事,我认为值得为 Linux 社区做出贡献。

简介

“因此,”教授总结道,“这个学期,我们将开始一些新的东西,而不是致力于完善我们自制的光线追踪器——我们已经为此努力多年了。你们将必须使用 OpenGL 构建一个 3D、支持网络的坦克游戏。你们将组成两到三名学生的团队。为此,你们将使用我们这里的 RS/6000 工作站,我们将向你们介绍 OpenGL。”

我的耳朵!他们简直不敢相信我刚刚听到的。作为蒙特利尔理工学院计算机工程专业的学生,以及对光线追踪有良好背景的计算机图形学爱好者,我多年来一直期待着在学业上取得足够的进步,以便能够参加高级计算机图形学课程。那个学期我终于能够参加这门难度很大的四年级课程,但我刚刚听到,令我非常失望的是,我必须使用 OpenGL,而不是使用光线追踪器并制作高质量的光线追踪图片。我的士气不高,恐惧感涌上心头,因为我意识到我对 OpenGL 的了解远不如对光线追踪的了解。但正如一位 LinuxDoom 爱好者所说:“仅仅依靠我的 Linux 电脑和我的 OpenGL Beta 产品,我便投入到充满敌意的 GL 内在函数中,准备用我拥有的每一根 GLfloat 变量战斗到底。”

什么是 OpenGL?

更严肃地说,OpenGL 是一个图形库,从一开始就被设计为一个硬件无关的接口,以便在许多不同的平台上实现。它使用类似于 X 客户端-服务器端方法的客户端-服务器端方法,在选定的窗口系统上提供图形图元的显示。服务器向客户端发送命令,客户端显示这些命令。

在支持 X 的 Unix 工作站上,OpenGL 具有 X 服务器的扩展,名为 GLX。您可以在一台计算机上运行您的 OpenGL 程序,并在另一台计算机上显示它,但这要求服务器机器具有所需的 OpenGL 库,并且客户端具有 GLX 扩展。由于这两个软件包通常一起提供,这意味着服务器和客户端都必须是“支持 OpenGL 的”。

简而言之,OpenGL 能够显示简单的几何对象,显示正交和透视投影,执行背面剔除,进行着色和抗锯齿,以及将纹理应用于对象。如果您想做一些复杂的事情——比如显示汽车或飞机——您必须自己构建这些对象,并使用 OpenGL 以您喜欢的方式渲染它们。

据我所知,在 Linux 上,您可以选择几种商业实现和一个免费实现

  • Xinside 和 Metrolink 的 Linux OpenGL 端口,每个端口都要求您安装自己的 X 服务器以提供 GLX 扩展和通常更高的性能。

  • Portable Graphics,其产品直接在 XFree86 上运行。

  • Brian Paul 的 Mesa 库,它是 GPL 许可的并且免费提供,但没有 GLX 扩展。它令人印象深刻且价格合理。

我的个人经验是,我正在使用的产品(Xinside 的 OpenGL 第二个 beta 版,以及后来的最终产品,速度甚至更快)质量非常高。它比 Mesa 更快且更兼容。谈论在免费操作系统上运行的商业应用程序是一个敏感且棘手的问题,尤其是当存在免费提供的等效产品(Mesa)时,甚至当您发现自己对商业工具非常(或至少更)满意时更是如此。我发现 Mesa 是一款令人印象深刻的软件,但 Xinside 的 OpenGL beta 版明显更快且更兼容 OpenGL,因为它是一个真正的 OpenGL 实现。

回到心爱的 Linux 电脑

所以,几天后,我坐在 RS/6000 工作站前,写下了即将到来的坦克游戏的前几行代码,并想知道它是否会在我的 Linux 电脑上运行。您看,几个月前,我订阅了 Xinside 的 OpenGL beta 计划,目的是从我的 Linux 电脑远程运行 OpenInventor,因此,我发现自己拥有一台支持 OpenGL 的 Linux 计算机。当天晚些时候,我回了家——而我的 Linux 电脑正在通过 FTP 检索示例代码——并准备在 Linux 下编译它。

我们正在构建的项目使用的是一个名为 libaux 的免费辅助库。“很好,”我想,我从 RS/6000 实验室通过 FTP 下载了它的源代码,并在我的 Linux 电脑上编译了它。它也可以从 ftp.sgi.com 的 OpenGL 子目录中获得,以及 OpenGL 编程指南中的所有示例。带着很大的希望和越来越兴奋的心情,我准备启动示例代码,然后...它崩溃了,生成了一个 panic 文件并杀死了 X 服务器。

团队后来发现,这个问题是由我使用的 Beta OpenGL 版本中的一个小错误引起的,该错误导致它在使用颜色索引颜色模式和单缓冲时行为异常。然而,当我切换到使用 RGBA(红色、绿色、蓝色和 Alpha)颜色模式后,程序运行正常——它甚至比我们使用的旧 RS/6000 工作站运行得稍快一些!

诚然,这些 RS/6000 是基本的入门级工作站,它们的年代(大约两年)加上较差的 3D 硬件加速显卡,证明它们根本不是我的配备 Matrox Millennium 的 P133 的对手(尽管 Linux 上的 OpenGL 仅提供软件 3D 加速)。对于一个曾经习惯于“这种热门的东西在工作站上运行——工-作-站——甚至不要想在你的家用 PC 上运行它!”的人来说,这种 Linux 上的 OpenGL 体验就像梦想成真。

移植还是不移植,这不是问题

日子一天天过去,我们开始将越来越多的代码集成到项目中。我的团队成员比我更多的课程作业,所以我发现自己领导着团队——在项目的第一部分编写了大部分代码,并在第二部分和第三部分编写了全部代码。当然,我都是在 Linux 上编写的——但总是稍后验证它是否在 RS/6000 工作站上运行(墨菲定律,你知道的?)。

当然,这并没有被忽视,班上的一些学生开始探索在家中使用 NT 或那个名字带有过期日期的操作系统(Windows 95)在他们的 PC 上构建和开发他们自己的项目的方法。其他人听从了我的建议,即最好使用 Unix,因为存在可移植性问题(我当时认为...或者预想...或者想象...Win32 API 可能与大多数 Unix 的 API 非常不同),并让 Mesa 运行起来了。毕竟,如果您有选择,并且可以在家做与在大学做相同的事情,您是愿意在寒冷的计算机实验室里坐在没有扶手的木椅上熬夜,还是愿意在您的家用电脑上工作?

就在几周后,当我们被要求在游戏中实现和使用计时器时,问题开始出现。这对 NT/95 用户来说是第一次打击,因为除非您熟悉 Windows API 或有一些示例源代码,否则将 Unix 的 gettimeofday() 更改为 Windows API 调用并非易事。毕竟,如果您的虚拟坦克以 10 米/秒的速度行驶,那么无论您拥有什么硬件,无论是 16 CPU 的 SGI 工作站还是性能较差的 80486,它都应该以这个速度行驶。有些人厌倦了在他们的代码中放置 #ifdef#ifndef,并决定改为在实验室熬夜。

然后是网络守护进程。这个想法(主要是在我的建议下)是在特定工作站上运行的游戏客户端会在初始化时 fork() 一个守护进程。守护进程将与客户端共享一个或多个内存段,并且任务是在特定端口上侦听其他可能的网络玩家发送的广播消息。不用说,这些 Unix 内在函数标志着 Windows 移植的结束;即使您可以在 Win32 上运行 3D 引擎的一部分,您仍然必须在学校的 RS/6000 工作站上完成所有网络和最终调试。

但在所有这些时间里,至少有一位快乐的 Linux 用户在将代码从他的家用 Linux 电脑发送到 Risc 工作站时没有更改一行代码。他唯一一次真正需要放置 #ifdef 是当 Pentium 和 RS/6000 处理器之间的字节序差异开始在他加载和用于纹理的 TARGA 文件的字节顺序中显示出来时。甚至有传言说,他在没有实际进入计算机实验室的情况下调试了他的网络代码:在深夜,他使用了两台工作站来运行他的程序,并将显示导出到他的 Linux 电脑(虽然速度很慢,但功能足够强大,可以追踪一些错误)。

性能:硬件和软件

对于我们这些在家或工作时不使用中高端 SGI 工作站的人来说,谈论 OpenGL 的性能与谈论 OpenGL 本身几乎同样重要。在我们的案例中,大约在学期中期,教授和学生都清楚地意识到,我们使用的 RS/6000 工作站对于我们用它们做的事情来说不够快。

最终我们切换到了另一个属于机械工程系的 RS/6000 工作站实验室。那里的人们运行 CATIA——就像 AutoCad,但功能和内存要求是其十倍。这些工作站本质上仍然没有配备足够 RAM 的优秀 Linux Pentium PC 快;大多数测试,gcc、xv 等都表明我的 P133 在执行通用操作时速度大约快 50-60%。但它们的硬件加速 OpenGL 图形允许我的游戏在它们上面以每秒 25 帧的速度和 512x384 像素的分辨率运行。相比之下,在我的 Linux 电脑上,我最多只能获得每秒 9-10 帧的速度和 320x240 像素的分辨率,其中 OpenGL 渲染仅由主 CPU 和 FPU 上的软件完成。

程序仍然运行,并且速度足够快,让我能够解决大部分错误并实现新功能,但如果我使用的 Linux OpenGL 端口能够利用我的显卡上的 3D 功能使我的程序运行得更快,我个人会更喜欢它。在我这边,我尝试从游戏的主循环中删除尽可能多的未优化内容,以使其在所有平台上尽可能快地运行。

以下是关于项目的一些统计数据

  • 代码行数:约 7600 行(游戏和守护进程)+ 900 行(爆炸渲染器)

  • 纹理和光线追踪渲染爆炸的数量:34

  • 使用的不同对象列表的数量:38

  • 可能的网络玩家或自动对手的数量:20

  • 仅在 Linux 上可用的功能:基本声音!

  • 花在那个游戏上抓狂的时间:约 200-250 人时

结论

对于我们课程中的所有工作组来说,该项目现在已经完成,因为它涉及到学生从事编程项目,其结果将由教授评估。我几乎独自完成了最终“产品”,并且比所有其他团队提前大约一周。最终,我们的游戏客户端可能拥有最多的功能、最复杂的图形、最漂亮的爆炸效果和最可靠的运动引擎——并且我们在教授的最终评估中获得了尽可能高的分数。在某种程度上,我认为如果我不能在我的家用 Linux 机器上运行所有东西,并在我想做的任何时间和任何方式做所有事情,我可能不会达到这个成就水平。

除了表明一些计算机工程专业的学生在他们的家用机器上比在您可以让他们访问的大多数计算机上效率更高之外,这个有点非凡的冒险经历表明,一些领域——直到现在,这些领域还保留给高端工作站——可以使用像好的 Linux 电脑和一些相关软件这样简单的东西来探索。

未来方向

更新:2006年11月29日

如果您想查看与本文相关的图片和代码,请访问此链接:www.step.polymtl.ca/~coyote/graphics_tank.html

Vincent Cojot 是蒙特利尔理工学院计算机工程专业的学生。他喜欢计算机图形学、Xview/OL 编程(当然是在 Linux 下)和微缩模型绘画。

加载 Disqus 评论