Unity着色器和屏幕特效开发秘笈(原书第2版).html.pdf

您所在的位置:网站首页 aabc词语大全100个 Unity着色器和屏幕特效开发秘笈(原书第2版).html.pdf

Unity着色器和屏幕特效开发秘笈(原书第2版).html.pdf

#Unity着色器和屏幕特效开发秘笈(原书第2版).html.pdf| 来源: 网络整理| 查看: 265

《Unity着色器和屏幕特效开发秘笈(原书第2版).html.pdf》由会员分享,可在线阅读,更多相关《Unity着色器和屏幕特效开发秘笈(原书第2版).html.pdf(175页珍藏版)》请在点石文库上搜索。

1、译者序 我从2015年开始接触Unity开发,在此之前接触过很多游戏,也间或见过一些游戏开始时的Unity跳转页面。2014年暴雪发布 了一款卡牌游戏炉石传说,该游戏画风精美,趣味十足,也深深地吸引了包括我在内的千万玩家。更让我吃惊的是,在该游 戏的介绍页面中提到其开发平台使用的正是Unity3D。自此之后我便开始了Unity的学习之旅。 Unity是一个专业的游戏引擎,功能十分强大。但是对于没有接触过任何游戏开发或者没有接触过代码的新手而言,要学会 从头到尾地开发一个游戏还是颇有难度的。本书并不涉及Unity游戏开发的所有方面,而是重点关注游戏开发中颇为晦涩难懂的 着色器。 着色器是游戏表现

2、超强拟实效果的基石。和大千世界中各种各样的材料对应的是,游戏里面也需要有各种各样的着色器及其 组合来对其进行模拟。比如透明的玻璃效果,栩栩如生的动物皮毛效果等。如果读者恰好对这些内容感兴趣,或者需要实现一些 类似的需求,那么本书应该很适合你。受篇幅所限,有一些不是本书主要内容的部分作者也提供了很多资料和文档的链接,非常 有助于你对某些领域加强理解和认识。 就翻译本身而言,虽然我们会尽力细心地审查和校对,但仍难免有所疏忽。如果在阅读过程中发现一些瑕疵或者有争议的地 方,十分欢迎读者联系译者进行核对和改进,以免对大家造成困扰。我的联系方式是SonlyF。 在承接本书翻译之时,恰逢我的儿子刚刚出生。

3、当时除了工作的忙碌之外,还得花一部分业余时间来完成翻译,在此对我爱 人周彩萍和儿子詹小贤道一声感谢,是你们一直以来的理解和支持才让本书得以完成。 占红来 2017年3月北京 前言 本书介绍Unity 5中着色器的创建和后期特效开发。你可以从零开始学习创建最基本的着色器,掌握着色器代码是如何组织 的。开始的基础知识可以有效地“武装”你,让你在后续如体积爆炸、毛皮着色等章节中游刃有余。本版是专门为Unity 5量身定 制的,可以通过使用一些基于物理基础的渲染和全局照明来让你的场景栩栩如生。 在每一章的结尾,你都会获得一些新的技巧,比如改善着色器质量或者提升着色器代码编写效率等。这些章节都是量身定制

4、 的,所以如果你之前已经有了一些经验,完全可以直接跳到你感兴趣的章节来专门学习。对于新手来讲,可以逐章阅读来构筑整 个知识体系。不管使用何种方式,你都会学到制作现代游戏视觉的技术。 在读完本书之后,你手上会有一堆已经做好的着色器,可以在你的Unity3D游戏中使用这些着色器,除此之外你会理解如何 创建新的着色器,如何完成新的特效以及性能优化等。废话不多说,让我们开始吧! 本书主要内容 第1章 会将你引入Unity 4和Unity 5的着色器编码世界。 第2章 介绍表面着色器中的一些非常常用的技术,包括如何给你的模型使用纹理和法线映射。 第3章 深度解析着色器是如何给光照行为建模的。本章会教你如

5、何创建自定义光照模型来模拟一些特殊效果,比如卡通着 色。 第4章 会告诉你基于物理基础的渲染是Unity 5中使用的一种模拟现实的基础技术,会教你如何最大限度地使用好基于物理 基础的渲染,如何使用透明度、反射型表面和全局照明等。 第5章 会教你如何使用着色器来修改物体的几何结构。本章会引入顶点编辑器,使用它可以制作体积爆炸、雪花等生动的 特效。 第6章 解释如何使用抓取功能来制作一些半透明材料形成的变形效果。 第7章 会帮助你对着色器进行一些优化,以保证游戏在各种不同设备上都能正常运转。 第8章 展示如何创建特效和其他一些除了Unity几乎不可能实现的视觉效果。 第9章 会告诉你如何通过后期特

