
WebGL 是一项在网页上渲染三维图形的技术,也是HTML5 草案的一部分。 本书的主要篇幅讲解了WebGL 原生API 和三维图形学的基础知识,包括渲染管线、着色器、矩阵变换、着色器编程语言(GLSL ES)等等,也讲解了使用WebGL 渲染三维场景的一般技巧,如光照、阴影、雾化等等。本书提供了丰富的示例程序供读者钻研,也提供了极具价值的附录供读者参考。
赞誉之辞 “WebGL 提供了用以在浏览器中创建‘具有桌面应用体验’的应用的最终特性,而 《WebGL 编程指南》将教会你如何创建这些应用。这本书涵盖了使用WebGL 的方方面 面——JavaScript、OpenGL ES,以及基础的图形学技术——如果你想上手WebGL,这本 书里有你需要的一切。Web 应用是未来的趋势,这本书将让你走在潮流的前端!” ——Dave Shreiner 《OpenGL 编程指南》( 第8 版) 的作者, Addison Wesley 出版社OpenGL 系列丛书编辑 “HTML5 使Web 成为了高度可用的应用平台,使精致优美的Web 应用能够运行在 多种不同的系统中。WebGL 是HTML5 的一个重要组成部分,它允许Web 开发者充分利 用硬件的性能渲染三维图形。WebGL 被设计出来的目的就是为了安全地运行在任何支持 Web 的系统中,这项技术将在三维Web 内容和应用、用户界面等领域引发新一轮的技术 革命。这本书将帮助Web 开发者完全理解WebGL 技术的功能,并牢牢抓住这项技术带 来的机遇。” ——Neil Trevett NVIDIA 移动部门副总裁,Khronos 小组主席 “通过优美的三维渲染和清晰的讲解,这本书将WebGL 这样一个复杂晦涩的问题变 得亲切有趣。不可否认的是,WebGL 确实非常复杂,但这本书已经足够畅达,初学者应 该毫不犹豫地利用它开始学习。” ——Evan Burchard Web Game Developer's Cookbook (Addison Wesley) 的作者 “本书的两位作者都具有深厚的OpenGL 背景,并将此背景恰到好处地用在了 WebGL 上,写出了这本优秀的,即适合新手也适合老鸟的教材。” ——Daniel Heahn 波士顿儿童医院的软件工程师 “《WebGL 编程指南》以一种即直接又通俗易懂的方式,讲解了如何不依赖笨重的函 数库或插件来构建三维应用。对希望了解最前沿的三维Web 开发领域的工程师来说,这 是一本不可多得的好书。” ——Brandon Jones Google 的软件工程师 “这是一部出自杰出科学家之手的伟大作品。Kouichi Matsuda 清晰简洁地向初学者 指明了理解WebGL 所需经历的道路。这是一个复杂的话题,使得每一个刚开始使用这 项新技术的人都能够理解。这本书包括了很多三维的基本概念,以帮助读者理解后面的 知识。对任何一个web 开发者来说,这本书都值得收藏。” ——Chris Marrin WebGL Spec 编辑 “学习《WebGL 编程指南》是从WebGL 菜鸟到WebGL 专家的绝佳途径。WebGL 虽 然概念上很简单,但真正使用它需要大量3D 数学知识,《WebGL 编程指南》系统地帮 你总结了这些知识,你只需要好好理解它们并运用到实际开发中去。即使你最后还是选 择使用WebGL 3D 库,《WebGL 编程指南》里学到的知识也会帮助你理解那些库究竟在 做些什么,并允许你将它们进行改造,以适应你的应用的特殊要求。真见鬼,你最终还 是坚持使用OpenGL 和/ 或DirectX 编写桌面程序?即使这样,《WebGL 编程指南》也是 一本不错的入门书,因为市面上大多关于3D 的书籍,与目前的3D 技术相比都已经过时 了。总之,《WebGL 编程指南》将帮助你完整理解关于现代3D 图形学的基础知识。” ——Gregg Tavares Google 的软件工程师,Chrome 浏览器WebGL 系统的实现者 推荐序 2011 年的夏天,当我开始尝试翻译LearningWebGL.com 网站教程的时候,WebGL 在中国的天空可以说是刚蒙蒙亮。那时我们已经看到太多的国外的Demo 了,我们更想 学习如何亲手制作出这些Demo。当我开始下手时,才发现自己不知不觉跳进了一个大坑。 正如我之前反复强调过的,WebGL 原生API 是一种非常低等级的接口,就好像一个只有 “+”按钮的计算器,如果你想做2×3 的运算,只能重复两次加法运算才能得以实现。数 学和图形学的门槛浇灭了对WebGL 充满憧憬的前端程序员的激情,而JavaScript 语言本 身的孱弱又让图形程序员不屑一顾。因此从零开始学习WebGL 实在是一件让人头痛的 事情,每天都有一种明天就要开学但是暑假作业还没做完的感觉。 在Three.js、Oak3D、PhiloGL 等一批图形库的“引诱”下,很多人放弃了基础知 识,直接开始操控这些成熟的WebGL 3D 引擎。其中有的人成功了,但是据我了解大部 分的人都在初期的风光得意之后,又重新陷入了泥潭,于是不得不再次回到学习WebGL 原生API 的道路上;而那些一直坚持学习WebGL 原生API 的人,在经历了一开始的艰 苦岁月,战胜了面对他人突飞猛进而自己仍在画三角形的挫败感之后,现在已经成为了 HiWebGL 社区中的中流砥柱。因此在看到这本书后,我十分愿意并有些许兴奋地向广大 WebGL 学习者推荐本书,你可以在流畅的文字描述、大量详实的图例图解中,游刃有余 地在WebGL 原生API 中斩荆披棘,不断前进。这种感觉不再是焦躁不安,而是让我想 起了上大学时的青葱岁月,也希望你能在阅读中获得不一样的新的学习体验。 ——郝稼力 最大的HTML5&WebGL 中文社区创始人, 国内第一个WebGL 商用网站Lao3D.com 创始人 译者序 JavaScript 的野心越来越大了。在过去的十年中,这项技术逐渐把报纸一般的网页变 成了能与客户端程序相媲美的Web 应用。在接管了用户界面、网络通信、多媒体、甚至 数据存储这些原本由桌面程序负责的功能后,JavaScript 终于把触手伸向了最为复杂的领 域之一——三维图形渲染。WebGL 因此而诞生。 学习WebGL,仅有JavaScript 功底是不够的,因为WebGL 的API 非常低级,如果 不对图形学中的诸多概念比较了解,是没办法熟练操作这些API,并知道“你究竟在做 些什么”。互联网上大部分WebGL 教程都忽视了这一点,所以我最初在学习WebGL 时 异常艰辛,经常发生“效果出来了,但不知为什么”的情形。 这本书的好处,就是它系统详细地讲述了着色器、渲染管线、模型变换、投影矩阵 这些三维图形学的基本概念,对于没有图形学基础的前端大众实在是太适合了。这本书 不厌其烦地讲述了几乎每一个API 函数(甚至每一个参数)的作用,手把手地教你如何 编写着色器,涉及了无数与WebGL 相关的细节。这本书相当基础,它不会让你在很短 的时间里就能渲染出精美绝伦的场景(往往借助某些库)。事实上,直到本书篇幅过半, 它才会真正地考虑“三维”这件事。但是请相信我,仔细研究书中前半部分的基础知识, 会使你受益匪浅。但这本书也并不简单,最后一章“高级技术”会让你大开眼界。你会 从原理上理解,如何使模型在地面上投下阴影,如何绘制半透明的物体,如何在场景中 制造雾化效果,如何将渲染的结果作为纹理使用等等。也许你已经知道如何做,但这本 书却告诉了你,为什么要这样做。 总之,如果你是一个缺乏图形编程经验的Web 开发者,这是一本深入浅出,不可多 得的案头好书。风雨欲来,如果现在还不开始进行技术储备,更待何时呢? 最后,我要感谢电子工业出版社的任晓露编辑,是她让我在第一时间读到了如此精 彩的作品。水平所限,纰漏在所难免,如果要提交本书的勘误,或者对本书有任何想法 或建议,可以在本书的主页上留言( http://xieguanglei.com/post/2014-04-15-WebGL 编程指南.html )。 谢光磊 2014 年4 月 前言 WebGL 是一项用以在浏览器中绘制、显示三维计算机图形(“三维图形”),并与之 交互的技术。曾经只有高端的计算机或专门的游戏终端才能渲染三维图形,因为这需要 大量复杂的编程才能实现,然而随着个人计算机,以及——更重要的——浏览器的性能 的提高,使用网页技术渲染三维图形也已经成为可能。本书全面讲授了WebGL 技术, 带领读者一步一个脚印地编写WebGL 程序。和OpenGL 与Direct3D 不同,WebGL 程序 存在于网页中,可以在浏览器里直接执行,而不必安装任何特殊的插件或库。因此,你 只需要最普通的计算机环境,就可以开始进行开发或运行示例程序;而且,一切都是基 于网页的,你可以方便地将WebGL 程序作为网页发布出去。此外,由于WebGL 是基于 网页的,所以该技术的愿景之一,就是同一个程序能够通过浏览器运行在多种设备上, 比如智能手机、平板电脑、游戏终端等。这份远大的野心,意味着WebGL 技术期望对 开发者社区产生深远的影响,并在不久的将来成为图形开发的最佳选择之一。 本书的读者群 在写本书时,我希望本书的读者群主要由两类人构成:希望在网页中加入三维图形 的Web 开发者,以及希望将三维图形搬上网页环境的三维图形开发者。如果你是前一类 读者,即Web 开发者,你可能对标准的Web 技术,如HTML 和JavaScript,已经很熟悉了, 你希望知道如何向网页或Web 程序中插入三维图形,那么WebGL 将会向你提供简单且 强大的解决方案,你可以使用三维图形来增强Web 程序的用户界面(UI),或者开发更 复杂的三维程序,比如运行在浏览器中的三维网页游戏。 如果你是第二类目标读者群中的一员,你可能已经具有使用主流三维应用程序接口 (API),如Direct3D 或OpenGL 进行开发的经验,你希望知道如何在网页环境中应用这 些知识。我想你一定对开发出能够在现代浏览器中运行的复杂三维程序更感兴趣。 然而,这本书也适用于更加广泛的读者群。因为本书假定读者不具有任何关于二维 或三维图形编程的背景,所以几乎是手把手地向读者传授WebGL 的特性。因此,我想 以下读者可能也会对本书感兴趣: 所有希望了解网页技术与图形技术交集的程序员; 学习二维或三维图形学的学生,因为WebGL 只需要一个浏览器即可上手,无须 安装一整套开发环境。 探索最前沿技术,试图在安卓手机、iPhone 等移动设备的最新版浏览器中有所作 为的Web 开发者。 本书涵盖的内容 本书涵盖了WebGL 1.0 API 包含的几乎所有的JavaScript 方法,你可以学到WebGL、 HTML、JavaScript 是如何联系的,如何建立和运行WebGL 程序,如何使用JavaScript 控 制复杂的三维“着色器”程序。本书详细讲述了如何编写顶点着色器和片元着色器,如 何实现该机的渲染技术,如逐顶点光照、阴影、基本的交互操作(如选中三维物体)等。 本书的每一章将开发若干个可用的,具有一定功能的WebGL 示例程序,并通过这些示 例程序介绍WebGL 的关键特性。在读完本书之后,你就能够编写出能够充分利用浏览 器的编程能力和图形硬件的WebGL 程序。 本书的结构 本书一步一步地介绍了WebGL API 以及相关的Web API,以帮助你建立起关于 WebGL 的知识结构。 第1 章——WebGL 概述 这一章简要介绍了WebGL,讨论了WebGL 的历史起源,概括了它的一些关键特性 和优点。这一章还介绍了WebGL 与HTML5 以及 JavaScript 的关系,介绍了我们可以使 用哪些浏览器开始探索WebGL。 第2 章——WebGL 入门 这一章通过建立几个示例程序,依次介绍了<canvas> 元素和WebGL 的核心函数。 每个示例都是用JavaScript 编写的,并使用WebGL 在网页上绘制一个简单的形状。示例 程序突出了以下几点:(1)WebGL 如何使用<canvas> 元素并在其上绘图;(2)HTML 文件 和用JavaScript 编写的WebGL 代码文件的连接;(3) 简单的WebGL 绘图函数;(4) 着色 器程序在WebGL 中的地位。 第3 章——绘制和变换三角形 这一章在之前的基础上,探索了如何绘制较为复杂的图形,如何操作三维空间中的 这些图形。这一章主要包括:(1) 三角形的关键作用,以及WebGL 对绘制三角形的支持;(2)使用多个三角形绘制出其他图形;(3) 使用方程对三角形进行基本的变换,如平移、旋转和缩放等;(4) 矩阵可以简化变换的运算。 第4 章——高级变换和动画基础 这一章将更加深入地探索变换的原理,并开始将变换用于动画中。你将:(1) 了解一 个矩阵变换库,该库将矩阵变换的数学运算细节隐藏了起来;(2) 使用矩阵库将多次变 换组合起来;(3) 在矩阵库的帮助下,探索如何实现简单的动画。这些技术是构建复杂 WebGL 程序的基石,在后面几章的示例程序中都会用到。 第5 章——颜色和纹理 这一章在之前几章的基础上,进一步深入研究了以下三个问题:(1) 除了顶点坐标数 据,我们还可以将颜色信息等其他数据传入顶点着色器;(2) 顶点着色器和片元着色器之 间的光栅化过程,将图形转化为了片元;(3) 如何将图像(或纹理)贴到图形或模型的表 面。这一章是有关WebGL 核心功能的最后一章。 第6 章——OpenGL ES 着色器语言(GLSL ES) 这一章不涉及WebGL 示例程序,而是详细介绍了OpenGL ES 着色器语言(GLSL ES)的核心特性,包括:(1) 数据、变量、变量类型;(2) 矢量、矩阵、结构体、数组和 取样器;(3) 运算符、流程控制和函数;(4)attribute 变量、uniform 变量和varying 变量;(5)精度限定字;(6) 预处理过程和编程准则。在这一章的最后,你将对GLSL ES 有很好的理解,并学会使用该语言来编写各种着色器。 第7 章——进入三维世界 这一章将带领读者首次进入三维世界,探索如何将以前学到的一切从二维空间搬到 三维空间中。具体地,你将探索:(1) 如何在三维空间中表示观察者;(2) 如何控制可视 的三维空间体积;(3) 裁剪;(4) 物体的前后关系;(5) 绘制一个三维物体——立方体。所有这些问题都会对三维场景的渲染和最终呈现给用户的样子产生重大的影响。为了构建 三维场景,深入理解并掌握它们是必须的。 第8 章——光照 这一章主要研究如何实现光照,研究了不同类型的光源及其对三维场景产生的效果。 如果想要使三维场景逼真,光照是必需的,因为光照会增强场景的深度感。 本章讨论了以下几个关键点:(1) 着色、阴影和不同类型的光源产生的光,包括点光 源光、平行光和环境光;(2) 三维场景中两种主要的反射光类型:漫反射和环境反射;(3) 着色的细节,以及如何实现光照效果时场景更像是三维的。 第9 章——层次模型 这一章是关于如何使用WebGL 的核心特性的最后一章。在这一章结束时,你将掌 握WebGL 的所有基础知识,并完全能够创建逼真和可交互的三维场景了。这一章的重 点是层次模型。层次模型能够使复杂模型,如游戏角色、机器人,甚至是真人模型产生 动作,而不仅仅是生硬的立方体。 第10 章——高级技术 这一章在整本书的基础上,介绍了若干有用的高级技术,提供了一些关键的工具, 帮助你构建出可交互的、令人惊叹的三维图形。每一项技术都通过一个完整的示例来展示,你可以在自己的WebGL 程序中重用其中的代码。 附录A——WebGL 无须交换缓冲区 这篇附录解释了为什么WebGL 无须像OpenGL 那样交换缓冲区。 附录B——GLSL ES 1.0 内置函数 这篇附录提供了一份包含所有OpenGL ES 着色器语言内置函数的参考列表。 附录C——投影矩阵 这篇附录提供了Matrix4.setOrtho() 函数和Matrix4.setPerspective() 函数生成的 投影矩阵。 附录D——WebGL/OpenGL :左手还是右手坐标系? 这篇附录介绍了WebGL 和OpenGL 的内在坐标系统,并从技术上解释了为什么我 们说WebGL 和OpenGL 对采取左手坐标系或右手坐标系是中立的。 附录E——逆转值矩阵 这篇附录解释了模型矩阵的逆转值矩阵为什么可以用来变换法向量。 附录F——从文件中加载着色器 这篇附录解释了如何从文件中加载着色器程序。 附录G——世界坐标系和本地坐标系 这篇附录介绍了两种不同的坐标系统,以及如何在三维图形中使用它们。 附录H——关于WebGL 的浏览器设置 这篇附录介绍了浏览器的高级设置方法,以确保WebGL 程序能够正确运行,以及 程序不能正确运行时的应对方法。 支持WebGL 的浏览器在撰写本书之时,WebGL 被Chrome、Firefox、Safari、Opera 浏览器支持。遗憾的是,有一些浏览器如IE9(Microsoft Internet Explorer)并不支持WebGL。在本书中,我们使用Google 发布的Chrome 浏览器。Chrome 不仅支持WebGL,还支持一些有用的特性,如调试WebGL 的控制台函数。我们已经在以下环境中检查过本书的所有示例程序,都能够正确运行。在任何支持WebGL 的浏览器中,这些程序也应当能够正确运行。 表P.1 PC 环境 浏览器Chrome(25.0.1364.152 m) 操作系统Windows7 & 8 显卡NVIDIA Quadro FX 380,NVDIA GT X 580,NVDIA GeForce GTS 450,Mobile Intel 4 Series Express Chipset Family,AMD Radeon HD 6970 参考这个页面:www.khronos.org/webgl/wiki/BlacklistsAndWhitelists,以获取最新的、关于可能导致问题的硬件列表。 为了不受阻碍地开始学习本书,你应该去下载Chrome(或者你中意的其他浏览器), 然后进入本书的帮助网站https://sites.google.com/site/webglbook/。 在第3 章,点击示例程序文件HelloTriangle.html,如果你看到如图P.1 所示的红色 三角形,就说明WebGL 正常工作了。 图P.1 加载HelloTriangle 显示红色三角形 如果你没有看到红色三角形,那么请参考附录H,改变你的浏览器设置以加载 WebGL 程序。 示例程序和相关链接 本书所有的示例程序都可以在帮助站点上找到。出版社的官方站点位于www. informit.com/title/9780321902924, 而作者的站点则位于https://sites.google.com/site/ webglbook。 后一个站点包含了本书所有示例程序的链接,你可以点击链接并直接运行每个程序。 如果你想修改示例程序,可以从上述任意一个站点下载包含所有本书所有示例程序 的压缩文件到你自己的磁盘上。你会发现每个程序都包含一个HTML 文件和一个相应的 JavaScript 文件,二者在同一个文件夹下。比如,示例程序HelloTriangle,就包含HelloTriangle. html 和HelloTriangle.js。双击HelloTriangle.html 就可以运行该程序。 排版约定 本书遵循以下排版约定: 粗体Bold——术语或重要词汇首次出现。 斜体Italic——函数参数名、或引用名、程序名或文件名。 Monospace 字体——示例代码、方法、函数、变量、命令行选项、JavaScript 对 象名称、HTML 标签名称。 致谢 在撰写本书(包括最初的日文版和后来的英文版)的过程中,我们有幸接受了很多 才华横溢的同仁的帮助。 Takafumi Kanda 为本书提供了大量的代码示例和程序,如果没有他,这本书不可 能完成。Yasuko Kikuchi、Chie Onuma 和Yuichi Nishizawa 为本书的早期版本提供了很 多有价值的反馈,尤其是Kikuchi 女士的一条极富远见建议,使我们完全重写了好几节 内容,大大充实了本书。Hiroyuki Tanaka 和Kazsuhira Oonishi(iLinx) 为示例程序提供了帮助,Teruhisa Kamachi 和Tetsuo Yoshitani 为本书关于HTML5 和JavaScript 的章节提供了帮助。WebGL 工作小组,尤其是Ken Russell(Google),Chris Marin(Apple) 和Dan Ginsburg(AMD) 回答了很多技术问题。我们的工作也有幸受到Khronos 小组的主席Neil Trevett 的认可,同时也感谢帮助我们联系上Trevett 先生和WebGL 工作小组的Hitoshi Kasai(MIACIS 的社长)。此外,还需要感谢Xavier Michel 和Makoto Sato( 上智大学),他们为本书从日语翻译为英语提供了巨大的帮助。而Jeff Gilbert、Rick Rafey 和Daniel Haehn 则仔细地审阅了本书的英文版,并给出了极好的建议和反馈。最后,我们还从个人角度感谢Laura Lewin 和Olivia Basegio( 培生) 为顺利出版本书所作的组织工作。 我们对培生集团出版的“红宝书”(OpenGL Programming Guide) 和“金宝书”(OpenGL ES 2.0 Programming Guide) 的所有作者致敬,如果没有那两本书,这本书也无从谈起。 我们希望这本书的出版,如果可能的话,能够略表寸心。 关于作者 Kouichi Matsuda 博士是多媒体产品用户界面和用户体验设计方面的专家。他先后供 职于日本电气(NEC)、索尼(Sony) 研发中心、索尼(Sony) 计算机科学实验室,曾经做过 产品研发,也做过科学研究,最终回到产品研发的岗位。目前,他是用户体验和人机交 互领域的首席研究员,负责多款消费类电子产品的设计。他曾经设计了社交三维虚拟世 界“PAW”,也曾经参与过VRML97(ISO/IEC 14772-1:1997) 标准的开发工作,在VRML 和X3D(WebGL 的前身) 社区中仍然非常活跃。他撰写过15 本计算机技术的书籍,并翻 译过25 本相关书籍。他专长于用户体验、用户界面、人机交互、自然语言处理和面向娱 乐的网络设备,以及接口代理系统等领域。他不仅对技术领域的新鲜事物充满热情,还 热衷于温泉、夏季的海滩、红酒和漫画(为此他已经沉迷于绘制插画一段时间了)。他在 东京大学工程系获得了博士学位,你可以通过WebGL.prog.guide@gmail.com 联系他。 Rodger Lea 博士是卑诗大学媒体与图像跨学科中心的兼职教授,对多媒体和分布式 计算等领域很感兴趣。他和他带领的研究小组在学术和工业领域耕耘超过20 年,参与制 定了VRML97 标准,开发了多媒体操作系统、可交互数字电视原型,并领导了家用多媒 体网络标准的制定工作。他发表了60 多篇学术论文,著有3 本技术书籍,并拥有12 项 专利。目前,他的研究集中在探索发展中的互联网,但他仍然对有关多媒体和图形学的 一切抱有热情。 关于译者 谢光磊,毕业于南京大学,目前为中科院在读硕士,即将成为淘宝UED 的一名前端 工程师。因一次偶然的机会接触WebGL 而对其萌生兴趣,并愿意持久深入地研究这项 技术。个人站点为www.xieguanglei.com。
目录 第1 章 WebGL 概述 1 WebGL 的优势 3 使用文本编辑器开发三维应用 3 轻松发布三维图形程序 4 充分利用浏览器的功能 5 学习和使用WebGL 很简单 5 WebGL 的起源 5 WebGL 程序的结构 6 总结 7 第2 章 WebGL 入门 9 Canvas 是什么? 10 使用<canvas> 标签 11 DrawRectangle.js 13 最短的WebGL 程序:清空绘图区 16 HTML 文件(HelloCanvas.html) 16 JavaScript 程序(HelloCanvas.js) 17 用示例程序做实验 22 绘制一个点(版本1) 22 HelloPoint1.html 24 HelloPoint1.js 24 着色器是什么? 25 使用着色器的WebGL 程序的结构 27 初始化着色器 29 顶点着色器 31 片元着色器 33 绘制操作 34 WebGL 坐标系统 35 用示例程序做实验 37 绘制一个点(版本2) 38 使用attribute 变量 38 示例程序(HelloPoint2.js) 39 获取attribute 变量的存储位置 41 向attribute 变量赋值 42 gl.vertexAttrib3f() 的同族函数 44 用示例程序做实验 45 通过鼠标点击绘点 46 示例程序(ClickedPoints.js) 47 注册事件响应函数 48 响应鼠标点击事件 50 用示例程序做实验 53 改变点的颜色 55 示例程序(ColoredPoints.js) 56 uniform 变量 58 获取uniform 变量的存储地址 59 向uniform 变量赋值 60 gl.uniform4f() 的同族函数 61 总结 62 第3 章 绘制和变换三角形 63 绘制多个点 64 示例程序(MultiPoint.js) 66 使用缓冲区对象 69 创建缓冲区对象(gl.createBuffer()) 70 绑定缓冲区(gl.bindBuffer()) 71 向缓冲区对象中写入数据(gl.bufferData()) 72 类型化数组 74 将缓冲区对象分配给attribute 变量(gl.vertexAttribPointer()) 75 开启attribute 变量(gl.enableVertexAttribArray()) 77 gl.drawArrays() 的第2 个和第3 个参数 78 用示例程序做实验 79 Hello Triangle 80 示例程序(HelloTriangle.js) 80 基本图形 82 用示例程序做实验 83 Hello Rectangle(HelloQuad) 84 用示例程序做实验 85 移动、旋转和缩放 86 平移 87 示例程序(TranslatedTriangle.js) 88 旋转 91 示例程序(RotatedTriangle.js) 93 变换矩阵:旋转 97 变换矩阵:平移 100 4×4 的旋转矩阵 101 示例程序(RotatedTriangle_Matrix.js) 102 平移:相同的策略 105 变换矩阵:缩放 106 总结 108 第4 章 高级变换与动画基础 109 平移,然后旋转 109 矩阵变换库:cuon-matrix.js 110 示例程序(RotatedTriangle_Matrix4.js) 111 复合变换 113 示例程序(RotatedTranslatedTriangle.js) 115 用示例程序做实验 117 动画 118 动画基础 119 示例程序(RotatingTriangle.js) 119 反复调用绘制函数(tick()) 123 按照指定的旋转角度绘制三角形(draw()) 123 请求再次被调用(requestAnimationFrame()) 125 更新旋转角(animate()) 126 用示例程序做实验 128 总结 130 第5 章 颜色与纹理 131 将非坐标数据传入顶点着色器 131 示例程序(MultiAttributeSize.js) 133 创建多个缓冲区对象 134 gl.vertexAttribPointer() 的步进和偏移参数 135 示例程序(MultiAttributeSize_Interleaved.js) 136 修改颜色(varying 变量) 140 示例程序(MultiAttributeColor.js) 141 用示例程序做实验 144 彩色三角形(ColoredTriangle.js) 145 几何形状的装配和光栅化 145 调用片元着色器 149 用示例程序做实验 149 varying 变量的作用和内插过程 151 在矩形表面贴上图像 153 纹理坐标 156 将纹理图像粘贴到几何图形上 156 示例程序(TexturedQuad.js) 157 设置纹理坐标(initVertexBuffers()) 160 配置和加载纹理(initTextures()) 160 为WebGL 配置纹理(loadTexture()) 164 图像Y 轴反转 164 激活纹理单元(gl.activeTexture()) 165 绑定纹理对象(gl.bindTexture()) 166 配置纹理对象的参数(gl.texParameteri()) 168 将纹理图像分配给纹理对象(gl.texImage2D()) 171 将纹理单元传递给片元着色器(gl.uniform1i()) 173 从顶点着色器向片元着色器传输纹理坐标 174 在片元着色器中获取纹理像素颜色(texture2D()) 174 用示例程序做试验 175 使用多幅纹理 177 示例程序(MultiTexture.js) 178 总结 183 第6 章 OpenGL ES 着色器语言(GLSL ES) 185 回顾:基本着色器代码 186 GLSL ES 概述 186 你好,着色器! 187 基础 187 执行次序 187 注释 187 数据值类型(数值和布尔值) 188 变量 188 GLSL ES 是强类型语言 189 基本类型 189 赋值和类型转换 190 运算符 191 矢量和矩阵 192 赋值和构造 193 访问元素 195 运算符 197 结构体 200 赋值和构造 200 访问成员 200 运算符 201 数组 201 取样器(纹理) 202 运算符优先级 203 程序流程控制:分支和循环 203 if 语句和if-else 语句 203 for 语句 204 continue、break 和discard 语句 205 函数 205 规范声明 207 参数限定词 207 内置函数 208 全局变量和局部变量 209 存储限定字 209 const 变量 209 Attribute 变量 210 uniform 变量 211 varying 变量 211 精度限定字 211 预处理指令 213 总结 215 第7 章 进入三维世界 217 立方体由三角形构成 217 视点和视线 218 视点、观察目标点和上方向 219 示例程序(LookAtTriangles.js) 221 LookAtTriangles.js 与RotatedTriangle_Matrix4.js 224 从指定视点观察旋转后的三角形 225 示例程序(LookAtRotatedTriangles.js) 227 用示例程序做实验 228 利用键盘改变视点 230 示例程序(LookAtTrianglesWithKeys.js) 230 独缺一角 232 可视范围(正射类型) 233 可视空间 234 定义盒状可视空间 235 示例程序(OrthoView.html) 236 示例程序(OrthoView.js) 237 JavaScript 修改HTML 元素 239 顶点着色器的执行流程 239 修改near 和far 值 241 补上缺掉的角(LookAtTrianglesWithKeys_ViewVolume.js) 243 用示例程序做实验 245 可视空间(透视投影) 246 定义透视投影可视空间 247 示例程序(perspectiveview.js) 249 投影矩阵的作用 251 共冶一炉(模型矩阵、视图矩阵和投影矩阵) 252 示例程序(PerspectiveView_mvp.js) 254 用示例程序做实验 257 正确处理对象的前后关系 258 隐藏面消除 260 示例程序(DepthBuffer.js) 262 深度冲突 263 立方体 266 通过顶点索引绘制物体 268 示例程序(HelloCube.js) 268 向缓冲区中写入顶点的坐标、颜色与索引 271 为立方体的每个表面指定颜色 274 示例程序(ColoredCube.js) 275 用示例程序做实验 277 总结 279 第8 章 光照 281 光照原理 281 光源类型 283 反射类型 284 平行光下的漫反射 286 根据光线和表面的方向计算入射角 287 法线:表面的朝向 288 示例程序(LightedCube.js) 291 环境光下的漫反射 296 示例程序(LightedCube_ambient.js) 298 运动物体的光照效果 299 魔法矩阵:逆转置矩阵 301 示例程序(LightedTranslatedRotatedCube.js) 302 点光源光 304 示例程序(PointLightedCube.js) 305 更逼真:逐片元光照 308 示例程序(PointLightedCube_perFragment.js) 309 总结 310 第9 章 层次模型 311 多个简单模型组成的复杂模型 311 层次结构模型 313 单关节模型 314 示例程序(JointMode.js) 315 绘制层次模型(draw()) 319 多节点模型 321 示例程序(MultiJointModel.js) 323 绘制部件(drawBox()) 326 绘制部件(drawSegments()) 327 着色器和着色器程序对象:initShaders() 函数的作用 332 创建着色器对象(gl.createShader()) 333 指定着色器对象的代码(gl.shaderSource()) 334 编译着色器(gl.compileShader()) 334 创建程序对象(gl.createProgram()) 336 为程序对象分配着色器对象(gl.attachShader()) 337 连接程序对象(gl.linkProgram()) 337 告知WebGL 系统所使用的程序对象(gl.useProgram()) 339 initShaders() 函数的内部流程 339 总结 342 第10 章 高级技术 343 用鼠标控制物体旋转 343 如何实现物体旋转 344 示例程序(RotateObject.js) 344 选中物体 347 如何实现选中物体 347 示例程序(PickObject.js) 348 选中一个表面 351 示例程序(PickFace.js) 352 HUD(平视显示器) 355 如何实现HUD 355 示例程序(HUD.html) 356 示例程序(HUD.js) 357 在网页上方显示三维物体 359 雾化(大气效果) 359 如何实现雾化 360 示例程序(Fog.js) 361 使用w 分量(Fog_w.js) 363 绘制圆形的点 364 如何实现圆形的点 364 示例程序(RoundedPoint.js) 366 α 混合 367 如何实现α 混合 367 示例程序(LookAtBlendedTriangles.js) 369 混合函数 369 半透明的三维物体(BlendedCube.js) 371 透明与不透明物体共存 .372 切换着色器 373 如何实现切换着色器 374 示例程序(ProgramObject.js) 375 渲染到纹理 379 帧缓冲区对象和渲染缓冲区对象 380 如何实现渲染到纹理 381 示例程序(FramebufferObject.js) 382 创建帧缓冲区对象(gl.createFramebuffer()) 385 创建纹理对象并设置其尺寸和参数 385 创建渲染缓冲区对象(gl.createRenderbuffer()) 386 绑定渲染缓冲区并设置其尺寸(gl.bindRenderbuffer(), gl.renderbufferStorage()) 386 将纹理对象关联到帧缓冲区对象(gl.bindFramebuffer(), gl.framebufferTexture2D()) 388 将渲染缓冲区对象关联到帧缓冲区对象(gl.framebufferRenderbuffer()) 389 检查帧缓冲区的配置(gl.checkFramebufferStatus()) 390 在帧缓冲区进行绘图 390 绘制阴影 392 如何实现阴影 392 示例程序(Shadow.js) 393 提高精度 399 示例程序(Shadow_highp.js) 400 加载三维模型 401 OBJ 文件格式 404 MTL 文件格式 405 示例程序(OBJViewer.js) 406 自定义类型对象 409 示例程序(OBJViewer.js 解析数据部分) 411 响应上下文丢失 418 如何响应上下文丢失 419 示例程序(RotatingTriangle_contextLost.js) 420 总结 422 附录A WebGL 中无须交换缓冲区 423 附录B GLSL ES 1.0 内置函数 427 角度和三角函数 428 指数函数 429 通用函数 430 几何函数 433 矩阵函数 434 矢量函数 435 纹理查询函数 436 附录C 投影矩阵 437 正射投影矩阵 437 透视投影矩阵 437 附录D WebGL/OpenGL :左手还是右手坐标系? 439 示例程序(CoordinateSystem.js) 440 隐藏面消除和裁剪坐标系统 443 裁剪坐标系和可视空间 444 什么是对的? 446 总结 448 附录E 逆转置矩阵 449 附录F 从文件中加载着色器 453 附录G 世界坐标系和本地坐标系 457 本地坐标系 458 世界坐标系 459 变换与坐标系 461 附录H WebGL 的浏览器设置 463