《图形着色器:理论与实践(第2版)》详细阐述了与着色器程序设计相关的高效解决方案及相应的数据结构和算法,主要包括固定功能管线、OpenG着色器的发展、着色器基本概念、使用glman、GLSL着色器语言、光照、顶点着色器、片元着色器和表面外观、片元着色器中的表面纹理、噪声、基于着色器的图像处理、几何着色器的概念和示例、细分着色器、GLSLAPI、基于着色器的科学可视化计算以及着色器应用等内容。此外,《图形着色器:理论与实践(第2版)》还提供了相应的算法、代码以及伪代码,以帮助读者进一步理解相关方案的实现过程。
下面的漫画作品是否唤起了你的某些回忆?
你的脑海中是否萦绕着许多伟大、创新的理念却苦于无法实现?那么,你就是我们正在寻找的人,本书专门为你而打造。
欢迎阅读《图形着色器 ——理论与实践(第 2版)》。顾名思义,本书将讨论着色器理论以及实践过程,并辅以大量的实现代码。为了方便读者阅读,本书采用全彩印刷,亦即多数示例均配以效果图像,以便于读者深入理解相关概念。因此,放慢你的脚步,静下心来开始阅读,并从中获得极大的享受吧!
与第 1版相比,本书增加了 100多幅图像。除此之外,本书还对以下内容进行了改版:
(1)本书遵循 OpenGL最新规范,即 OpenGL 4.x和GLSL 4.x0。
(2)全部示例代码根据最新 GLSL语言标准加以编写。
(3)新增了与细分着色器相关的部分章节(及其示例代码)。
(4)各章增加了示例和练习。
(5)修改了大量的示意图,并将 GLSL功能级别调整至 4.x0。
(6)OpenGL架构评审委员会( ARB)弃用了 OpenGL中的某些功能,但尚未将其完全去除。本书将对此加以阐述且对应代码集中体现了这一重要变化。另外,本书全部示例代码均遵循这一理念。在该策略的引导下,读者还可向 OpenGL ES 2.0实现平稳过渡。
(7)本书附录添加了与着色器对应的 C++类,进而简化 OpenGL着色器应用程序的编写过程,并对上述弃用策略提供某种支持。
可编程图形着色器经历了一段有趣的发展历程。在以往的岁月中,计算机图形内容均需要通过编程实现,相信某些读者对此仍有清晰的记忆。鉴于图像创建过程中存在可编程选项,这也意味着 “可编程 ”往往包含某种贬义成分 ——事实并非如此。若期望生成某种图像结果,除了亲自动手编写程序之外,别无他法。
对于大多数图形实践者而言,计算机图形 API可在一定程度上改变这一现状。优秀的 API使得程序设计人员可轻松并出色地完成图形程序设计任务,期间, API功能项可掌控大部分图形处理操作。然而,程序设计人员也为此付出了一定的代价,即放弃 API无法处理的某些功能项,如表面着色技术。当时( 20世纪 90年代),大多数 API仅支持简单的平滑光照表面操作。
然而,无论是计算机图形开发社区还是高级图形程序员,对此都难以感到满意,这种满意度的欠缺分别来自软件和硬件方面。随着图形处理器的不断发展,基于特定功能的程序设计逐渐打破固定功能图形 API这一桎梏,此类功能项逐渐形成自己的标准,包括隶属于 OpenGL标准的 GLSL着色器语言。可编程图形着色器已成为计算机图形学的关键特征,其中,程序可载入图形处理器,并执行早期固定功能管线标准之外的相关操作。
在教学以及学习过程中,计算机图形学也可采用并行方式实现。初学者通常会通过相关标准(如 OpenGL)了解计算机图形学。当前,初学者还应理解可编程着色器所饰演的角色,并尝试编写和使用着色器。值得注意的是,基于着色器的程序设计往往会使我们重返昔日时光,并重新审视某些古老的图形学问题(例如,某些问题出现于 20世纪 70年代)。时至今日,读者可在 OpenGL的全力支持下实现顶点和独立像素操作,这种体验往往来自于游戏、科学可视化计算以及通用图形计算。
本书可用于传统的教学课程中,其内容自成一体,向学生全面阐述了计算机图形学着色器程序设计。同时,本书还可作为基于固定功能 API(尤其是 OpenGL)的辅助读物。本书从整体上系统地讲述了着色器程序设计,并重点讲解了 GLSL着色器语言。除此之外,本书还介绍了灵活、易用的编程工具 glman,以帮助读者在应用程序外部开发、调试着色器。
本书可作为本科、研究生层次计算机图形学课程的高级教程,并假设读者已了解 OpenGL以及相关图形学知识。本书重点讨论 GLSL语言并统一使用 OpenGL术语,对应内容同样适用于其他图形 API,如 Direct3D。鉴于着色器程序设计揭示了 API所隐藏的事实真相,因而读者需要进一步了解某些基础理论,包括几何、光照以及着色等内容,相信读者会加深对此类问题的理解。同时,着色器程序设计还会帮助读者剖析 API的工作原理,因而有必要对上述内容加以回顾。
本书采用 GLSL作为示例着色器,其原因在于, OpenGL跨平台 API具有较为广泛的应用范围且兼具高效性。鉴于着色器理念之间的相似性,相关概念同样适用于其他着色器 API,如 Cg和HLSL。本书首先通过着色器程序的基本角色和功能介绍固定功能图形管线,随后将在 glman和应用程序环境下编写顶点着色器、片元着色器和几何着色器。
尽管按照扩展图形管线中的应用顺序考察着色器更符合逻辑性,即顶点着色器 —几何着色器 —片元着色器,但本书的处理方案则稍显不同,即按照使用频率这一顺序考察着色器(片元着色器 —顶点着色器 —几何着色器)。需要说明的是,该顺序无法实现正确的工作流,其原因在于,片元着色器所接收的数据源自顶点着色器,因而顶点着色器位于初始位置,随后依次为片元着色器、几何着色器和细分着色器。
本书整体内容脉络鲜明,第 1章涵盖了后续章节所需要的背景知识,即基于固定功能的 OpenGL图形管线。第 2章讲述了 OpenGL的演化历史。第 3章讲解了顶点着色器、片元着色器和细分着色器的基本原理,以及基于 GLSL着色器语言的多个示例。第 4章以使用手册方式引入了 glman软件。第 5章讨论了 GLSL着色器语言,并针对 C语言比较了两者间的相似性和差异性。
第6~8章涉及顶点着色器和片元着色器等概念。其中,第 6章阐述着色器的视点光照,并引入了
ADS(环境光、漫反射光和镜面光)光照函数,此类光照环境将在后续章节中多次提及。由于顶点着色器需要计算各顶点的光照,片元着色器负责计算各像素的光照,因而光照可视为顶点着色器和片元着色器的基础内容。第 7章将重点探讨顶点着色器,对应内容主要集中于输入数据、输出数据以及顶点几何对象的调整方式。第 8章将讨论片元着色器,包括输入数据、输出数据以及固定功能片元操作的替换方式。
第9~11章将分析片元着色器的特定功能项。第 9章将描述片元着色器与纹理贴图之间的处理方式,包括凹凸贴图、立方体贴图以及场景的纹理渲染。第 10章将阐述噪声函数及其在纹理和着色器中所饰演的角色。除此之外,第 10章还介绍了 noisegraph工具,以使读者可对 1D和2D噪声函数属性进行调试。第 11章则根据片元着色器工具讲述 2D图像(纹理)的操控方式。
第12章讲述了几何着色器,包括几何着色器与顶点着色器和片元着色器之间的关系,以及几何着色器自身的功能项。本章通过多个示例强调几何着色器针对几何模型的扩展能力,以及细节级别的处理能力。第 13章介绍了细分着色器,着重说明该类型着色器与几何着色器之间的相似性以及重大改进。
第14~16章集中讨论应用程序中的图形着色器。第 14章定义了 GLSL API,读者可在应用程序中编译、链接并使用着色器。另外,本章还分析了着色器程序的数据和图形状态信息的传递方式,并使用 C++类封装着色器程序的整合操作。第 15章阐述了着色器在可视化应用程序中的应用方式,并演示了多个可视化操作示例。第 16章则考察了基于图形着色器的多个有趣示例。
附录部分显示了 C++类的应用方案,以方便读者编写 OpenGL应用程序并处理某些 API弃用问题。
本书多数内容均较为直观,部分内容则包含一定的技巧性,因而应引起读者的足够重视。本书中的数学知识源自 Nicholas Bourbaki所著教材,并采用符号加以标识,进而强调该问题的重要性。
由于着色器函数仍处于不断发展中,因而新鲜事物以及对应处理方案层出不穷。相应地,本书采用符号加以标识,希望读者对此有充分的认识。
通过本书的阅读,读者可进一步提升图形编程能力,并尽享图形编程的无限乐趣。 OpenGL前进的步伐从未停止,不久的将来,着色器或许是几何对象以及渲染操作的唯一处理方式,我们有理由相信,读者将会再次认识到本书的价值所在。
致谢
本书的出版得益于多方的支持。这里,首先对 Mike Bailey表达最真挚的谢意。另外,还要感谢俄勒冈州立大学同仁们的支持,他们是 Ron Adams、Bella Bose、Terri Fiez、Karti Mayaram、Ron Metoyer、Eric Mortensen、Cherri Pancake、Sinisa Todorovic以及 Eugene Zhang。
鸣谢 UCSD和OSU的同学们,他们才华横溢并自始至终伴我左右,他们是 Tim Bauer、William Brendel、Guoning Chen、Matt Clothier、John Datuin、Will Dillon、Jonathan Dodge、Chuck Evans、 Nick Gebbie、Kyle Hatcher、Nick Hogle、Chris Janik、Ankit Khare、Vasu Lakshmanan、Adam Leibel、 Jessica McGregor、Daniel Mof.tt、Chris Moore、Patrick Neill、Jonathan Palacios、Nadia Payet、Randy Rauwendaal、Dwayne Robinson、Avneet Sandhu、Nick Schultz、Sudarshanram Shetty、Evon Silvia、 Ian South-Dickinson、Madhu Srinivasan、Michael Tichenor、Christophe Tome、Ben Tribelhorn、Ben Weiss以及 Alex Wiggins。
感谢我的同事 Ryan Bailey教授、 Mike Gannis教授、 Jenny Orr教授、 Todd Shechter教授以及 Justin
——
Spencer教授。同时,还要感谢 NVIDIA公司的鼎力支持,尤其是 Gary Brown、Greg Gritton、Jen-Hsun Huang、
David Kirk、Dave Luebke以及 David Zier。特别感谢来自 AMD/ATI公司的 Bill Licea-Kane。感谢 Randi Rost在3D Labs和Intel工作时给予的支持,感谢他所撰写的 “橘皮书 ”,本书从中受益匪浅。感谢派拉蒙电影公司授权使用本书中的图 2.2。同时,皮克斯动画工作室提供了原始图像,在此
一并表示感谢。感谢 xkcd.com授权使用前言首页处的漫画作品。最后,还要感谢 Alice Peters和Sarah Cutler为本书提供的建议以及所付出的努力;感谢本书的审稿
人员,他们的宝贵意见使得本书内容得到了进一步的完善。
Mike Bailey Corvallis,Oregon
Steve Cunningham Coralville,Iowa
第1章 固定功能管线
传统的视见方案
顶点操作
管线的片元处理
图形管线中的状态
传统视见机制的实现方案
顶点处理操作
渲染处理操作
固定管线中的齐次坐标
顶点数组
本章小结
本章练习
第2章 OpenGL着色器的发展
着色器发展史
OpenGL着色器发展史
OpenGL2.O/GLSLl.10
OpenGL3.x/GLSL3.30
OpenGL4.O/GLSL4.00
OpenGL4.x/GLSL4.x0
内部原因
OpenGLES
处理不同版本
本书方案
变量名命名规则
本章练习
第3章 着色器基本概念
图形管线中的着色器
顶点着色器
片元着色器
细分着色器
几何着色器
GLSL着色器语言
应用程序与着色器之间的数据传递
在应用程序中定义attribute变量
在应用程序中定义uniform变量
GLSL新版本之间的转换方式
本章练习
第4章 glman的使用
使用glman
加载GLIB文件
编辑GLIB文件和着色器文件
生成GLIB场景
窗口和视见操作
转换操作
定义几何对象
定义纹理
定义着色器名
其他命令
定义uniform变量
GLIB文件示例
纹理和噪声
使用纹理
使用噪声纹理
glman界面窗口功能
生成并显示场景的硬拷贝
全局场景转换
眼睛转换
对象拾取和转换
纹理转换
显示帧速率
其他功能项
本章练习
第5章 GLSL着色器语言
着色器语言的成因
图形卡功能项
通用GLSL语言
共享命名空间
函数扩展和操作符功能项
……
第6章 光照
第7章 顶点着色器
第8章 片元着色器和表面外观
第9章 片元着色器中的表面纹理
第10章 噪声
第11章 基于着色器的图像处理
第12章 几何着色器的概念和示例
第13章 细分着色器
第14章 GLSLAPI
第15章 基于着色器的科学可视化计算
第16章 着色器应用
参考文献
附录A 基于GLSL程序的C++类
附录B Matrix4C++类
附录C VecC++类
附录D 顶点数组类