6、效来提升游戏的可玩性,比如夜视效果。 第10章 介绍本书中的很多高级技巧,比如毛皮着色和热度图渲染等。 阅读前的准备工作 下面列出的是使用本书时所必需和可选的一些软件: Unity 5(必需) 一个3D应用程序,比如Maya、Max或者Blender(可选) 一个2D图像编辑软件,比如Photoshop或者Gimp(可选) 本书的读者对象 如果你想用Unity 5来创建你的首个着色器,或者想通过一些专业的后期特效来将你的游戏提升到一个新的高度,这本书就很 适合你,但是可能需要一些对于Unity的基础理解。 本书结构 在本书中,你会发现有几个频繁出现的标题(准备工作、操作步骤、工作原理、更多内容

7、、参考),这几个标题一般是这样 用的: 准备工作 这个部分告诉你预期要做出来的效果是什么,需要准备哪些软件和预先的设置。 操作步骤 这个部分包含了实现的具体步骤。 工作原理 这个部分一般是对操作步骤的详细解释。 更多内容 这一部分由一些相关的附加信息组成,以方便读者对整体内容有更全面的认识。 参考 这一部分会提供一些有用的链接和其他有用信息。 约定 注意 注意以这种方式出现。 技巧 提示和技巧以这种方式出现。 下载示例代码 本书提供相关的一些示例代码文件下载,可以访问http:/ 给你。 下载代码文件的步骤如下: 1.通过电子邮件和密码在上述网站上登录或者注册。 2.移动鼠标到网站顶部的SUP

8、PORT标签处。 3.点击Code Downloads&Errata。 4.输入书名,点击Search按钮。 5.选择你在查找的书籍,下载相关代码文件。 6.从下拉菜单中选择你的购买渠道。 7.点击Code Download。 文件下载之后,请使用如下解压软件进行解压: Windows系统请使用WinRAR/7-Zip,Mac系统请使用Zippeg/iZip/unRarX,Linux系统请使用7-Zip/PeaZip。 下载本书的彩图 我们还提供本书中所用到的截图、图片的彩图PDF文件,这些彩图可以让你更好地理解输出的细微差别。你可以 从https:/ 第1章 创建你的第一个着色器 本章会讨论

9、一些游戏开发着色流程中广泛使用的漫反射技术。在这一章中,你会学到如下内容: 创建基本的标准着色器 从Unity 4向Unity 5迁移 给着色器添加属性 在表面着色器中使用属性 1.1 引言 首先让我们想象一个均匀涂白的立方体。这个立方体的各个面上的颜色都是一样的,但是随着光照方向的不同,以及观察者 视角的不同,各个面上呈现出来的影像都是不同的。在3D图像技术中,这种级别的拟实效果是通过着色器完成的。着色器是一 种特殊的程序,主要用来模拟光照效果。一个木质立方体和一个金属立方体可以共用一个同样的3D模型,然后使用着色器就可 以让它们看起来大不相同。这一章会循序渐进地介绍Unity中的着色器代码

10、。如果你之前没有怎么接触过着色器,经过这一章你 就会理解着色器是什么、它们是如何工作的以及怎么对着色器进行自定义了。 在本章的结尾,你应该已经知道了如何创建一个有些基本功能的基础着色器。有了这些知识之后,你就基本上能随心所欲地 创建表面着色器了。 1.2 创建基本的标准着色器 每一个Unity开发人员都应该熟悉模块(component)的概念。游戏中的所有物体都会包含一系列模块,这些模块会影响它 的外观和行为。一般而言脚本(script)会决定物体的行为,而渲染器(renderer)则决定了它在屏幕上呈现出来的外观。 Unity有多种渲染器,根据我们想要显示的物体类型的不同,会使用不同的渲染器

11、。每个3D模型一般都会有一个名为 MeshRenderer的渲染器。一个物体可以只有一个渲染器,但是一个渲染器可以有多种材质(material)。每一种材质就是一个 着色器呈现出来的外观,因此着色器也就是3D图像食物链的最后一环。这些模块之间的关系可以从下图看出: 理解了这些模块之间的不同十分有助于我们理解着色器是如何工作的。 1.2.1 准备工作 在准备学习这一部分时,你需要运行Unity 5并且创建一个新的项目(project)。在本书配套的代码里面也包含这样一个初 始化好的Unity项目,你可以使用这个项目作为基础,随着后续章节的深入学习来自定义你的着色器。准备好这两样东西之后, 实时着

