本节书摘来自华章计算机《Unity着色器和屏幕特效开发秘笈(原书第2版)》一书中的第1章,第1.2节,作者 [英]艾伦朱科尼(Alan Zucconi)[美]肯尼斯拉默斯(Kenneth Lammers),译 占红来,更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1.2 创建基本的标准着色器
每一个Unity开发人员都应该熟悉模块(component)的概念。游戏中的所有物体都会包含一系列模块,这些模块会影响它的外观和行为。一般而言脚本(script)会决定物体的行为,而渲染器(renderer)则决定了它在屏幕上呈现出来的外观。Unity有多种渲染器,根据我们想要显示的物体类型的不同,会使用不同的渲染器。每个3D模型一般都会有一个名为MeshRenderer的渲染器。一个物体可以只有一个渲染器,但是一个渲染器可以有多种材质(material)。每一种材质就是一个着色器呈现出来的外观,因此着色器也就是3D图像食物链的最后一环。这些模块之间的关系可以从下图看出:
理解了这些模块之间的不同十分有助于我们理解着色器是如何工作的。
1.2.1 准备工作
在准备学习这一部分时,你需要运行Unity 5并且创建一个新的项目(project)。在本书配套的代码里面也包含这样一个初始化好的Unity项目,你可以使用这个项目作为基础,随着后续章节的深入学习来自定义你的着色器。准备好这两样东西之后,实时着色的精彩世界已经为你敞开了。
1.2.2 操作步骤
在开始做着色器之前,可以先创建一个小的场景作为基础。创建场景的步骤是在Unity编辑器中选择GameObject | Create Empty。在这个场景中,可以创建一个简单的地平面,再添加几个球体来供我们的着色器使用,再添加一个平行光来照亮这个场景。创建好场景之后,可以按照如下步骤编写着色器:
- 在Project标签页中,右键单击Assets文件夹,然后选择Create | Folder。
- 将你创建的文件夹重命名为Shaders。重命名方式是右键单击文件夹,然后从弹出的菜单中选择Rename。或者选中文件夹后按快捷键F2(这也是Windows系统下默认的重命名快捷键)。
- 创建另外一个名为Materials的文件夹。
- 右键单击Shaders文件夹,选择Create | Shader。然后右键单击Materials文件夹,选择Create | Material。
- 将新创建的着色器和材质都重命名为StandardDiffuse。
- 在MonoDevelop(Unity默认的脚本编辑器)中双击打开StandardDiffuse着色器。Unity会自动打开该编辑器并且显示对应的着色器代码。
- 现在我们需要声明着色器所在的自定义位置。着色器中的第一行代码就是我们指定给着色器的自定义路径,只有这样Unity才会知道这里有一个着色器,在给材质指定着色器的时候,该着色器才会出现在下拉菜单中。我们已经将路径重命名为“CookbookShaders/StandardDiffuse”,但是你完全可以按照自己的喜好给它换个名字。现在不用担心它有任何依赖。在MonoDevelop中保存着色器,然后返回Unity编辑器。Unity在识别到着色器文件发生改动时,会自动编译着色器相关代码。确保你的着色器代码是这样的:
- 技术上来讲,这是一个基于物理基础渲染(physically-based rendering)的表面着色器。在Unity 5中已经将物理基础渲染作为标准。顾名思义,这种着色器会通过模拟光照到物体上来获得真实感。如果你使用的是之前版本的Unity(比如Unity 4),代码会大不相同。在引入物理基础渲染之前,Unity 4并没有多少精细技术。关于不同类型着色器的介绍会在本书后面章节中详细展开。
- 在创建好着色器之后,我们需要将其关联到一种材质上。选择第4步中创建的名为StandardDiffuse的材质,从Shader下拉菜单中查看Inspector标签页,选择CookbookShaders | StandardDiffuse(如果你使用的路径与本书不同的话,看到的着色器路径也会有所不同)。这个操作就会将之前的着色器指定给该材质,接下来你就可以将这个材质指定给某个物体了。
做完上述步骤之后的例子应该看起来和下面差不多:
现在还没什么好看的,但是我们的着色器开发环境已经准备好了,可以按照需要来修改着色器了。
1.2.3 工作原理
Unity有一些帮助你准备着色器环境的指令,让你事半功倍。只需要简单地单击几下就已经准备好了。其实在表面着色器的背后,有很多元素在协同工作。Unity使用的是Cg着色器语言,但是针对该语言做了很多优化和提升,以帮助你高效地编写着色器代码。表面着色器语言更多的是一种基于组件的编码方式。诸如处理纹理坐标和转换矩阵的事情,Unity都已经为你做好了,所以你不用完完全全从头开始。放在以前,我们在创建着色器的时候要反反复复地编写大量重复代码。随着对表面着色器的了解逐步深入,你自然会对Unity如何使用这些Cg语言相关的底层函数来完成底层图像处理器(GPU)任务感兴趣的。
在简单地修改了一下着色器路径名之后,我们已经得到了一个可以在Unity环境中正常工作的基础漫反射着色器了。我们只改了一行代码,所有的光照和阴影都已经做好了。
1.2.4 参考
Unity 5中内建着色器的源代码是隐藏的,你不能从编辑器中像打开自己的着色器那样打开这些内建着色器。
如果你想知道在哪里可以找到Unity中大量的内建Cg函数,可以到Unity的安装目录,然后进入Unity45EditorDataCGIncludes。在这个目录下,可以找到这些Unity中用到的着色器源码。这些源码本身也是随着时间变化的,如果你想找其他版本的着色器代码,可以去UNITY DOWNLOAD ARCHIVE(https://unity3d.com/get-unity/download/archive )查找,方法是选中正确的版本之后,从下拉菜单中选择Build in shaders,如下图所示。这里应该有三个文件:UnityCG.cginc、Lighting.cginc和UnityShaderVariables.cginc。当前这个着色器会用到所有三个文件。
在第10章中,我们会深入探讨如何使用这些CgInclude来将着色器代码模块化。