法线贴图

法线贴图 3D模型的每一个三角面都有一个 朝向facing direction ,这个朝向就是它向前的指向。它通常用一个垂直并且放置在三角面正中心的一个箭头来表示。这个朝向对于光在表面反射中来说非常的重要。如果相邻的两个三角面朝向不同的方向,那么它们对光的反射也会朝向不同的角度,也就是在着色器中它们的处理方式会不一样。对于曲面物体来说,这里有个疑问:很显然这些拥有曲面的几何体仍然是由平面三角形构成的,那光线改如何处理? 为了避免这个问题,对应三角面的光的反射计算方式此时不根据它的朝向计算,而是根据它的 法线方向normal direction 方向计算。前面 向着色器添加纹理 那个知识点讲到,顶点是保存有数据的。法线方向信息也是继UV信息之后,保存在顶点中最有用的信息。这是一个单位长度的向量,并且它表示了顶点的朝向。不考虑朝向的话,那么三角面内的每一个顶点都有它自己的法线方向,只不过这个法线方向是一个存储在顶点中的线性插值。这给了我们用低模模拟高模的能力。下面示例图展示了同一个几何形状在不同的顶点插值密度下的表现。在左边,法线垂直于由顶点表示的面;很明显每个面之间有明显的的割裂感。再看看最右边的几何体,它的法线是通过他的面线性插值得到的,可以看出来的是,尽管它的表面看起来还是很粗糙,但是光线的反射看起来却似乎很光滑。很容易看出来尽管这三个物体的几何体都相同,但是它们的光线反射却不一样。尽管都是由平面三角形构成,但是右边物体的光线反射似乎看起来像曲面反射。 一个有着粗糙的边的光滑物体很明显的表示单位顶点的法线肯定进行了线性插值。如果我们对保存在每个顶点的法线按其方向进行绘制,我们就能够看到它们,正如下图所展示的那样。你应该注意的是每个三角形仅有三条法线,但是相连的三角形有相同的顶点,会看到不止有一条法线从中绘制出来。 法线贴图在计算3D模型的法线技术中脱颖而出。跟纹理贴图类似,法线方向也可以用一张额外的纹理表示,我们把它们叫做 法线贴图normal map 或者 凹凸贴图bump map 。 法线贴图通常是一张RGB图片,里面的RGB通常分别用来表示法线方向中的X,Y,Z方向。现在有很多种技术方法来创建一张法线贴图。比如这些应用程序,CrazyBump (http://www.crazybump.com/)跟 NDO Painter (http://www.crazybump.com/)可以把2D数据转换成法线数据。其他的应用程序比如 Zbrush 4R7 (http://www.pixologic.com/)和 AUTODESK (http://usa.autodesk.com)可以把雕刻数据转换成法线贴图。如何创建法线贴图完全超出了本书的范畴,但上面的内容对你了解相关相应的知识还是有好处的。 在Unity中向着色器添加法线的过程很简单,因为在表面着色器中有着 UnpackNormals() 这样的方法给你调用。就让我们看看这是怎样的一个过程。 始前准备 分别创建一个新的材质和着色器,并且把它设置到 场景视图Scene view 中的游戏对象中去。这样的话,我们的项目非常简单,好让我们仅仅是观察法线贴图这项技术。 这个知识点中你需要一张法线贴图,但是我们这本书附带的Unity工程中包含了一张。[当然,你也可以从我这里把这张图片下载下来,如下图] 操作步骤 下面就是创建法线贴图着色器的步骤了: 让我们设置好我们的属性块,从而可以获得颜色和贴图: Properties { _MainTint ("Diffuse Tint", Color) = (1,1,1,1) _NormalTex ("Normal Map", 2D) = "bump" {} } 注意 因为用的是 bump 来初始化了属性的贴图类型,这等于是告诉了Unity _NormalTex 包含了法线贴图。如果这个贴图没有被设置, 那么会默认给它设置一张灰色的贴图。颜色值会用 (0.5,0.5,0.5,1) ,然后看不出一点凹凸感。 在 CGPROGRAM 下面的 SubShader{} 块中声明下面两个变量,让这两个变量跟属性块中的两个属性关联起来: CPROGRAM #pragma surface surf Lambert // Link the property to the CG program sampler2D _NormalTex; float4 _MainTint; 我们需要修改 输入结构体Input struct 的名字,从而让我们可以让我们通过模型的UV来访问法线贴图: ...

January 9, 2021 · 1 min · 210 words · Link

通过改变UV值来移动纹理

通过改变UV值来移动纹理 在当惊的游戏产业中,一个很常见的游戏纹理技术就是允许你对游戏物体表面的纹理进行滚动。这种技术可以让你创建很多效果,比如瀑布,河流,流动的沿江等等。同时这些技术也是制作动画精灵特效的基础,我们会在这一章节的一系列知识点中来讲解这些内容。 首先,让我们来看看在**表面着色器(Surface Shader)**如何创建一个简单的纹理滚动效果。 始前准备 在这个知识点开始之前,需要你创建一个新的着色器文件和材质。这么做的目的是为了有个干净的着色器,然后我们可以更加方便的学习和观看滚动效果。 操作步骤 闲话少说,我们打开刚才创建的的着色器[着色器的名字文章中没有说,就自己取一个启动的名字吧],然后输入下面每个步骤所展示的代码: 这个着色器需要两个控制纹理滚动的新属性。所以我们添加一个速度属性控制 X 方向的滚动,添加另一个速度属性控制 Y 方向的滚动,如下面的代码所示: Properties { _MainTint("Diffuse Tint",Color) = (1,1,1,1) _MainTex ("Base (RGB)", 2D) = "white" {} _ScrollXSpeed("X Scroll Speed",Range(0,10)) = 2; _ScrollYSpeed("Y Scroll Speed",Range(0,10)) = 2; } 修改 CGPROGRAM 代码块中的Cg属性中的变量,创建新的变量[把原来的都删掉,用下面展示的代替],这样我们就能访问来自着色器属性的值了: fixed4 _MainTint; fixed _ScrollXSpeed; fixed _ScrollYSpeed; sampler2D _MainTex; 修改 表面函数surface function 从而修改传递给 tex2D() 函数的UV值。然后,使用内建的 _Time 变量来对UV进行循环播放的动画,这样的话当我们点击Unity中的运行按钮的时候,我们就能看到动画效果了: void surf (Input IN, inout SurfaceOutputStandard o) { // Create a separate variable to store our UVs // before we pass them to the tex2D() function fixed2 scrollUV = IN.uv_MainTex; // Create variables that store the individual x and y // components for the UV's scaled by time fixed xScrollValue = _ScrollXSpeed * _Time; fixed yScrollValue = _ScrollYSpeed * _Time; // Apply the final UV offset scrollUV += fixed2(xScrollValue,yScrollValue); // Apply textures and tint half4 c = tex2D(_MainTex,scrollUV); o.Albedo = c.rgb * _MainTint; o.Alpha = c.a; } 下面的图片中的示例就是利用滚动UV的系统来创建的一个自然环境中河流的动画,你可以注意到场景中叫 ScrollingUVs 的特效就是来自于本书提供的代码: ...

January 9, 2021 · 2 min · 228 words · Link

在LayaBox中使用Unity中的导航网格,实现AI自动寻路

在LayaBox中使用Unity的导航网格,实现AI自动寻路 使用这个这个库的好处在于,你不必了解AStar算法,一样可以使用AStar算法来进行AI导航。只需要调用接口即可。 下面我给出LayaBox的示例项目地址和Unity导出网格示例项目地址,各位按需克隆下来即可 Unity示例项目:https://github.com/linkliu/ExportNavMesh LayaBox示例项目:https://github.com/linkliu/LayaNavMesh 原始的教程在http://ask.layabox.com/question/47899这里,大家可以去看看这里也行 这次的实例会从下面三个方面来讲解: Laya要用到的导航组件库NavMesh.js Unity如何将Navmesh数据导出成json文件【Laya中用到】 Unity中用到的NavMeshComponents 开始之前,说一下相关软件的版本 LayaAir 2.9 ,Laya引擎库2.7.1,Unity 2018.4.11f1 1.Laya中用到的导航组件库NavMesh.js 可以直接在Unity中对导航网格进行编辑,非常的方便。 NavMesh.js可以直接从这里去拿https://github.com/lear315/NevMesh.Js/tree/main/build 名字可能跟我的不一样,但是里面内容完全一样,我这里是强迫症发作,把Nev改成了Nav。然后只要拿NavMesh.js和NavMesh.d.ts这两文件就行了。NavMesh.js请放在Laya项目的bin/libs目录下面。NavMesh.d.ts放在项目的libs文件夹中。并且在bin/index.js中增加loadLib(“libs/NevMesh.js”),注意需在loadLib(“js/bundle.js”);前面。完成上面这些步骤,就把导航组件库NavMesh.js放到我们的项目中了 2.Unity如何将Navmesh数据导出成json文件 将Unity的导航网格数据导出成LayaBox需要的json数据,需要用到两个关键文件,一个是把导航网格转换成.obj文件的NavMeshExport.cs。另一个是Python自动转换脚本convert_obj_three.py,这两个文件的获取方式,我贴在下面: NavMeshExport.cs:https://github.com/lear315/NevMesh.Js/tree/main/unity convert_obj_three.py: https://github.com/lear315/NevMesh.Js/tree/main/python NavMeshExport.cs是一个Unity中的一个C#脚本,只要放到Unity中即可,便会在Unity中生成一个导出菜单,合并在LayaBox的导出菜单中。如下图 点击Export按钮,就会把当前的导航网格导出到ExportNavMesh文件中,里面就是需要下一步需要的.obj文件。 convert_obj_three.py是一个python脚本,所以各位需要安装python,并且配置配置好python环境,并且把python添加到系统的环境变量中去。 这个脚本的使用方法是 python convert_obj_three.py -i xx.obj -o xx.json,这个命令是把上一步生成的.obj文件转换成.json文件,这样我们就能在LayaBox中使用这个.json文件来进行AI导航了。 我的示例项目中已经做好了一键obj转json的功能,具体的用法是:选中你要转换的obj文件,然后右键,菜单选择Convert Navmesh to Json,就回自动在当前目录下生成一个同名的.json文件。这个就是LayaBox需要的文件,把这个文件放在LayaBox中的一个目录中。 3.Unity中用到的NavMeshComponents Unity中的导航网格的生成需要用到NavMeshComponents组件,目前这个组件Unity没有集成到Unity编辑器中,至少Unity2018以及之前的版本没有。但是Unity官方把它们放在Github上,地址在这里:https://github.com/Unity-Technologies/NavMeshComponents 克隆下来后,你只需要把Assets/NavMeshComponents这个文件复制到自己的项目中就行了,其他的东西可以不用。 NavMeshComponents的用法我就不细讲了,各位可以到https://docs.unity3d.com/Manual/NavMesh-BuildingComponents.html查看,也可以看这个中文的的博客https://blog.csdn.net/wangjiangrong/article/details/88823523各位按需观看吧。 总结 完成上面的三个步骤后,准备工作都OK了,具体的使用,各位可以去看我的LayaBox示例项目吧,哪里有完整的代码。 感谢各位耐心看完。

January 7, 2021 · 1 min · 45 words · Link

向着色器添加纹理

向着色器添加纹理 通过纹理,可以很容易让着色器变得生动起来,获得非常真实的效果。为了更有效的使用纹理,我们需要了解一张2D图片是如何映射到3D模型中去的。 这个映射的过程称之为 纹理贴图texture mapping ,为了完成映射,我们在使用的模型和着色器上还有额外的工作。模型实际上是由很多的三角形拼接而成的;而三角形的每个顶点都保存有着色器可以访问的各种数据。 其中很重要的一个信息就是 UV信息 (UV data) 。 它包含两个坐标,U 和 V ,其取值范围是0到1。这两者表示2D图片的像素点坐标的 XY 位置信息,而这些信息将会映射到顶点中去。 UV数据只为顶点表示[意思可能也等价于:UV数据只存在顶点中]; 当三角内的点需要被纹理贴图时,GPU会插值最接近的UV值,从而从相应的纹理中找到正确的像素点。下面的图片展示了一张2D纹理贴图到3D模型中的三角形中的情况: UV数据保存在3D模型中并且需要3D模型工具去编辑它们。有些模型缺少UV组件,因而它们不支持纹理贴图。比如3D模型软件中的默认的那个兔子模型,就没有提供这么一个组件。 始前准备 学习这个知识点的时候,你需要一个有UV数据和纹理的3D模型。然后把它们都导入到Unity中。也可以直接拖拽到Unity编辑器中,会自动导入。因为标准着色器支持默认的纹理贴图。我们会用到这一点,而后会详细的介绍它是如何工作的。 操作步骤 用标准着色器给你的模型添加一张纹理异常的简单,按照下面步骤: 创建一个叫 TexturedShader 标准着色器。 创建一个名为 TexturedMaterial 的材质球。 通过拖拽的方式,把着色器赋值给材质,把着色器拖到材质上即可。 选择刚才的材质,然后拖拽模型对应的纹理到一个叫 Albedo(RGB) 的矩形区域中的空白部分。如果你正确的执行了上述步骤,你的材质 检查器面板(Inspector) 会如下图所示: 标准着色器知道如何通过UV信息把2D图像映射到3D模型中 原理介绍 当通过材质的检查器面板使用标准材质的时候,纹理贴图背后的处理过程对于开发者来说是透明的。如果我们想了解它是如何工作的,那我们需要更加详细的了解我们刚才创建的 TexturedShader 着色器。在着色器的 属性Properties 部分,我们可以看到 Albedo (RGB) 的纹理跟代码的关联如下代码所示: MainTex: _MainTex ("Albedo (RGB)", 2D) = "white" {} 在我们着色器代码中的 CGPROGRAM 代码块部分,纹理被定义为 sampler2D 类型,这是一种标准的2D纹理类型: ...

December 11, 2020 · 1 min · 132 words · Link

使用包组数组

使用包组[包装组织] 笼统的讲,显示器上每一个像素点都至少会执行一次。这也是为什么GPU要设计高度优化的并行架构的原因。同样的在Cg语言的标准变量类型和操作符中,这种设计哲学也很明显。理解它们,不仅仅是为了正确的使用着色器,同时也是为了能够写出更高效的着色器。 操作步骤 在Cg语言中有两种类型的变量: 单精度值single 和 包组packed arrays 。后者很容易辨别因为这种类型通常会以数字结尾,比如 float4 , int4 等等。正如它们的名字所表示的一样,这些类型的变量跟我们编程语言中的 结构体structs 类似,这也意味着每一个这样的变量包含了多个单精度值。在Cg语言中我们称之为 包组packed arrays ,尽管它们并非真的是传统意义上的数组。 在包组中的元素能像常见的结构体那样访问。通常它们表示成 x ,y ,z 和 w 。然而Cg语言还有另一种表示,就是 r ,g ,b ,a 。尽管你使用 x 或者 r 去表示都是可以的,但是对于代码阅读者来说它们之间的区别就非常的大了。事实上,在着色器编程中,经常涉及到的就是位置和颜色的计算。你可能对下面的标准着色器代码中的代码片段还有印象吧: o.Alpha = _Color.a; 在这里, o 是一个结构体而 _Color 就是一个包组。这也是为什么Cg要禁止上面提到的两种表示进行混用的原因:你不能使用 _Color.xgz 。 这里还有一个很重要的包组的特性,这种特性在C#中没有: swizzling [这个不知道怎么翻译]。Cg允许仅通过简单的一行代码就对包组内的元素进行寻址和重新排序。又是下面在标准着色器中熟悉的代码片段: o.Albedo = _Color.rgb; Albedo 是一个 fixed3 类型,也就是说它里面包含了三个 fixed 类型的值。 然而 _Color 是一个 fixed4 类型的定义。由于 _Color 定义包含的元素比 Albedo 定义包含的元素要多,直接赋值的话,由于不匹配,肯定会产生一个编译错误。如果用C#代码来进行同样的操作,代码如下所示: o.Albedo.r = _Color.r; o.Albedo.g = _Color.g; o.Albedo.b = _Color.b; 相比于C#代码,在Cg语言中,我们可以用如下代码简写: o.Albedo = _Color.rgb; Cg语言也允许对元素进行重新排序。比如,通过 _Color.bgr 这个代码去交换红色和蓝色通道的颜色。 最后要讲一点,当一个单精度值赋值给包组时,这个值会被复制到包组的所有元素中去: o.Albedo = 0; // Black =(0,0,0) o.Albedo = 1; // White =(1,1,1) 这个就是Cg语言中的 smearing 特性。 ...

December 9, 2020 · 1 min · 149 words · Link

表面着色器和纹理贴图

第二章 表面着色器和纹理贴图 在这一章节,我们将会探索表面着色器的使用。我们会用一个非常简单的磨砂材质开始讲起,然后会在后面讲解全息投影和高级的地形混合。 我们将能够使用纹理制作动画效果,混合等,或者用着色器去驱动我们想要的属性。在这一章你将会学习下面一些表面着色器的使用方法: 漫反射的着色处理 使用包组 向着色器添加纹理 通过改变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 · 2 min · 269 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 · 320 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 的滑动条,就如下图所示: 着色器的属性让你可以通过可视化的方式调整着色器,而不用在着色器自己的代码中调整。 下一个知识点将会为你介绍如何利用这些属性创建一些更有趣的着色器。 ...

August 19, 2020 · 1 min · 181 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 · 23 words · Link