12、色的精彩世界已经为你敞开了。 1.2.2 操作步骤 在开始做着色器之前,可以先创建一个小的场景作为基础。创建场景的步骤是在Unity编辑器中选择GameObject|Create Empty。在这个场景中,可以创建一个简单的地平面,再添加几个球体来供我们的着色器使用,再添加一个平行光来照亮这个场 景。创建好场景之后,可以按照如下步骤编写着色器: 1.在Project标签页中,右键单击Assets文件夹,然后选择Create|Folder。 注意 如果你使用的是本书配套的项目,可以直接跳到第4步。 2.将你创建的文件夹重命名为Shaders。重命名方式是右键单击文件夹,然后从弹出的菜单中选择Re

13、name。或者选中文件 夹后按快捷键F2(这也是Windows系统下默认的重命名快捷键)。 3.创建另外一个名为Materials的文件夹。 4.右键单击Shaders文件夹,选择Create|Shader。然后右键单击Materials文件夹,选择Create|Material。 5.将新创建的着色器和材质都重命名为StandardDiffuse。 6.在MonoDevelop(Unity默认的脚本编辑器)中双击打开StandardDiffuse着色器。Unity会自动打开该编辑器并且显示 对应的着色器代码。 注意 你会看到Unity已经为我们的着色器添加了一些基础代码。默认情况下,这个基础

14、漫反射着色器会接受一个纹 理。你可以在这些基础代码的基础上,快速自定义自己的着色器。 7.现在我们需要声明着色器所在的自定义位置。着色器中的第一行代码就是我们指定给着色器的自定义路径,只有这样 Unity才会知道这里有一个着色器,在给材质指定着色器的时候,该着色器才会出现在下拉菜单中。我们已经将路径重命名 为“CookbookShaders/StandardDiffuse”,但是你完全可以按照自己的喜好给它换个名字。现在不用担心它有任何依赖。在 MonoDevelop中保存着色器,然后返回Unity编辑器。Unity在识别到着色器文件发生改动时,会自动编译着色器相关代码。确 保你的着色器代码是

15、这样的: 8.技术上来讲,这是一个基于物理基础渲染(physically-based rendering)的表面着色器。在Unity 5中已经将物理基础渲 染作为标准。顾名思义,这种着色器会通过模拟光照到物体上来获得真实感。如果你使用的是之前版本的Unity(比如Unity 4),代码会大不相同。在引入物理基础渲染之前,Unity 4并没有多少精细技术。关于不同类型着色器的介绍会在本书后面章节 中详细展开。 9.在创建好着色器之后,我们需要将其关联到一种材质上。选择第4步中创建的名为StandardDiffuse的材质,从Shader下 拉菜单中查看Inspector标签页,选择Cookboo

16、kShaders|StandardDiffuse(如果你使用的路径与本书不同的话,看到的着色 器路径也会有所不同)。这个操作就会将之前的着色器指定给该材质,接下来你就可以将这个材质指定给某个物体了。 注意 将材质指定给物体的步骤是:从Project标签页中将材质拖曳到场景中的物体上。或者将材质拖曳到物体的 Inspector标签页中也可以。 做完上述步骤之后的例子应该看起来和下面差不多: 现在还没什么好看的,但是我们的着色器开发环境已经准备好了,可以按照需要来修改着色器了。 1.2.3 工作原理 Unity有一些帮助你准备着色器环境的指令,让你事半功倍。只需要简单地单击几下就已经准备好了。其实

17、在表面着色器的 背后,有很多元素在协同工作。Unity使用的是Cg着色器语言,但是针对该语言做了很多优化和提升,以帮助你高效地编写着色 器代码。表面着色器语言更多的是一种基于组件的编码方式。诸如处理纹理坐标和转换矩阵的事情,Unity都已经为你做好了, 所以你不用完完全全从头开始。放在以前,我们在创建着色器的时候要反反复复地编写大量重复代码。随着对表面着色器的了解 逐步深入,你自然会对Unity如何使用这些Cg语言相关的底层函数来完成底层图像处理器(GPU)任务感兴趣的。 注意 Unity中所有文件都是从它们所在的文件夹中独立引用的。我们可以在Unity编辑器中移动着色器和材质文件的位 置,它

