本书中从着色器技术必须掌握的向量、矩阵与空间等数学知识开始介绍, 通过大量的实例, 图文并茂地讲解了渲染流水线的原理, 着色器相关的语言、数据结构、基本语法, 着色器的分类等相关内容, 让读者在实战中逐步掌握Unity Shader的相关技术, 并应用到实际工作中。
1.面向零基础人群写作,内容由浅入深,基础知识全面,注重原理讲解,让读者知其然更知其所以然。
2.语言通俗易懂,插图丰富,用大量生动与图形化的描述讲解Shader及其原理知识,学习门槛低,上手快。
3.内容贴近实战,帮助读者举一反三,拓展知识,不局限于书中介绍的内容。
4.配套资源齐全。课后习题,帮助读者巩固知识。
前言
当我还是一个刚高考完的愣头青时,抱着满腔热血打开Unity,满脑子都是光怪陆离的游戏画面,以为下一个非同寻常的独立游戏就要出现在我的手里,结果在第一步就卡住了——想象的画面很美好,但Unity只给了我一个平平无奇的Standard材质,这可如何是好?于是我创业未半而中道找教程,才知道有个东西叫“Shader”,要想真正随心所欲地“画”出理想的游戏画面,我要先学会它。
彼时,Shader还在社群里被认为是一种“高端”的代码,资料不多、教程很少,即便是当时流行的入门资料也是有一定门槛的(这种情况到目前也依然存在),无论是对数学的要求,还是对编程的要求,以及对计算机图形学知识的要求。毕竟Shader本身就是一项融合了多种学科知识的技术,尤其是对于对Shader还一无所知的初学者来说,不了解线性代数,不会编程,基本就告别大多数教程了。近几年来,独立游戏越来越多,游戏开发的门槛也一降再降,当很多入门不久的用户都能使用C#在Unity面前游刃有余时,唯独Shader保持着它那“高冷而不近人情”的高门槛。对于大多数刚刚入门的Shader初学者,或者是那些只是想能看懂Shader以对它稍作修改的开发者,掌握晦涩难懂的底层理论是否真的是必要的?
因此,本书尝试用浅显易懂的语言和大量的比喻、引导,先力求让读者明白“写Shader到底是在写什么”,只有建立起对Shader的宏观概念,才能谈“怎么写Shader”,否则写起来就像盲人摸象,很容易陷入“只会改Shader而不会写Shader”的困境。另外一点,比起用案例和代码的堆砌来教读者“怎么做”,本书将更多的笔墨集中在写“为什么这么做”,这个理念从第1章一直持续到了最后一章,也是笔者最希望读者从本书中学到的。我们总是先遇到问题,再去想解决问题的方法,而只知道“怎么做”,只能解决一种问题,我们也不可能指望网上的教程总能完完全全地贴合我们的需求,一五一十地照搬案例只会让未来的开发变成“对着墙砖找墙洞”——那我们岂不就成了案例的提线木偶了?本书的大部分案例都旨在告诉读者一种新思想、一种新工具,并希望读者能真正将它们融会贯通,变成属于自己的“武器”。
在视频资料和电子文档大行其道的当下,阅读一本纸质书学计算机知识看起来多少是有一些“传统”,但笔者认为纸媒依然有着独特的作用。它不依赖于电子设备和网络环境,也方便反复查看,读者可以更聚焦于代码之外的行文思路,学习每一步之间的思路推理过程,所以本书在许多章节中并不着重突出“代码与反馈”的内容。这不是一本“没有计算机在旁边随时操作就看不下去”的书(当然,并不是认为看本书的时候不需要实践)。
在本书的编写过程中,参考了许多前辈撰写的入门教程,包括Catlike Coding的教程、冯乐乐的《Unity Shader入门精要》。在数学章节中,笔者受到3Blue1Borwn极大的影响,他对线性代数的集合本质进行了鞭辟入里的讲解。这些教程都是很棒的学习资料,读者在学习中遇到问题时也可以进行查阅。
在编写本书的过程中,我尽可能地检查校对内容的准确性,但由于个人能力和知识储备的限制,难免会存在一些错误或者不足之处。因此,非常欢迎读者朋友在阅读本书的过程中积极提供反馈和建议,以帮助我更好地改善内容。
非常感谢何睿骅、李恒、肖洪广和胡致远,他们对本书的校对、编排、内容调整提供了巨大的帮助。同时,对中国铁道出版社有限公司的编辑于先军先生的约稿表示感谢,是您的信任让本书得以面世。
15年前,有个名叫66RPG的独立游戏论坛用一句“梦想世界,在你手中”的口号激励了成千上万的游戏开发者,而我正是其中之一。我们的游戏世界从来不缺乏奇景,只是我们还未能拥有足够的魔法将它的绮丽展现出来。衷心期盼本书能成为每一位读者在游戏世界中创世的魔法指南,祝各位早日开发出自己梦想中的游戏。
黄志翔(网名:Hking Auditore)
2023年10月
黄志翔,网名HkingAuditore,国内某知名游戏大厂技术美术。曾参与项目:玩具帝国(第二届CUSGA中国大学生游戏开发创作大赛具潜力奖提名,2023GWB腾讯独立游戏大奖赛决赛入围);糖果灾难(第二届中国原创艺术类精品游戏大赛提名、2021indiePlay中国独立游戏大赛最佳设计奖提名)。
第1章 数学基础
1.1 向量
1.1.1 向量的基本运算
1.1.2 线性组合
1.1.3 线性相关与线性无关
1.1.4 基向量
1.2 矩阵与空间
1.2.1 矩阵概念与几何意义
1.2.2 矩阵运算及其几何意义
1.2.3 使用矩阵进行空间变换
1.3 习题
第2章 渲染流水线
2.1 教机器人画速写
2.2 GPU的“思维方式”
2.3 应用阶段
2.4 几何阶段
2.4.1 顶点着色器
2.4.2 曲面细分着色器
2.4.3 几何着色器
2.4.4 投影
2.4.5 裁剪
2.4.6 屏幕映射
2.5 光栅化阶段
2.5.1 图元组装
2.5.2 三角形遍历
2.5.3 片元着色器
2.5.4 逐片元操作
2.6 可编程渲染管线:Unity SRP
2.7 习题
第3章 Shader基础
3.1 我的第一个Shadel
3.2 Properties
3.3 SubShader
3.4 Pass
3.4.1 Pragma
3.4.2 Include
3.5 Shader内的结构体
3.5.1 顶点着色器输入
3.5.2 片元着色器输入
3.6 顶点着色器
3.7 片元着色器
3.8 我该怎么写呢
3.8.1 基本语法
3.8.2 常用函数
3.9 习题
第4章 上个色吧:基础Shader上手
4.1 纹理
4.1.1 平移、缩放、旋转——UV的奇妙用途
4.1.2 更多的纹理、奇妙的遮罩
4.1.3 混合的艺术
4.1.4 示例代码
4.2 不同空间的操作
4.2.1 世界空间与模型空间
4.2.2 观察空间与裁剪空间
4.3 控制覆盖的方式
4.3.1 渲染队列
4.3.2 深度测试、深度写入、深度裁切与Early
4.3.3 溶解效果:Alpha Test与Clip操作
4.3.4 模板测试
4.4 完善材质面板:Properties
4.5 你能获得的其他信息
4.5.1 顶点上的其他信息
4.5.2 其他信息
4.6 习题
第5章 计算与串联:需要思考的Shader
5.1 边缘光效果
5.1.1 如何“看到”外边缘
5.1.2 让效果不断变换
5.1.3 使用遮罩美化
5.1.4 让功能是“可选的”:Shader变体
5.1.5 最终代码
5.2 简单光照
5.2.1 漫反射
5.2.2 环境光
5.2.3 高光反射
5.2.4 阴影
5.2.5 多光源渲染
5.2.6 球谐光照
5.2.7 障眼法:烘焙
5.2.8 完整代码
5.3 法线贴图
5.3.1 提高模型细节的“障眼法”
5.3.2 翻译法线贴图
5.3.3 Unity中的法线贴图
5.3.4 完整代码
5.4 类玻璃物体的渲染
5.4.1 折射效果与Grabpass
5.4.2 模糊
5.4.3 反射
5.4.4 完整代码
5.5 习题
第6章 在模型上雕塑:Shader与几何
6.1 描边
6.1.1 额外的Pass
6.1.2 平直着色物体描边
6.1.3 完整代码
6.2 无中生有的顶点:曲面细分着色器
6.2.1 曲面细分的流程及数据传递
6.2.2 Gerstner波
6.2.3 计算法线
6.2.4 基于视距的曲面细分
6.2.5 完整代码
6.3 改变网格:几何着色器
6.3.1 几何着色器的流程与数据传递
6.3.2 生成随机草地
6.4 习题
第7章 中转站:Render Texure
7.1 轨迹效果
7.1.1 渲染的中转站Rerder Teture
7.1.2 在Render Tenure上作画
7.2 后处理效果
7.2.1 Uhity Post Processing包
7.2.2 创建自己的后处理效果
7.2.3 后处理中的描边效果
7.3 习题
第8章 非真实感渲染
8.1 色彩控制
8.2 风格化描边
8.3 边缘光
8.4 笔触感
8.5 我们想要什么样的“非真实感”
8.6 习题
第9章 真的入门了吗
9.1 是否是个好Shader
9.1.1 良好的代码习惯
9.1.2 函数库
9.1.3 互不耦合的属性
9.1.4 小心容易忽略的风险
9.1.5 性能与效果的平衡
9.2 学习的路还很长