Unity Shader入门系列(五):法线贴图

Number of views 13

上次我们学习了如何进行颜色混合!在该教程中,你需要知道如何混合颜色,所以如果你还没学过,请仔细阅读。

还记得我们在系列第一节材质中玩球体和胶囊体的时候,材质呈现出一种亮蓝色/紫色的纹理,让瓷砖看起来就像真的从物体里冒出来一样吗?太酷了,让我们用着色器来实现这个效果吧!

那个蓝紫色的纹理叫做法线贴图。它包含关于 3D 物体应该呈现出怎样的凹凸效果的信息。法线贴图很有用,因为它们可以让细节较少的 3D 物体看起来比实际更细致。(我们很难为了模型凹凸感去修改顶点信息,这很难)不过,我们稍后会详细讨论这一切的工作原理。 

在 Unity 中,点击 Lerp 着色器,然后按 Ctrl + D 复制它,并将其命名为 XibStandard。双击以在 Visual Studio 中打开它。首先,让我们将顶部的路径更新为“Xibanya/XibStandard”。

image1753859727049.png

在属性部分,添加以下行: 

_BumpMap("Normal", 2D) = "bump" {}

在 SubShader 部分中,在其他 sampler2D 行下添加此行:

sampler2D _BumpMap;

完成后,您的代码应如下所示:

image1753859793725.png

顺便说一下,在属性的顶部,你会看到 2D 类型的属性有些显示“white”,而我们刚刚添加的属性显示“bump”

image1753859830445.png

我们在这里输入“white”,指的是如果插槽中没有任何纹理,默认的颜色应该是什么。我们在这里输入“bump”,指的是放置法线贴图的插槽,因为如果插槽中没有任何纹理可放,在这里输入“bump”将使用默认的法线贴图信息,这意味着 3D 对象看起来还是正常的。

在此表面函数中,添加此行

o.Normal = UnpackNormal(tex2D(_BumpMap,IN.uv_MainTex));

首先,我们通过告诉着色器查看插槽中的纹理,然后应用主纹理的UV坐标,并通过该坐标信息拾取颜色来获取法线贴图纹理的颜色。然后,UnpackNormal 函数将颜色信息转换为法线信息(关于物体应该有多么凹凸不平的信息)。你应该记得,这里的o存储物体应该会有什么样子的输出,而o.Normal就是我们保存物体应该有多么凹凸不平信息的地方。

image1753859861827.png

当你完成上述代码时,保存,然后单击返回 Unity。

前往“Claire”>“Materials”文件夹,复制“ClaireBody2”。点击“ClaireBody3”,其信息就会显示在检查器中。 

image1753859889505.png

在下拉菜单中,选择着色器 Xibanya > XibStandard。现在将 ClaireBody3 拖到 Girl_Body_Geo 的材质槽中。

image1753859918572.png

法线贴图插槽自动填充了克莱尔的法线贴图。这是为什么呢?因为 Unity 中的材质会保存其所有属性,而我们一直在不断复制。所以,材质保存了法线贴图纹理和名为“_BumpMap”的属性之间的链接。我们稍后会讨论这个问题。如果你的材质没有自动填充,请将克莱尔的法线贴图拖到插槽中。

现在克莱尔有了法线贴图,混合两种纹理会更有趣,因为即使不再使用她的主纹理,你也可以看到她的细节。

image1753859948973.png

好了,既然我们前面已经混合了颜色,为什么不也混合一下凹凸效果呢?回到代码,并将其更新为如下所示:

image1753859992749.png

保存并返回 Unity。将图块状的法线贴图拖到新插槽中。现在你应该能看到如下内容:

image1753860022638.png

注意,第二张法线贴图"Normal2"完全没有设置不等于1的Tiling值,即它没有缩放,但它仍然与平铺纹理(OtherTex)匹配,即使平铺纹理(OtherTex)比默认纹理小了 5 倍。这是因为我们告诉着色器在解析第二张法线贴图时使用第二张纹理(即 IN.uv_OtherTex )的坐标。这使它们保持同步。我们对第一张法线贴图也做了同样的操作。

让我们来看看这张法线贴图的完整效果。点击层级视图(左上角窗格中场景中的节点列表)中的定向光源,取消勾选光源组件旁边的复选框以将其关闭。

image1753860051854.png

接下来,右键单击 claire@Female Standing Pose 并添加一个新的点光源。 

image1753860088188.png

通过右键单击克莱尔来添加它,这会使新的灯光嵌套在克莱尔下方,并且与她所在的位置完全重叠。会产生如下戏剧化的效果!

image1753860126157.png

让我们拖动箭头手柄,让光线照射在她的脸上。

image1753860156103.png

拖动灯光时,你可以看到克莱尔实际上是由瓷砖图块拼成的。为了获得完整的效果,你可以点击“场景”选项卡顶部附近的图标来关闭天空盒,这个图标看起来像一叠闪闪发光的纸(或者两颗短而宽的钻石和一颗星光?)。 

image1753860180962.png

但这里有个挺有意思的地方!看起来好像有一排排凸起的瓷砖,瓷砖之间还有凹槽,但放大她的脸,看看网格的边缘。 

image1753860203016.png

它们非常光滑!3D网格中实际上没有任何凹槽,只是因为光照效果的原因,使得表面看起来凹凸不平。所以,无论我们在表面函数的 o.Normal 中输入什么信息,3D物体的实际形状都不会改变。尽管如此,仅仅改变光照效果就相当逼真,尤其是在远处的角度观看时! 

(顺便说一句,我们办法用着色器改变 3D 对象的形状,但我们改天再讨论这个想法。)

那么,如果我们想要法线贴图更强大呢?通常,当我们谈论着色器时,法线由 3 个数字组成,但这些数字并非代表红、绿、蓝。而是代表 x、y 和 z 轴的数字,它们用于指示方向。如果我们在桌子上放一张纸,我们可以使用 x 和 y 来表示基于宽度和高度的坐标。纸的中心是 0,0,所以如果我们有其他坐标,那么从中心到该坐标绘制的线就是方向。z 轴增加了深度(即上下),但在 3D 中寻找方向仍然需要从 0,0,0 绘制一条到另一点的假想线作为方向指向。 

所以实际上,我们所说的法线并非“凹凸程度”,而是指3D网格各部分朝向的方向。不过现在你不需要太担心这个。 

Z 是沿着上下方向的,因此如果我们弄乱了法线的 Z,那么我们就会弄乱 3d 网格表面突出的程度

更新属性以包含此新行

image1753860238793.png

并在 _Mix 下声明新的 Float类型的 Uniform变量,如下所示:

image1753860258752.png

然后在surf表面函数中我们再添加一行:

image1753860281334.png

保存并返回 Unity。点击“Normal Strength”框旁边,然后向左拖动。哇哦。

image1753860307019.png

尝试向下拖动“Mix”混合滑块来查看其与克莱尔的法线贴图的搭配效果。

image1753860342420.png

咦!看看当我们接近零时,光亮部分和阴影部分之间的对比度变得越来越鲜明。

image1753860366456.png

如果我们朝相反的方向走,光的颜色和阴影的颜色之间的差异就会变得更加平滑。

image1753860401233.png

挺有意思的,你不觉得吗?我猜我们肯定能用上它。

好了,目前为止我只能做到这些了。如果你想挑战一下,可以试试添加一个属性,这样就能分别控制两个法线贴图的强度了。如果你需要任何帮助,评论区中尽管告诉我!

进入第 6 部分:让物体发光

0 Answers