18、们之间的链接是不会被破坏的。但是不能把文件移出Unity编辑器,一旦移出了Unity就没办法跟踪到这些文件及其引用的 更新了。 在简单地修改了一下着色器路径名之后,我们已经得到了一个可以在Unity环境中正常工作的基础漫反射着色器了。我们只 改了一行代码,所有的光照和阴影都已经做好了。 1.2.4 参考 Unity 5中内建着色器的源代码是隐藏的,你不能从编辑器中像打开自己的着色器那样打开这些内建着色器。 如果你想知道在哪里可以找到Unity中大量的内建Cg函数,可以到Unity的安装目录,然后进入 Unity45EditorDataCGIncludes。在这个目录下,可以找到这些Unity中

19、用到的着色器源码。这些源码本身也是随着时间变化 的,如果你想找其他版本的着色器代码,可以去UNITY DOWNLOAD ARCHIVE(https:/ unity/download/archive)查找,方法是选中正确的版本之后,从下拉菜单中选择Build in shaders,如下图所示。这里应该有 三个文件:UnityCG.cginc、Lighting.cginc和UnityShaderVariables.cginc。当前这个着色器会用到所有三个文件。 在第10章中,我们会深入探讨如何使用这些CgInclude来将着色器代码模块化。 1.3 从Unity 4向Unity 5迁移 不可否认,

20、电子游戏中的图像技术在过去的10年中发生了翻天覆地的变化。每一个包含前沿技术的新游戏的面世,带给我 们的都是无与伦比的实时超现实体验。同样,在Unity中着色器及其相关技术也是日新月异,这种不断的更新换代很多时候也是 大家产生迷惑的根源之一。在Unity 5之前,主要有两种着色器被采用:漫反射和高光着色器。顾名思义,这两种着色器分别用 在无光和高光材料上。如果你已经用了Unity 5,可以跳过这一部分,这部分内容主要解释如何使用Unity 5重现这些之前的特 效。 1.3.1 准备工作 开始这一部分之前,我们需要准备一个Unity 4的环境。在Unity 4中同样有一些预先提供好的内建着色器。

21、如果你是开始开 发一个新游戏,毫无疑问你会使用最新版本的Unity,但是如果是个遗留项目,很有可能之前使用的就是一些低版本的Unity。在 做版本迁移的时候一定要格外小心。在Unity引擎中,很多东西都发生了变化。而且就算是某些内建着色器能正常工作,脚本也 可能变了。如果你准备迁移整个工作空间,首要的是要做好备份。很重要的一点是:要记住仅仅保存资源和场景文件是远远不够 的,Unity中大量的配置文件保存在其元数据中。做迁移备份时最安全的方式是将包含项目的整个文件夹拷贝一份。最好的方式 是从资源管理器(Windows)或者Finder(Mac)中将整个文件夹物理拷贝一份。 1.3.2 操作步骤

22、如果你想将之前做好的着色器迁移到Unity 5,有两种方式:自动升级项目或统一切换到标准着色器。 自动升级 这是最简单的一种办法。Unity可以导入之前版本的项目并对其进行升级。你会发现,升级转换完之后,就不能用Unity 4 了,哪怕你的资源文件一个都没有改动。原因是Unity的元数据已经做过转换了。自动升级的步骤是打开Unity 5,单击OPEN OTHER来选择老版本项目所在的文件夹。Unity会询问你是否需要进行转换。单击Upgrade按钮开始转换。Unity会重新导入你 的所有资源文件,重新编译脚本。如果你的项目很大的话,这个过程可能持续数小时。转换完成之后,你就会发现一些改变。例

23、如材质的Inspector栏中可能会从Bumped Diffuse变成了Legacy Shader/Bumped Diffuse。 注意 即使Unity 4中的诸如漫反射、镜面反射等着色器都已经废弃了,Untiy 5还是保持了良好的向下兼容性。你可以在 材质的下拉菜单中的Legacy Shaders目录下找到这些遗留着色器。 使用标准着色器 如果不想继续使用遗留的着色器,可以使用Unity 5中新的标准着色器来取而代之。在替换之前,需要记住一点:这两者是 基于不同的光照模型来构建的,因此肯定会影响材质本身的外观。Unity 4中有超过80种不同的内建着色器,总共分为6个大类 (普通、透明、透明

24、剪切、自照明和反射类等)。在Unity 5中,全都被标准着色器取代。不幸的是,并没有什么魔法可以将你 的着色器直接转换成标准着色器,但是你可以通过下面这个表格来理解如何配置Unity 5中的标准着色器来模拟Unity 4中那些遗 留的着色器: 可以使用Inspector中的Shader下拉菜单来让老的材质使用这些着色器,只需要选择合适的标准着色器即可。如果你的老着 色器使用了纹理、颜色和法线映射,这些属性会自动应用在新的标准着色器中。你可能还是需要配置一些标准着色器的参数来让 它跟之前的光照模型保持一致。下图展示的是一个斯坦福兔子在旧的漫反射着色器(右图)、转换成标准着色器(左图)和光滑 度(

25、Smoothness)调为0的标准着色器(中图)中的显示效果: 迁移自定义着色器 如果你在Unity 4中写过自定义着色器,大部分情况下在Unity 5中可以直接使用这些代码。除此之外,Unity 5中对着色器 的工作方式做了些微调,因此可能会引起一些错误或者矛盾。最重要的一点修改是光的亮度。Unity 5中的光亮度是Unity 4中的 两倍。所有老的着色器在重写的时候都考虑到了这一点。如果你升级一些内建着色器,或者切换到标准着色器,不会发现任何问 题。但是如果你重写过自己的光照模型,需要注意新环境下光亮度不再需要乘以2倍了。下面这段代码可以确保这一点: 如果你没写过着色器也不用害怕。光照模型

