表面着色器和纹理贴图

第二章 表面着色器和纹理贴图 在这一章节,我们将会探索表面着色器的使用。我们会用一个非常简单的磨砂材质开始讲起,然后会在后面讲解全息投影和高级的地形混合。 我们将能够使用纹理制作动画效果,混合等,或者用着色器去驱动我们想要的属性。在这一章你将会学习下面一些表面着色器的使用方法: 漫反射的着色处理 使用包组 向着色器添加纹理 通过改变UV值来移动纹理 法线贴图 创建一个带透明度的材质 创建一个有全息效果的着色器 纹理的压缩和混合 在地形的表面绘制一个圆 介绍 我们在第一章,创建你的第一个着色器 已经介绍了表面着色器,这是Unity引擎中的主要着色器类型。在这一章我们将更详细的向你展示它到底是什么以及它具体是如何工作的。通常来说,每个表面着色器都有两个重要的步骤。 首先,你需要在材质中描述你想指定的物理属性,比如漫反射的颜色,光滑度和透明度等。 这些属性将会在一个叫表面函数 surface function的函数中初始化并且保存在一个叫表面输出 surface output的结构体中。其次,表面输出 surface output结构体传入到一个光照模型 lighting model中。这是一个特殊的函数,这个函数会获取场景周围的光照信息。所有获得的这些信息将会被用于去计算你的模型最终在每一个像素点上最终呈现出来的颜色。这个光照函数就是着色器真正进行计算的地方,而正是这部分代码,决定了使用这个着色器材质的光照表现。下面的示意图简单的总结了表面着色器时如何工作的。在第三章,理解光照模型 将探索自定义光照模型,当学习到第五章,顶点函数 会着重讲解顶点修改器: 漫反射的着色处理 在我们开始学习纹理贴图之前,了解漫反射材质时如何工作的显得尤为重要。具体的一些物体也许会有统一的光照和光滑的表面,但是可以还是不够光滑来反射光线。磨砂材质是漫反射着色器使用的一个典型代表 。然而我们现实世界中,完全漫反射材质是不存在的;漫反射着色器是一种成本相对比较低的实现方式并且在低多边形风格中有着大量的应用。 始前准备 有好几种方式来创建你自己的漫反射着色器。最快的一个方式是在Unity5中创建一个表面着色器然后编辑它,移除所有的纹理,跟我们前面学习的第一章,创建你的第一个着色器 类似。 操作步骤 让我们开始创建我们的标准着色器,首先在Unity中新建一个标准着色器,然后按照下面的步骤进行修改: 首先在着色器的属性列表移除除**_Color**之外的所有属性: _Color ("Color", Color) = (1,1,1,1) 在SubShader{}代码块中,移除_MainTex,_Glossiness和**_Metallic这三个变量。但是你不能删除uv_MainTex** 这个变量,因为Cg着色器语言不允许输入结构体为空。这个值会被Unity简单的忽略。 删除**surf()**函数内代码内容并且把下面代码放在里面: o.Albedo = _Color.rgb; 最终,你的着色器代码应该如下所示: Shader "CookbookShaders/Diffuse" { Properties { Color ("Color", Color) = (1,1,1,1) } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf Standard fullforwardshadows #pragma target 3.0 struct Input { float2 uv_MainTex; }; fixed4 _Color; void surf (Input IN, inout SurfaceOutputStandard o) { o.Albedo = _Color.rgb; } ENDCG } FallBack "Diffuse" } 当这个着色器从标准着色器修改调整之后,那么这个着色器将会使用基于物理原理的渲染去模拟光在模型表面的表现。如果你想试着获得一个看起来不那么真实表现的话,你可以直接修改**#pragma部分,这样着色器就可以使用Lambert而不是Standard**。如果你这样修改了的话,那么你还应该用SurfaceOutput替换掉**SurfaceOutputStandard **。 按照书上的意思,应该是改成下图所示: ...

October 24, 2020 · 1 min · 196 words · Link

使用表面着色器的属性

使用表面着色器的属性 现在我们已经为着色器创建了一些属性,这里我们将要正式的把这些属性跟着色器关联起来,这些属性就像着色器的调节器一样,可以让材质拥有更好的交互性。 我们可以在材质的**检查器面板(Inspector tab)**使用着色器属性的值,因为我们为这个属性添加了一个变量名,但是如果你在着色器代码中想要通过这个变量名来获得这个值,我们仍然还有很多事情要做。 操作步骤 下面的步骤展示了如何在表面着色器中使用属性: 开始之前,我们先删除下面的行的代码,就好像我们在章节创建一个基本的标准着色器中删除属性的操作步骤一样,删除**_MainTex**属性: _MainTex ("Albedo (RGB)", 2D) = "white" {} sampler2D _MainTex; fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; 下一步,添加下面这些行的代码到着色器代码中,添加到CGPROGRAM下面, add the following lines of code to the shader, below the CGPROGRAM line: float4 _AmbientColor; float _MySliderValue; 当第二部完成之后,我们就可以在着色器中使用属性的值了。我们把**_Color属性的值与_AmbientColor值相加,并且把两者的结果赋值给o.Albedo**。为了达成目的,我们需要在着色器代码中的**surf()**方法中添加如下代码: void surf (Input IN, inout SurfaceOutputStandard o) { fixed4 c = pow((_Color + _AmbientColor), _MySliderValue); o.Albedo = c.rgb; o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } 最终你的代码将会是如下所示。如果你在你的VSCode中保存好然后返回Unity编辑器,你的着色器将会重新编译。 如果没有什么错误,那么现在你可以修改材质的环境光和自发光的颜色,当然也可以通过滑动条增加最终颜色的饱和度。听巧妙的噢。 Shader "CookbookShaders/StandardDiffuse3" { // We define Properties in the properties block Properties { _Color ("Color", Color) = (1,1,1,1) _AmbientColor("Ambient Color", Color) = (1,1,1,1) _MySliderValue("This is a Slider", Range(0,10)) = 2.5 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 // We need to declare the properties variable type inside of the //CGPROGRAM so we can access its value from the properties block. CGPROGRAM #pragma surface surf Standard fullforwardshadows #pragma target 3.0 struct Input { float2 uv_MainTex;}; fixed4 _Color; float4 _AmbientColor; float _MySliderValue; void surf (Input IN, inout SurfaceOutputStandard o) { // We can then use the properties values in our shader fixed4 c = pow((_Color + _AmbientColor), _MySliderValue); o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" } 提示 下载示例代码 你可以在Packt网站登陆后,下载所有已购买书籍的所有示例代码文件,下载地址:http://www.packtpub.com。如果你是在别处购买的书,那么请访问: http://www.packtpub.com/support然后注册,以便通过邮件直接获取相关的代码文件。 ...

September 2, 2020 · 2 min · 239 words · Link

给着色器添加属性

给着色器添加属性 着色器的属性对于着色器管线来说时非常重要,因为艺术家或者用户想要添加纹理或者调整着色器的值都是通过著色器的属性来修改的。着色器的属性在材质的检查器面板(Inspector )中会提供GUI,提供图形界面让玩家去调整一个着色器,不用打开额外的编辑器。用Visual Studio Code打开你的着色器代码,从第2行到第7行的代码块就是着色器的属性(Properties )。当前的这个着色器,他会有一个叫**_MainTex的属性。如果你查看使用了这个着色器的材质,你能注意到着色器的检查器面板(Inspector )中有一个纹理(texture )**的GUI元素。着色器中的这行代码为我们创建了这个GUI元素。还有就是,Unity工作人员通过编码方式和努力的迭代,让你改变属性的这个过程非常快速高效。 始前准备 让我们来了解一下这个过程在标准漫反射(StandardDiffuse)着色器中是如何工作的,为此我们要创建自己的属性并且学习更多相关的着色器语法。比如我们会修改之前创建的着色器。在这个修改的着色器中,不适用纹理,而是仅仅使用能从检查器面板(Inspector)直接修改的颜色和其他的属性。开始之前,我们先复制一个标准漫反射(StandardDiffuse)着色器。你可以在项目(Project)面板中选中它,然后按Ctrl + D。这样就会复制一份新的StandardDiffuse 1的着色器。【书上的写法有问题,在Inspector面板根本不能选中复制,应该在项目面板中选中在复制】 注意 你最好给你复制的这个着色器在第一行代码处给它一个恰当的名字。比如,Shader “CookbookShaders/StandardDiffuse”可以告诉Unity这个着色器叫StandardDiffuse并且把它分组到CookbookShaders这个着色器组。如果你是通过Ctrl + D复制的着色器,你新复制的这个着色器跟被复制的着色器就会用相同的名字和分组。为了避免混淆,一定要记得复制着色器代码之后,在第一行那里修改着色器的名字,给一个不会重复的名字。 操作步骤 当StandardDiffuse2这个着色器准备好后,我们就可以开始修改它的属性了: 在着色器的**属性(Properties )**块中,删除着色器中下面的属性代码,整行删除: _MainTex ("Albedo (RGB)", 2D) = "white" {} 当我们移除这个必要的属性后,着色器不会被编译直到所有跟**_MainTex**的代码都被移除。然我们删除另外有引用的代码: sampler2D _MainTex; 原始的着色器使用**_MainTex给游戏模型上色。为了改变这个,我们替换掉surf()**方法的第一行代码,通过如下代码: fixed4 c = _Color; 当你修改完成之后,返回Unity,然后着色器会被重新编译, 之后我们的材质检查器面板中就没有纹理选择这一选项了。 为了完成这个着色器的调整,让我们添加一个额外的属性给着色器,看看会有什么效果。输入下面的代码: _AmbientColor ("Ambient Color", Color) = (1,1,1,1) 我们在材质的检查器面板中添加了另一个颜色选项。现在,让我们来额外添加另一种类型的属性来找找属性语法的感觉。添加下面的代码到属性代码块中: _MySliderValue ("This is a Slider", Range(0,10)) = 2.5 我们创建了其他两种不同类型的GUI元素,它们可以让我们与着色器进行可视化的交互。我们这次创建了一个叫做This is a Slider的滑动条,就如下图所示: 着色器的属性让你可以通过可视化的方式调整着色器,而不用在着色器自己的代码中调整。 下一个知识点将会为你介绍如何利用这些属性创建一些更有趣的着色器。 注意 尽管属性属于着色器,但是着色器上属性的值却是保存在材质上的。不同的材质可以很安全的共用相同的着色器。从另一方面说,修改材质上的属性的值,将会影响到所有使用了该材质的游戏对象的外观。 原理介绍 每一个Unity的着色器都有它想要的内建的代码结构。属性代码块就是Unity所期望的功能之一。属性代码块的目的是让着色器编程人员能快速的创建GUI交互元素,并且将GUI元素与着色器代码相关联起来。那些你在着色器属性面板中申明的属性,能让你在着色器代码中使用,从而修改着色器中的一些值,颜色和纹理。 定义一个属性的语法[也可以叫语义,也可以叫语法糖]如下: 让我们来解释一下这个示意图。 当你第一次开始写一个新的属性时,你需要给这个书信一个变量名(Variable Name)。这个变量名能让着色器使用并且能让着色器代码获得来自该变量名绑定的GUI元素的值。这给我们节约了大量的时间因为我们不用自己来创建这么一个系统。属性的下一个元素时检查器面板GUI名称( Inspector GUI Name )和属性的类型(Type),这两个元素放在一对括号中。当玩家想要交互和调整着色器时,**检查器面板GUI名称( Inspector GUI Name )将会在材质的检查器面板(Inspector tab)**中展示。**类型(Type)**就是这个属性想要控制的数据类型。在Unity着色器中,有很多属性可以使用的类型。下面这个表展示了我们在着色器中可以使用的变量类型: 类型 说明 Range (min, max) 创建一个浮点类型的滑动条属性,值从最小值到最大值[min最小值,max最大值] Color 在 检查器面板(Inspector tab) 中创建一个颜色选取框,当你打开的时候会弹出一个调色板,颜色值R,G,B,A 2D 创建了纹理选取框的GUI元素,可以让玩家通过拖拽的方式给着色器一张纹理 Rect 创建一个非2次幂纹理[NPOT]选取框,功能更 2D 属性类似 Cube 在 检查器面板(Inspector tab) 创建一个立方体纹理[大家想想天空盒],可以让玩家拖拽立方体纹理到着色器中 Float 在 检查器面板(Inspector tab) 中创建一个浮点型的值,但是没有滑动条– Vector 创建一个有四个值的属性,能让你表示方向或者颜色 最后就是这些属性的**默认值(Default Value)**了。可以在着色器代码中简单的给着色器的属性设置特定的值。在上一个图片属性改成颜色属性的列子中,属性 ...

August 19, 2020 · 1 min · 112 words · Link

如何把Unity 4的旧着色器迁移至Unity 5

如何把Unity 4的旧着色器迁移至Unity 5 不可否认,在过去10年中图形学在电子游戏中获得了惊人的发展。每一个新游戏带来的尖端技术让我们的游戏画面更加接近现实。随着Unity引擎版本的不断迭代,它的着色器技术也自然而然的经历了相当大的变化。这也是为什第一次接触着色器的时候感到困惑的原因。在Unity5还没有推出之前,Unity自带了两种不同的着色器,分别是:漫反射(Diffuse)和高光反射(Specular)。正如其名字所描述,它们分别用来模拟表面粗糙和表面光滑的材料。如果你现在使用的Unity5,那么你其实可以跳过这个知识点。该知识点会讲解如何在Unity5中重现这些效果。 始前准备 要开始这个知识点,前提时你有个用Unity4版本作为开发引擎工作空间,并且你使用了这个版本内建的一些着色器。当你开发新游戏的时候,毫无疑问你应该改选择最新版本的Unity引擎。然而如果你的项目已经使用了旧版的Unity引擎开发,那么你在迁移着色器前应该三思。引擎背后可能又很多东西都不一样了,即使有时候内建的着色器表面看起来可以正常工作,但是你写的脚本可未必能。所以如果你要迁移整个项目空间,这个时候首先要做的事情就是备份。但是要注意噢,仅仅只是保存Assets资源和场景可不够,同时所有的.meta文件也要一并保存,因为大多数Unity的配置信息保存在元数据中。在迁移项目的过程中最稳妥的办法还是要把整个项目空间所在文件夹都复制一份。最好的是物理拷贝一份,如果是windows就在资源管理器物理复制,如果是Mac就在Finder中物理复制。【建议大家将这个项目目录用压缩工具【如winrar】打包一份】。 操作步骤 如果你想要迁移你的内建着色器,有两个主要选择:采用自动升级的方式或者切换至标准着色器 着色器版本的自动升级 这种选择是最操作起来最简单的。Unity5可以导入使用旧版内建着色器的项目并且自动升级。你需要主义的是一旦升级完成后,那么你在Unity4中就不能再使用它们了。尽管这个过程并没有直接改变你的Assets资源,但是Unity的元数据已经被转换过了。要进行这个过程,你需要打开Unity5引擎,然后点击文件(File)|打开项目(Open Project)来打开你就项目所在的文件夹。然后回有提示问你是否愿意转换;然后点击升级(Upgrade)执行改过程。Unity就会重新导入所有的Assets资源并且重新编译所有的游戏脚本。如果你的项目非常巨大,这个过程可能回持续几个小时。一旦转换完成,来自Unity4的内建的旧着色器会被相应的替换掉。 你可以通过检查器面板验证这个转换,材质实例中从原来的Bumped Diffuse变为了Legacy Shader/Bumped Diffuse。 注意 尽管Unity4版本的漫反射,高光反射和其他内建的着色器现在已经已弃用了,但是Unity5依然向后对它们保持兼容。它们在材质的Legacy Shaders路径下的下拉列表中依然可以看到。 使用标准着色器 相比于使用旧版本的着色器,你可能想使用Unity5新的内建标准着色器替代它们。但是这么做之前,请留意新旧两个版本的着色器是基于不同的光照模型的,你的材质很可能看起来不一样。Unity4总共有8个不同的内建着色器,它被划分进了6个大类(法线(Normal),透明(Transparent),透明剪切(Transparent Cutout),自发光(Self-Illuminated)和反射(Reflective))。但在Unity5中,它们都被上一个知识点所讲的那些标准着色器所替代了。不幸的是,没有什么很好的办法能够将旧着色器完美的迁移只新版本的着色器。但是你可以通过下面这个表格着重理解如何通过配置标准着色器去模拟unity4的旧着色器的效果: 你可以在旧材质的**检查器面板(Inspector)上通过着色器(Shader)下拉菜单改变它所使用的着色器。所有你需要做的就是简单的选择适当的标准材质。如果你的旧着色器使用了纹理,颜色和发现题图,那么在新版本的标准着色器上也会自动使用。当然为了更好的接近之前旧版本着色器的光照模型,你可能需要配置标准着色器的相关参数。 下图展示的是常见的斯坦福兔(Stanford bunny ),它们分别使用旧版本的漫反射着色器(右),被转换的标准着色器(左),和把平滑度(Smoothness)**设置成0的标准着色器(中): 迁移用户自定义的着色器 如果你以前在Unity4上有写自定义的着色器,很有可能在Unity5中能直接正常使用。即使如此,Unity也有可能在着色器的工作原理上做了细小的改动,这些改动是可能引发一些错误和不一致性。有个变化最明显的重要参数就是光的强度。 光在Unity5中是原来亮度的两倍。所有的旧版本着色器在重写的的时候都应该考虑到这一点;如果你升级了你的着色器或者切换到标准着色器,你不会发现有任何的不同。但是如果你是自己写的光照模型,那么你就要注意确认光的强度不能再乘以二了。我们就用下面的代码举例来确认这种变化: // Unity 4 c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten * 2); // Unity 5 c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten); 如果你还没有写过着色器,大可不必惊慌:光照模型会在第三章,理解光照模型 中全面详细的讲解。 注意 Unity5对着色器的处理相比于Unity4来说还有一些其他的变化,你可以下面这个网址中查看所有着色器在Unity5中的处理方式的变化 http://docs.unity3d.com/Manual/UpgradeGuide5-Shaders.html。 原理介绍 着色器的编写需要权衡画面表现和效率;效果逼真的着色器需要极大的计算量,可能导致严重的延迟。所以,有一点很重要,就是只使用我们确切需要的效果:如果一个材质不需要高光反射,那么就不要在着色器中去计算它们。这也是在Unity4中把这些效果拆分成了很多不同着色器的主要原因。 新版本的标准着色器有潜力替换掉先前旧版本的着色器,因为它把法线贴图,透明度和反射都包括在内了。然而,这个标准着色器经过巧妙的优化,使它能够只去计算用到的效果,没用到的效果就不计算。尽管这样,标准着色器主要还是设计用于模拟现实的材质。相比较而言,漫反射和高光反射着色器并不是为模拟现实的材质设计的。 这就是为什么从旧版本的着色器切换到标准着色器时,游戏对象在渲染的时候通常回发生一些细小的变化的原因。 相关补充 第三章, 理解光照模型, 将会深入探索漫反射和高光反射着色器的作用原理。尽管在Unity5中,它们已经被弃用了,但是如果你想要设计新的光照那么理解它们还是有必要的。 第四章,Unity 5中基于物理原理的渲染 ,将会介绍如何在Unity5中展现标准着色器的潜力。

August 15, 2020 · 1 min · 70 words · Link

内容结构

内容结构 在本书中, 会经常出现一系列的小标题 (始前准备,操作步骤,原理介绍,额外内容 ,相关补充)。 主要功能是对每一个知识点进行说明,如何完成该知识点的掌握。下面说明具体的用法: 始前准备 这个部分会告诉你这个知识点会学习什么,怎么安装和设置对应的软件。 操作步骤 这个部分包含了学习该知识点包含那些步骤。 原理介绍 该部分通常是为了详细解释“操作步骤”这个部分的知识原理,上面的每一步到底做了什么。 额外内容 为了让读者了解更多与该知识点相关的额外知识,我们才准备了这个额外信息让读者阅读。 相关补充 如果想了解更多与该知识点相关的信息,这里还额外提供了一些相关链接。

August 13, 2020 · 1 min · 16 words · Link

勘误表

勘误表 尽管我们非常注意本书内容的准确性,但还是会有不小心出错的地方。如果您在我们出版的书中(不限本书)找到了错误,有可能是文字错误或者代码错误,我们非常欢迎您将这些错误报告给我们。如此善举,既解他人之惑,亦可助改善此书。如果您发现任何勘误,请通过链接https://www.packtpub.com/support/errata (原书写的链接失效了)向我们报告。当您的勘误确认后,您提交的勘误将会被接受并且勘误会上传至我们的网站和任何已存在的勘误名单中。 如果您想看看之前的勘误提交,可以访问https://www.packtpub.com/support/code-downloads(原书的网址失效了,现在是这个),然后输入书名搜索,你想要的信息会出现在下面的勘误部分。

August 13, 2020 · 1 min · 4 words · Link

客户支持

客户支持 很高心您能拥有此书,为了让您物有所值,我们还为你准备了很多东西(很搞不懂这也要搞一个章节出来,就一句话)。

August 13, 2020 · 1 min · 2 words · Link

本书一些彩图的下载

本书一些彩图的下载 这本书中的彩图,比如说屏幕截图/示意图我们都把他放在了一个PDF文件中。希望这些图片可以让你更好的理解屏幕输出图像的变化。 你可以通过下面的链接下载这个PDF文件https://www.packtpub.com/sites/default/files/downloads/Unity5xShadersAndEffectsCookboo

August 13, 2020 · 1 min · 3 words · Link

本书有问题请联系

本书有问题请联系 如果您对本书有任何层面的问题,您可以通过邮箱questions@packtpub.com联系我们,我们会尽己所能改善这些问题。

August 13, 2020 · 1 min · 2 words · Link

本书的一些文体要求

本书的一些文体说明 在书中你可以发现很多种不同的文本样式用来表示不同的信息内容。这里列举几个来解释一下。(需要说明一下的是,我在翻译的过程中,代码的字体样式可能会跟书本上不一样,我主要是用markdown的代码块来表示。然后它的粗体,比如强调,那我就用markdown中的强调标签来表示,说声抱歉了,希望大家能看的懂) 代码块,数据库表名,文件夹名字 ,文件名字,文件扩展名,路径名称,虚拟URL(觉得这个翻译不准确),用户输入,推特账号等会按照如下表示:“请输入下面的代码到你的着色器属性块( Properties )中” void surf (Input IN, inout SurfaceOutput o) { float4 c; c = pow((_EmissiveColor + _AmbientColor), _MySliderValue); o.Albedo = c.rgb; o.Alpha = c.a; } 当我们想提醒你代码块中的特别部分,那么对应的代码行或者语句会用粗体标记,比如那个void:(代码块中我不知道怎么加粗,下面这个就不用代码块了) void surf (Input IN, inout SurfaceOutputStandard o) { ​ fixed4 c = pow((_Color + _AmbientColor), _MySliderValue); ​ o.Albedo = c.rgb; ​ o.Metallic = _Metallic; ​ o.Smoothness = _Glossiness; ​ o.Alpha = c.a; } 新的术语 和 非常重要的词语 都应该用粗体表示.像出现再电脑屏幕中的菜单和弹窗中的文本,也会用粗体加以强调。比如:“在Unity编辑器的菜单栏中的“ 项目(Project) ,在 资产(Assets) 文件夹上右键单击和在菜单中选择 创建(Create)|文件夹(Folder) 。” (中文后面括号里的是英文版的编辑器中菜单项的名字) 注意(Note) 警告或者很重要的注意会像这样,有个 注意(Note) 提醒你。 提示(Tip) 提示和小技巧会像这样,有个 提示(Tip) 提示你。

August 13, 2020 · 1 min · 82 words · Link