1.1 程序员的三大浪漫
有人说,程序员的三大浪漫是编译原理、操作系统和图形学(是的,我已经听到很多人在反驳这句话了,不要当真啦)。不管你是否认同这句话,我们只是想借此说明图形学在程序员心目中的地位。正在看此书的你,想必多多少少都对图形学或者渲染有一定兴趣,也许你想要通过此书来学习如何实现游戏中的各种特效,也许你仅仅是好奇那些绚丽的画面是如何产生的。我们是程序员中的“外貌协会”,期待着用代码编写出一个绚丽多姿的世界。这就是我们的浪漫。
我想,读者大概都经历过这样的场景:当你在游戏里看到那些出色的画面时,你很好奇这样的游戏是如何制作出来的,更具体的是,这样的渲染效果是如何得到的。于是你搜索后发现,这个游戏是Unity引擎开发的,更巧的是,Unity也是你熟知的引擎!于是你继续搜索,想要知道如何在Unity里实现这样的效果,最后,你往往会得到“要编写自己的Shader”这样的答案。总算有了一些头绪,你继续在网络上搜索如何学习编写Shader。于是你看到了很多文章,这些文章告诉你Unity Shader有哪些语法,一个普通的漫反射或者边缘高光的效果的代码是什么样子的。然后,你把这些代码粘贴到Unity中,保存后运行,效果出现了!一切看起来好像都很顺利,可是,当你仔细阅读这些代码时,却往往没有头绪。你不知道为什么要有一个名为vert和frag的函数,它们是什么时候调用的,为什么vert函数里要进行一些矩阵运算,这些矩阵是用来做什么的,为什么当你按照C#里面的一些语法编写时Shader却报错了。这些疑问大大影响了你学习Shader的信心,你开始觉得这是一个比学习C#难许多倍的事情,怀疑自己是不是还不具备学习如何编写Shader的基础。
如果上面的情景和你的经历有些类似,那么相信我,有很多人和你有一样的烦恼。事实上,我们之所以会觉得学习Shader比学习C#这样的编程语言更加困难,一个原因是因为Shader需要牵扯到整个渲染流程。当学习C++、C#这样的高级语言时,我们可以在不了解计算机架构的情况下仍然编写出实现各种功能的代码,这样的高级语言更符合人类的思维方式。然而,Shader并不是这样的。我们之所以要学习Shader,是想要学习如何把物体按照自己的意愿渲染到屏幕上,但是,Shader只是整个渲染流程中的一个子部分。虽然它很关键,但想要学习它,我们就需要了解整个渲染流程是如何进行的。和C++这样的高级语言不同,尽管Shader的编写语言已经达到了我们可以理解的程度,但Shader更多地是面向GPU的工作方式,所以它的一些语法对我们来说并不那么直观。因此,任何一篇只讲语法、不讲渲染框架的文章都无法解决读者的困惑。
我们希望通过本书可以帮助读者建立一个渲染流程的整体体系,这些基础是跨越Shader学习中层层障碍的重要因素。我们也相信,在学习完本书后,读者可以自行回答本章开头提出的那些问题。