26、相关内容会在第3章中详细解释。 注意 相比于Unity 4,Unity 5在着色器的处理方式上还有一些其他方面的改动。你可以 在http:/ Guide5-Shaders.html的Shaders in Unity 5.0中找到更详细的改动说明。 1.3.3 工作原理 制作着色器始终要考虑性价比。拟实效果好的着色器需要占用大量的计算资源,在某些设备上可能会引起延时。一般而言特 效最好应用在一些非常重要、缺之不可的地方。如果某种材质并不需要高光反射,那么就没有必要专门用一个着色器来计算高光 效果。这也是Unity 4中引入了如此多不同的着色器的原因之一。Unity 5中的标准着色器理论上可以替代

27、之前的所有着色器,因 为标准着色器集合了法线映射、透明和反射功能。但是在Unity 5中进行了某些合理的优化,以确保只计算那些真正必需的特 效。如果你的标准材质并没有反射效果,那么Unity 5是不会计算这一部分的。 除此之外,标准着色器主要是为拟实材质而设计的。相对而言,老的漫反射和高光着色器并不是为拟实材质而设计的。这也 是从老的着色器迁移到标准着色器时,需要对物体的渲染方式做一些修改的原因之一。 1.3.4 参考 第3章深入讲解了漫反射着色器和高光着色器是如何工作的。即使在Unity 5中这些着色器已经废弃了,理解它们的原理对 于你设计新的光照模型也是大有裨益的。 第4章将会向你展示如何

28、释放Unity 5中的标准着色器的更多潜力。 1.5 在表面着色器中使用属性 我们已经创建了一些属性,现在在着色器中开始试着把这些属性用起来,通过这些属性让材质的微调过程更加高效。 可以通过材质的Inspector标签页得到这些属性的值,因为我们给属性绑定了一个变量名。但是在通过变量名访问属性值之 前,要先准备一些东西。 1.5.1 操作步骤 下面是在表面着色器中使用属性的步骤: 1.因为我们在1.2节中已经删除了_MainTex,所以开始之前,先移除下面几行代码: 2.接下来,在着色器中的CGPROGRAM行之下添加如下代码: 3.第2步完成之后,可以在着色器中使用属性的值了。我们先将_Co

29、lor属性和_AmbientColor属性的值相加之后,赋给 o.Albedo,所以在surf()函数中添加下面的代码: 4.最终的着色器代码应该看起来像下面这样。如果你在MonoDevelop中保存代码然后在Unity中打开,着色器会被自动编 译。如果没有错误的话,可以修改材质的环绕色和发光色了,也可以通过滑块来增加最终颜色的饱和度等值。就是这么智能! 提示 下载示例代码 可以通过账号在http:/下载你购买的Packet书籍的示例代码文件。如果你通过其他途径购买了本书,可以 通过访问http:/ 注意 pow(arg1,arg2)是一个内建函数,表示的是数学上的幂函数,第一个参数是底数,第

30、二个参数是幂次数。 有关pow函数的其他内容,可以参见Cg的教程。Cg教程是一个学习着色和了解Cg着色语言中有哪些可用函数的不错的免费资 源。地址为:http:/ 下面这张截图是使用我们新添加的属性,在Inspector标签页微调了颜色和饱和度之后得到的结果。 1.5.2 工作原理 当你在Properties代码块中声明一个新的属性时,实际上是在给着色器提供一种获取材质的Inspector标签页中值的方式, 这个值存储在变量名对应的存储单元中。在这个例子中,_AmbientColor、_Color和_MySliderValue就是所有我们用来存储微 调值的变量。为了能在SubShader代码块

