法线贴图是一种凹凸贴图 (Bump Map)。它们是一种特殊的纹理,可让您将表面细节(如凹凸、凹槽和划痕)添加到模型,从而捕捉光线,就像由真实几何体表示一样。
Unity 使用 Y+ 法线贴图,有时也称为 OpenGL 格式。
例如,您可能希望显示一个表面,在表面上有凹槽和螺钉或铆钉,比如飞机机身。为实现此目的,一种方法是将这些细节建模为几何体,如下所示。
根据具体情况,将这些微小的细节建模为“真实”几何体通常并非一种好的思路。在右侧,您可以看到构成单个螺丝头的细节所需的多边形。在具有大量精细表面细节的大型模型上,这种方案需要绘制极大数量的多边形。为了避免这种情况,我们应使用法线贴图来表示精细的表面细节,而使用分辨率较低的多边形表面来表示模型的较大形状。
如果我们改用凹凸贴图来表示此细节,则表面几何体可以变得简单得多,并且细节将通过纹理呈现,用纹理来调节表面如何反射光。现代图形硬件可以非常快速地完成此过程。现在,金属表面可变为一个简单多边形平面,而螺钉、铆钉、凹槽和划痕将捕捉光线,并会因为纹理而显得有深度。
在现代游戏开发的美术制作流程中,美术师将使用他们的 3D 建模应用程序基于超高分辨率的源模型生成法线贴图。然后将法线贴图映射到可直接用于游戏的较低分辨率的模型版本,从而使用法线贴图渲染原始的高分辨率细节。
法线贴图使表面法线的这种修改更进一步,使用纹理来存储有关如何修改模型上的表面法线的信息。法线贴图是映射到模型表面的图像纹理,类似于常规颜色纹理,但法线贴图纹理中的每个像素(称为纹素)表示平面法线方向与平面(或平滑插值)多边形“真实”表面法线之间的偏差。
该图再次以 2D 形式表示 3D 模型的表面上的三个多边形,每个橙色箭头对应于法线贴图纹理中的像素。下面的是法线贴图纹理的单像素切片。在中心位置,您可以看到法线已被修改,在多边形的表面上呈现出几个凹凸的外观。因为这些修改过的法线将用于光照计算,所以这些凹凸只会由于表面上的光照显示情况而变得明显。
原始法线贴图文件中可见的颜色通常具有蓝色色调,并且不包含任何实际的浅色或深色着色,这是因为这些颜色本身不打算按原样显示。实际上,每个纹理像素的 RGB 值表示方向矢量的 X、Y 和 Z 值,并作为对多边形表面的基本内插平滑法线的修改而应用。
这是一个简单的法线贴图,包含一些凸起的矩形和文本的凹凸信息。此法线贴图可导入到 Unity 中,并放入标准着色器的 Normal Map 字段中。在材质中与颜色贴图(反照率 (Albedo) 贴图)相结合并应用于上述圆柱体网格的表面时,结果如下所示:
同样,这不会影响网格的实际多边形性质,只会影响在表面上计算光照的方式。表面上明显凸起的字母和形状并不存在,以掠射角观察这些面时将揭示出平面表面的真实性质,但从大多数视角看,圆柱体此时看上去会具有从表面凸起的浮雕细节。
法线贴图和高度贴图 (Height Map) 是两种类型的凹凸贴图。二者都包含一些数据用于表示较简单多边形网格的表面上的明显细节,但各自却以不同的方式存储这些数据。
在上方左侧,您可以看到用于石墙凹凸贴图的高度贴图。高度贴图是一种简单的黑白纹理,其中每个像素表示该点在表面上看起来应该凸起的程度。像素颜色越白,该区域看起来越高。
法线贴图是 RGB 纹理,其中每个像素表示表面看起来应该面向的方向的差异(相对于其未经修改的表面法线)。由于矢量存储在 RGB 值中的方式,这些纹理往往为蓝紫色调。
现代实时 3D 图形硬件依赖于法线贴图,因为此类型的贴图包含了必要的矢量来修改在表面上反射光线的方式。Unity 还可接受高度贴图类型的凹凸贴图,但必须在导入时将其转换为法线贴图才能使用。
了解这一点对于使用法线贴图并不重要!您可以选择跳过这一段。但是,如果的确想要了解这部分,请参考以下信息:RGB 颜色值用于存储矢量的 X、Y、Z 方向,其中的 Z 为“向上”(与 Unity 通常使用 Y 作为“向上”的惯例相反)。此外,纹理中的值视为经过减半处理,并加上 0.5。这样就能存储所有方向的矢量。因此,为了将 RGB 颜色转换为矢量方向,必须乘以 2,然后减去 1。例如,RGB 值 (0.5, 0.5, 1) 或十六进制的 #8080FF 将得到矢量 (0,0,1),这便是用于法线贴图的“向上”,并表示模型表面没有变化。这就是您在此页面前文的法线贴图“示例”的平面区域中看到的颜色。
一个 (0.43, 0.91, 0.80) 值将得出 (–0.14, 0.82, 0.6) 矢量,这是对表面的大幅修改。在石墙法线贴图的明亮青色区域中,一些石头边缘的顶部可以看到这样的颜色。最终结果是,这些边缘捕捉光线的角度非常不同于较为平坦的石面。
法线贴图