前言
本书的主要写作目标是为计算机科学专业本科OpenGL 3D图形编程相关课程提供合格的教材。同时,我们也付出了很大的努力,让本书成为一本无须配合课程使用的自学教材。在以这两者为目标的前提下,本书尽力将内容解释得简单而清晰。本书中的所有代码示例都已经尽可能地在保证完整性的同时进行了简化,以便读者直接运行。
我们期望本书与众不同的一点是对初学者(刚接触3D图形编程的读者)友好。关于3D图形编程这个主题的学习资料从来都不匮乏,恰恰相反,很多初学者刚入门的时候,相关的资料就扑面而来,令人不知所措。作者在刚接触3D图形编程的时候,期望能遇见这样的教材:一步步解释基础概念,循序渐进并有序地梳理进阶概念,因此作者也尝试将本书编写成这样的教材。作者曾想将本书命名为“轻松学习着色器编程”,虽然我们并不认为有什么方法能真的让着色器编程变得“轻松”,但我们希望本书能够帮助读者尽可能地达成这个目标。
本书使用C++进行OpenGL编程教学。使用C++学习图形编程有以下好处。
- 由于OpenGL的原生语言是C,因此C++程序可以直接进行OpenGL函数调用。
- C++编写的OpenGL应用程序通常有着很好的性能。
- C++提供C语言所没有的现代编程结构(类、多态等)。
- OpenGL社区中,C++是个热门选项,许多OpenGL的教学资源都有C++版本。
值得一提的是,OpenGL也存在着其他语言绑定,常见的有Java、C#、Python,以及其他许多语言。但本书仅关注C++。
本书与众不同的另一点是它有一个Java版,英文书名是Computer Graphics Programming in OpenGL with Java, 2nd Edition。这两本书是按同样的节奏组织的,使用相同的章节编号、主题、图表、习题和讲解方式,也尽可能以相似的方式组织代码。诚然,使用C++或Java编程肯定有着相当大的差异(不过书中着色器代码完全一致)。尽管如此,我们仍然相信这两本书提供了几乎相同的学习路径,甚至可以让选修同一门课程的学生使用。
需要着重澄清的一点是,OpenGL有着不同的版本(稍后简述)和不同的变体。例如:在标准OpenGL(也称桌面OpenGL)之外,还有一个变体叫作OpenGL ES,是为嵌入式系统(Embedded System)的开发而定制的(因此称为“ES”)。“嵌入式系统”包括手机、游戏主机、汽车和工业控制系统之类的设备。OpenGL ES大部分内容是标准OpenGL的子集,删除了嵌入式系统通常用不到的很多操作。OpenGL ES还增加了一些功能,通常是特定目标环境下的特定功能。本书侧重于介绍标准OpenGL。
OpenGL的另一个变体称为WebGL。WebGL基于OpenGL ES,它的设计目标是支持在浏览器中运行OpenGL。WebGL允许应用程序通过JavaScript[1]进行OpenGL ES操作调用,从而简单地将OpenGL图形嵌入标准HTML(Web)文档中。大多数现代Web浏览器都支持WebGL,包括Apple Safari、Google Chrome、Microsoft Edge、Microsoft Internet Explorer、Mozilla Firefox和Opera。由于Web编程超出了本书的范围,因此本书不会涵盖WebGL。不过,由于WebGL基于OpenGL ES,而OpenGL ES又基于标准OpenGL,因此本书涵盖的大部分内容都可以直接迁移到这些OpenGL变体中去。
3D图形编程这个主题通常让人想起精美而宏大的画面。事实上,许多相关热门教材中充满了令人惊叹的场景,吸引着读者翻阅它们的图库。虽然我们认同这些图像的激励作用,但我们的目标是教学而非令人惊叹。本书中的图像仅仅是示例程序的输出。由于本书只是入门教程,因此其渲染的场景大概无法让专家心动。然而,本书呈现的技术确实是构成当今这些炫目3D效果的基础。
本书并没有尝试成为一本“OpenGL参考大全”,所涵盖的OpenGL部分只是其所有功能中的一小部分。本书的目标是以OpenGL作为基础工具,教授基于现代着色器的3D图形编程,并为读者提供足够深入的理解,以供读者自行进行进一步的研究。
新版内容
本书在第1版的基础上新增了3章。
- 第15章:模拟水面。
- 第16章:光线追踪和计算着色器。
- 第17章:3D眼镜和VR头显的立体视觉。
在过去多年的教学中,学生们对于水的模拟表现出了极大的兴趣。但是,由于水的形态繁多,在入门教材中加入这样一章很困难。最终,我们决定用辅助本书其他章节内容的形式加入与水相关的内容。在第15章中,我们主要介绍了如何使用第14章中所介绍的噪声图,生成像湖面或海面的水面。
光线追踪(ray tracing)这个主题最近变得很热门,因此我们涵盖了这部分内容。同时光线追踪也是一个很庞大的话题,虽然本书只涵盖了一些基础介绍,但第16章依然是书中篇幅最大的一章。第16章同时也涵盖了OpenGL 4.3所引入的计算着色器(compute shader)的介绍,并在展开14.2节中的话题时介绍了加法混色和减法混色。
3D眼镜和VR头显的立体视觉(stereoscopy)相关内容的加入是因为虚拟现实的日益流行。当然,这些知识同样可以应用于开发“3D电影”中的动画。同时,我们在第 17 章中尝试对这两种应用情景以同样权重进行涵盖。
由于新加了以上内容,本书篇幅比第1版要长一些。
除了新的内容之外,本书还有很多重要的修正。如修复了第6章中的Torus类的代码缺陷并优化了第14章中的噪声图代码,对Utils.cpp类进行了扩展以处理计算着色器的加载,为SOIL2库找到了一个会影响macOS用户加载立方体贴图的代码缺陷(现已修复)。
书中还有很多读者可能注意不到的小改动散布于各章中:改正错别字、整理代码、更新安装指引、微小的措辞修改、整理图表、更新引用等。在一本讲述快速进化的技术话题的书中完全消灭错别字几乎是一件不可能的任务,但我们对此倾尽了全力。
目标读者
本书的目标读者是计算机科学专业的学生(可以是本科生),但其实任何想要学习计算机科学相关知识的人都适合阅读本书。因此,我们假设读者有扎实的面向对象编程基础,至少有相当于计算机科学专业大二或大三学生的水平。
本书中未涵盖如下内容,因为我们假设读者已经有足够的背景知识。
- C++和其常用库,如标准模板库(standard template library)。
- 集成开发环境(Integrated Development Environment,IDE),如Visual Studio。
- 事件驱动编程。
- 基础的数据结构和算法知识,如链表、栈、队列等。
- 递归。
- 基础矩阵代数、三角函数。
- 颜色模型,如RGB、RGBA等。
希望本书的潜在受众能够因对Java版的喜爱而进一步支持本书。正如前面所说的,我们期望看到这样一种情景——学生在同一门课中可以自由选择使用C++版教材或Java版教材。这两本教材按照同样的节奏对教学内容进行组织编排,这种模式已经在图形学编程的课程实践中获得了成功。
如何使用本书
本书内容安排上适合从前往后阅读,即对后面章节中知识的学习经常依赖于前面章节中所讲的内容。我们不推荐在各章节中来回跳跃地选择性阅读,读者最好逐章阅读。
同时,本书也希望成为一本实用的动手指南。由于已经有许多其他偏理论的学习材料,读者应该将本书作为一本“练习册”,通过一边参考本书一边自己动手编程来学习和理解基础概念。虽然我们为所有的示例提供了代码,但是想要真正学会这些概念,还是得自己动手“实现”这些代码——通过编程来搭建自己的3D场景。
本书第2章~第14章留给读者一些习题,其中有的题目比较简单,仅仅需要对提供的代码进行简单的改动就可以解决。而那些标记为“项目”的习题需要读者花更多的时间来解决,因为可能需要编写大量代码或者使用多个示例中用到的技术。少数标记为“研究”的习题则会用到在本书中并没有提供的知识细节,我们鼓励读者自主学习并解答。
OpenGL中的函数调用通常会有很长的参数列表。我们在撰写本书时曾多次讨论是否要描述所有参数,最终决定在前面的章节中详细讲解函数的所有参数。随着主题深入,本书会避免在每次OpenGL调用(因为调用次数很多)中过分描述细枝末节,以防读者失去对全局的理解。因此,在浏览示例时,读者需要准备OpenGL和所使用的各种库的参考资料。
为此,我们建议结合一些优秀的在线资源使用本书。OpenGL的官方文档是绝对必要的,它涵盖了有关各种命令的详细信息。可以利用搜索引擎,或访问OpenGL的官方网站获取帮助。
本书示例使用了名为GLM的数学库。安装GLM(见附录)后,读者应找到其官方在线文档并将其加入浏览器书签。
本书经常用到的另一个库是SOIL2,用于读取以及处理纹理图像文件,读者可能也时常需要查阅它的文档。虽然SOIL2没有中心化的文档资源,但通过搜索可以找到一些例子。
还有许多关于3D图形编程的图书,建议与本书并行阅读(例如在解决各章最后的“研究”习题时翻阅)。以下是本书中经常提到的5本图书。
- Sellers等著《OpenGL超级宝典(第7版)》[SW15]。
- Kessenich等著《OpenGL编程指南(原书第9版)》(“红书”)[KS16]。
- Wolff著OpenGL 4 Shading Language Cookbook[WO18]。
Angel和Shreiner著《交互式计算机图形学:基于WebGL的自顶向下方法(第七版)》[AS14]。
Luna著,王陈译《DirectX 12 3D游戏开发实战》[LU16]。
配套资源
本书提供随书的配套资源,其内容有:
- C++/OpenGL程序代码、相关的实用类文件代码和GLSL着色器的代码;
- 各种程序和示例中使用的模型和纹理文件;
- 用于制作天空和地平线的天空顶和立方体贴图图像文件;
- 用于照明和呈现物体表面细节效果的法线贴图和高度贴图;
- 本书中所有的图表(以图像文件形式提供)。
上述资源可以通过访问异步社区(www.epubit.com)的本书页面获取。
教师辅助
我们鼓励教师获取本书的教学辅助资料,其中包含以下附加项(以英文提供):
- 一套完整的教学幻灯片,涵盖本书中的所有主题;
- 本书中大多数章末习题的答案及所需代码;
- 基于本书的课程大纲示例;
- 每章用于讲解材料的额外内容。
教师辅助包获取方式请联系contact@epubit.com.cn。
致谢
本书中的许多内容都基于Java版教材——Computer Graphics Programming in OpenGL and Java,它是作者于2016年为加利福尼亚州立大学萨克拉门托分校的CSc-155(高级计算机图形编程)课程编写的教材。当年许多学习CSc-155课程的学生都主动对早期的草稿给出了修改建议,并帮助修复了相关程序中的代码缺陷。要特别感谢Mitchell Brannan、Tiffany Chiapuzio-Wong、Samson Chua、Anthony Doan、Kian Faroughi、Cody Jackson、John Johnston、Zeeshan Khaliq、Raymond Rivera、Oscar Solorzano、Darren Takemoto、Jon Tinney、James Womack、Victor Zepeda的建议。在接下来的几年中,我们的同事Pinar Muyan-Ozcelik博士开始在她的CSc-155课程教学中使用Java版,并持续记录了每章中所遇到的问题以及需要更正的内容,最终为Java版的第2版以及C++版的第1版提供了许多改进意见。
2020年春天,作者在CSc-155课程中测试了让学生自由选择使用C++或Java并使用对应版本教材进行学习的计划。作者以此测试在一门课程中同时使用C++版和Java版教材,其结果令人很满意。同时,学生们也发现了书中的一些错误——Paul McHugh发现并修复了3D纹理代码中的一个重大内存泄露问题。
同时我们也从全世界使用本书作为课程教材的教师、专业人士以及爱好者群体中持续收到了很棒的反馈——在这里要感谢Mauricio Papa博士(University of Tulsa)、Dan Asimov(NASA Ames)、Sean McCrory、Michael Hiatt、Scott Anderson、Reydalto Hernandez、Bill Crupi等人。
Alan Mills博士在2020年年初开始教授课程之后,从浏览Java版时整理的笔记中,发给我们超过200条建议和修正意见。其中大约一半建议和修正意见同样适用于C++版。在他的诸多发现中,有一个条目是对环形模型中纹理坐标的重大修正。Alan对细节的关注令人赞叹,我们非常感谢他为本书所做的工作,他的工作对本书产生了积极的影响。
Jay Turberville来自亚利桑那州Scottsdale的Studio 522 Productions。他创建了封面以及书中所有的海豚模型,学生们非常喜欢。Studio 522 Productions制作了高质量的3D动画和视频,以及自定义3D建模。我们很高兴Turberville先生慷慨地为本书建立这个精美的模型。
Martín Lucas Golini,作为SOIL2纹理图像处理库的开发者和维护者,也对本书付出了极大的支持和热情,一直快速回应我们提出的相关问题。我们对他的帮助表示感谢。
我们还要感谢其他一些艺术家和研究人员,他们非常慷慨地让我们使用他们的模型和纹理。 来自Planet Pixel Emporium的James Hastings-Trew提供了许多行星表面纹理。Paul Bourke允许我们使用他所拥有的精彩的星域。斯坦福大学的Marc Levoy博士授权我们使用著名的“斯坦福龙”模型。Paul Baker的凹凸贴图教程是我们在许多例子中使用的“环面”模型的基础。我们还要感谢Mercury Learning允许我们使用[LU16]中的一些纹理。
已逝的Danny Kopec博士向我们介绍了Mercury Learning公司,并向其出版人David Pallai引荐了我们。作为象棋爱好者的Gordon博士(本书作者之一)最早熟悉Kopec博士是因为其国际象棋大师、国际象棋畅销书作者的身份。Kopec博士同时也是一名计算机科学家,他编写的教科书Artificial Intelligence in the 21st Century[《人工智能(第2版)》,人民邮电出版社,ISBN:9787115488435]让我们考虑通过Mercury Learning出版图书,我们在与Kopec博士的几次通话中获得了很多信息。Kopec博士于2016年早逝,我们深感悲痛,也对他没有机会看到他所启动的项目取得的成果而感到遗憾。
最后,我们要感谢Mercury Learning的David Pallai和Jennifer Blaney。感谢他们对这个项目持续的热情和支持,以及引导我们完成了本书的整个出版流程。
参考资料
[AS14] E. Angel and D. Shreiner, Interactive Computer Graphics: A Top-Down Approach with WebGL, 7th ed. (Pearson, 2014).
[KS16] J. Kessenich, G. Sellers, and D. Shreiner, OpenGL Programming Guide: The Official Guide to Learning OpenGL, Version 4.5 with SPIR-V, 9th ed. (AddisonWesley, 2016).
[LU16] F. Luna, Introduction to 3D Game Programming with DirectX 12, 2nd ed. (Mercury Learning, 2016).
[SW15] G. Sellers, R. Wright Jr., and N. Haemel, OpenGL SuperBible: Comprehensive Tutorial and Reference, 7th ed. (Addison-Wesley, 2015).
[WO18] D. Wolff, OpenGL 4 Shading Language Cookbook, 3rd ed. (Packt Publishing, 2018).
[1] JavaScript 是一门脚本语言,其代码可以嵌入网页中运行。它与Java 有一定的相似性,但同时在很多重要的方面也有区别。