31、中使用这些值,需要创建三个与属性变量同名的变量。这样就能给二者自动建立一种 联系,以便它们知道是在围绕同一个数据做修改。此外,它还声明了我们想存储在子着色器变量中的数据类型,这也给我们日后 的优化带来了不少方便。 如果你创建了子着色器变量,就可以在surf()函数中使用它们了。在这里,我们想将_Color和_AmbientColor变量加到一 起作为幂函数的底,而将_MySliderValue变量作为幂函数的幂次数。 绝大部分着色器都是从标准着色器开始的,然后逐步调整到想要的样子。我们现在已经创建好了一个基础的表面着色器,通 过这个表面着色器你可以创建任何你想要的漫反射组件。 注意 材质是资源

32、的一种,也就意味着游戏运行时任何一点针对材质的修改都是永久性的。如果你误操作了某个属性的 值,可以通过Ctrl+Z来撤销。 1.5.3 更多内容 和其他的编程语言差不多,Cg不允许代码错误。此时,如果你的代码中有笔误,着色器是不会正常显示的。如果发生了这 种情况,你的材质会呈现无任何涂层的洋红色: 如果脚本不能编译,Unity会阻止游戏输出甚至阻止游戏运行。相反,着色器中的错误并不会阻止游戏运行。 如果你的某个着色器呈现洋红色,就要花点时间研究问题在哪里了。如果选中出错的着色器,会在Inspector标签页中看到 一个错误列表: 除了显示出错行之外,错误消息也同时在告诉你应该去这里修复问题。上

33、面截图里的错误信息是在删除SubShader代码块 中的sampler2D_MainTex变量的时候产生的。但是错误出现在首次想要访问这个变量的地方。 找到并且修复问题的过程称为调试,大家常犯的错误如下: 少个括号。如果你在某个部分忘了一个反括号,编译器会在这一部分文本的最后、最前或者某个新的部分处报错。 少了分号。这是最为常见的一种错误,也是最容易发现和修复的。报错信息通常出现在下一行。 在Properties代码块中定义了一个属性,但是没有在SubShader代码块中标明为一个变量。 与C#脚本混淆了,Cg中的浮点数并不需要在后面加一个f,比如1.0而不是1.0f。 着色器提供的报错信息可

34、能非常难懂,特别是在某些有特别严格的语法约束的时候。如果你不懂报错信息的意思,最好在网 上搜一搜。Unity论坛里面有很多开发者,他们很有可能碰到或者修复过你现在碰到的问题。 1.5.4 参考 表面着色器及其属性的更多内容放在第2章中。如果你想知道着色器火力全开的时候能做些什么,可以看看第10章,这一章 有本书中所覆盖的大部分高级着色技术。 第2章 表面着色器和纹理映射 在这一章中,会研究表面着色器。我们会从一个非常简单的无光材料开始,最后做出一个全息投影和高级地形混合特效。我 们还可以用纹理来制作动画、混合或者其他一些特效。在这一章中,你会学到如下内容: 漫反射着色 使用包装数组 给着色器添

35、加纹理 通过修改UV值来滑动纹理 法线映射 创建透明材质 创建全息着色器 打包和混合纹理 在地形周围创建圆环 2.1 引言 我们在第1章中已经对表面着色器进行了初步讲解,表面着色器是Unity中主要使用的一种着色器。本章会深入探讨表面着 色器及其工作原理。一般来讲,使用每一个表面着色器都需要两个基本步骤:首先需要给你想描述的材质指定特殊的物理属性, 比如其漫反射颜色、光滑度、透明度等。这些物理属性会在一个名为表面函数(surface function)的函数中进行初始化,存储 在一个名为表面输出(surface output)的结构中。第二步是surface output会被传递给光照模型(l

36、ighting model)。光照模 型是一个特殊的函数,该函数还依赖于场景中周围的光照信息。所有这些参数会被用来计算模型的每一个像素上最终的颜色。光 照函数是着色器的这部分计算的根源,因为光照函数决定了光线在接触到材质时的行为。 下面这个图简单总结了一下表面着色器的工作原理。自定义光照模型的内容会在第3章中展开。第5章主要关注顶点编辑 器。 2.2 漫反射着色 在开始学习纹理映射之前,我们需要先理解漫反射着色是怎么工作的。某些物体的颜色比较均匀,表面很光滑,但是又不是 光滑到那种像镜子一样光亮的程度。这种非反光材料最好的渲染方式就是使用漫反射着色器。虽然在真实世界中纯漫反射材料本 身并不存在

37、,但在游戏世界中漫反射着色器是一种大量用到的相对廉价的着色方式。 2.2.1 准备工作 创建漫反射着色器有多种方式。最快的一种方式是从Unity 5的标准着色器开始,然后编辑标准着色器,移除所有纹理。在 第1章中我们就是这么做的。 2.2.2 操作步骤 我们从标准着色器开始,按照下面的步骤逐步进行: 1.删除除_Color之外的所有属性: 2.在SubShader部分,删除_MainTex、_Glossiness和_Metallic变量。注意不要删除uv_MainTex,因为Cg不接受空的输 入。这个值会被忽略。 3.删除surf()函数的函数体,用下面的代码替换: 4.你的着色器应该看起来是

38、这样的: 因为该着色器是在一个标准着色器的基础上修改的,它会使用基于物理基础的渲染方式来模拟光照行为。如果你想做一种非 拟实的外观,可以直接修改第一个#pragma指令来让其使用Lambert而不是Standard。如果你这么做了,还应该将 SurfaceOutputStandard替换为SurfaceOutput。 2.2.3 工作原理 着色器中,材质的渲染属性和光照模型之间是通过表面输出来通信的。表面输出是对当前光照模型所需的所有参数的一个封 装。所以你应该能理解不同的光照模型需要不同的表面输出结构了。下面列出了Unity 5中三种主要的表面输出结构。 SurfaceOutput结构有如下

39、属性: fixed3Albedo:表示材质的漫反射颜色。 fixed3Normal:如果写的话表示切面法线。 fixed3Emission:表示材质发射的颜色(该属性在标准着色器中声明为half3)。 fixed Alpha:表示材质的透明度。 halfSpecular:表示光亮度,值从0到1。 fixed Gloss:表示光强度。 SurfaceOutputStandard结构有如下属性: fixed Albedo:表示材质的基础颜色(表示是漫反射还是高光)。 fixed3Normal。 half3Emission:该属性声明为half3,而在SurfaceOutput中名字是fixed3。

40、 fixed Alpha。 half Occlusion:表示遮挡,默认是1。 half Smoothness:表示光滑度,0表示粗糙,1表示光滑。 half Metallic:0表示非金属,1表示金属。 SurfaceOutputStandardSpecular结构有如下属性: fixed3Albedo。 fixed3Normal。 half3Emission。 fixed Alpha。 half Occlusion。 half Smoothness。 fixed3Specular:表示高光颜色,与SurfaceOutput结构中的Specular属性有很大不同,这里可以指定一种颜色而非单一

41、值。 正确使用表面着色器很重要的一点是用正确的值初始化表面输出结构。 2.3 使用包装数组 简单来讲,着色器中的代码需要在屏幕的每一个像素上执行,这也是为什么GPU现在都需要优化成并行计算的。同样的道 理,在Cg中的标准变量类型和操作符也得考虑这些优化。理解这些原理不仅有助于正确使用着色器,而且可以帮助我们写出更 优的代码。 2.3.1 操作步骤 在Cg中有两种类型的变量:单一值变量和包装数组。后者很容易通过名字识别出来,因为通常会在名字后面加一个数,比 如float3或者int4。顾名思义,这种包装数组类型的变量类似于结构体,每一个数组包含数个单一值。Cg将其称为包装数组,尽 管这种结构并不

42、是传统意义上的数组。 包装数组的元素可以作为一个普通结构访问到,一般称之为x、y、z和w。然而Cg还给这些元素提供了一些其他的名字,比 如r、g、b、a等。使用xyzw和rgba是没有区别的,但是对于读者而言却有很大差异,因此应该选择合适的方式让代码更加表 义。其实着色器编码通常是处理一些位置和颜色的计算。你可能已经在标准着色器中见过了: 在这一行代码中,o是一个结构体,_Color是一个包装数组。这也是为什么Cg不允许将两种方式混着用:比如不能使用 _Color.xgz。 包装数组的另外一个不同于C#的重要功能是调和(swizzling)。Cg也可以通过简单一行代码来处理和重新排序包装数组中

43、 的元素。再看一个标准着色器中的例子: Albedo是fixed3类型的,也就是说其包含三个fixed类型的值。然而_Color是定义为fixed4类型的,如果直接将Color赋值给 Albedo会出现编译错误,因为类型不匹配。C#中的实现方式会是这样的: 但是在Cg中可以使用一种简化方式: Cg还可以对元素重新排序,比如写成_Color.bgr可以将红色成分和蓝色成分进行对调。 最后,如果将单一值赋给包装数组,则这个单一值会填充数组的每一个元素: 这一特性又称为涂抹(smearing)。 调和也可以用在表达式的左边,以重写包装数组的部分元素: 这种情况称为遮罩(masking)。 包装矩阵

44、调和特性真正大显身手的地方是用在包装矩阵上。Cg接受矩阵类型的声明,比如float44表示一个浮点型数据构成的4行4 列的矩阵。你可以通过_mRC标注来访问矩阵的某个具体元素,其中R表示行号,C表示列号: _mRC标注可以链式调用: 使用中括号可以选择一整行: 2.3.2 参考 包装数组可以说是Cg中最酷炫的特性之一,你可以访问下列网址查看关于包装数组的更多内 容:http:/ 2.4 给着色器添加纹理 在模拟现实效果方面,纹理可以让着色器迅速生动起来。为了高效使用纹理,我们需要理解二维图像是如何映射成三维模型 的。这个映射过程称为纹理映射。为了进行纹理映射,我们需要在着色器和想要应用纹理的三

45、维模型上下点工夫。模型事实上是 由三角形组成的,三角形的每一个顶点可以存储着色器可以访问的数据。UV数据是顶点中存储的诸多重要信息之一。UV数据由 两个坐标组成,也就是U和V,取值范围为0到1,它们表示了二维图像中像素映射到顶点时的XY坐标。UV数据只是给顶点用 的,三角形内部其他位置上的值则是GPU根据差值算法按照一定的间隔比例去纹理上取的值。下图展示了二维纹理是如何映射 到一个三维模型的基础三角形上去的。 UV数据保存在三维模型中,并需要用专门的建模软件才可编辑。某些模型没有UV组件,也就不能支持纹理映射了。比如之 前举例的那个斯坦福兔子最开始就没有UV组件。 2.4.1 准备工作 在这一

46、节中,需要一个有UV数据的三维模型及其纹理。在开始之前需要将这二者导入Unity中。你可以直接将其拖曳到 Unity编辑器中。标准着色器默认支持纹理映射,所以我们会用这个标准着色器来解释纹理映射是怎么工作的。 2.4.2 操作步骤 使用标准着色器给模型添加纹理非常简单,步骤是: 1.创建一个新的名为TexturedShader的标准着色器。 2.创建一个新的名为TexturedMaterial的材质。 3.通过拖曳将着色器指定给材质。 4.选中材质后,将纹理拖曳到名为Albedo(RGB)的空长方形中。如果你按照这个步骤进行的话,材质的Inspector标签页 应该看起来像这样: 标准着色器知

47、道如何通过UV数据将二维图像映射到三维模型上。 2.4.3 工作原理 当标准着色器在材质的审查器(inspector)中被使用时,纹理映射背后的过程对于开发人员是完全透明的。如果我们想理 解它是如何工作的,需要深入看一看TexturedShader。从Properties部分来看,可以发现Albedo(RGB)纹理实际引用的代码 是_MainTex: 在CGPROGRAM部分,该纹理被定义为sampler2D二维纹理的标准类型: 下一行代码是一个名为Input的结构体。这是表面函数的输入参数,这个输入参数包含一个名为uv_MainTex的包装数组: 每次surf()函数被调用时,Input结构

48、会包含三维模型需要渲染的某一个特殊点的_MainTex的UV值。标准着色器会识别 出uv_MainTex引用的是_MainTex的值,并且会自动对其进行初始化。如果你对于UV值是如何从三维模型映射到二维纹理上的 比较感兴趣,可以看看第3章的内容。 最后,表面函数的第一行中,UV数据被用来对纹理进行采样: 这个过程是通过Cg的tex2D()函数来实现的。该函数接受一个纹理和UV,并返回像素在该位置的颜色值。 注意 UV坐标都是从0到1,其中(0,0)和(1,1)表示的是两个对顶角。不同的实现方式会把UV和不同的角联系 起来。如果你的纹理看起来有点翻转了,试着颠倒一下V的值。 2.4.4 更多内容 当你向Unity导入一个纹理的时候,其实是在给sampler2D准备一些它需要用到的属性。最重要的是Filter(过滤)模式,过 滤模式会决定纹理采样时颜色是如何插值的。一般而言,UV数据不会准确指向像素的中心,而其他一些时候你可能需要在最接 近的像素间进行插



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3