上一章:【Unity3D技术文档翻译】第2.3.3.5篇 平滑度(Smoothness)
本章原文所在章节:【Unity Manual】→【Graphics】→【Graphics Overview】→【Materials, Shaders & Textures】→【Standard Shader】→【Material parameters】→【Normal map (Bump mapping)】
法线贴图(凹凸贴图)(Normal map (Bump mapping))
法线贴图是一种凹凸贴图。是一种允许你为表面添加细节的特殊纹理,比如模型的凹凸、凹槽、划痕等,并且看上去将像真的几何体一样捕捉光线。
举个例子,你可能想要展现一个分布了凹槽、螺丝或铆钉的表面,就像飞机外壳。实现这些模型细节的一种方式是使用几何体,如下图所示:
一张使用了真实几何体建模的飞机金属板。在这种情况下,使用真实几何体构建这么细小的模型通常不是一个好主意。在上图右侧,你能看到为了制作一个螺丝头所需要的多边体。在一个具有许多致密表面细节的大模型上,将需要绘制大量的多边体。为了避免这点,我们应该使用一张法线贴图来表现这些致密的表面细节,并且使用一张较低分辨率的多边形表面来表现较大的形状模型。
如果我们使用一张凹凸贴图来表现这些细节,物体外观的几何体将变得更简单,而且纹理上的这些细节能够调节物体表面的反射光。现代图形硬件能够非常快地处理这些。你的金属表面现在可以是一个低多边形平面,而螺丝、铆钉、凹槽和划痕将通过法线贴图捕捉光线,就像它们真的具有深度。
螺丝、凹槽和划痕被定义在法线贴图中,法线贴图重新构造了光线在低多边平面的反射方式,创建了具有3D细节的效果。铆钉和螺丝也是如此,一张纹理将允许我们包含更多类似精密凹凸和划痕的细节。在现代游戏开发的艺术管线中,艺术家将使用他们的3D建模软件来生成基于高分辨率源模型的法线贴图。接着将法线贴图映射到模型的低分辨率版本中,以便使用法线贴图呈现原始的高分辨率细节。
如何创建和使用凹凸贴图
凹凸贴图映射是一个相对古老的图形技术,但仍然是创建详细的真实实时图形所需的核心方法之一。凹凸贴图通常也被称为法线贴图( Normal Maps)或者高度贴图( Height Maps),然而这些术语的含义略微不同,将在下面进行解释。
什么是表面法线?
要真正解释法线贴图是如何工作的,我们首先将描述什么是“法线”,以及它在实时光照中是如何使用的。可能最基本的例子是一个模型,在这个模型中,每个表面多边形都是根据相对于光的表面角度来照明的。表面角可以表示为从表面垂直方向伸出的线,相对于表面的这个方向(一个矢量)被称为“表面法线(surface normal)”,或者简单地说,一个法线(normal)。
两个12面圆筒,左边是扁平阴影,右边是平滑阴影在上图中,左边的圆筒有基本的扁平阴影,并且每个多边形都根据它相对于光源的角度进行阴影处理。每个多边形上的光在多边形区域的表面都是一致的,因为表面是扁平的。下面有相同的两个圆筒,带有各自可见的线框网格。
两个12面圆筒,左边是扁平阴影,右边是平滑阴影右边的模型具有和左边一样数目的多边形,然而阴影却表现得很平滑——横跨多边形的光线使表面呈现出曲面。这是为什么呢?原因就是反射光线上每一点的表面法线(surface normal)在多边形的宽度上逐渐变化,所以对于表面上的任何一个给定点,光线都会像曲面一样反射,而不是它实际上扁平一致的多边形。
作为2D视图,扁平阴影圆筒的三个表面多边形看起来将像下图这样:
2D视图,三个多边形上扁平阴影分布表面法线使用橙色箭头来表现。这些法线的值被用于计算光线是如何从表面反射的。因为表面上的每一点法线具有相同的方向,所以每个多边形表面上的反射光方向也都是相同的。于是产生了扁平阴影,这也是左边圆筒的多边形表面具有硬边缘的原因。
而阴影平滑的圆筒,表面法线在扁平多边形上的每点都是不同的,如下图所示:
2D视图,三个多边形上的平滑阴影分布法线方向随着扁平多边形表面的位置逐渐改变,因此遍布表面的阴影看起来就像是平滑的曲面(如图中的绿色线)。这么做并没有实际改变网格的表面性质,只是改变了光线在扁平表面上的计算方式。表面上的曲面不是真实的样子,并且从切线角去看,仍然能看到扁平多边形原始的样子。然而在大多数可视角度上,圆筒看上去都具有一个平滑的曲面。
在这个基础的平滑阴影中,决定法线方向的数据实际只被存储在每个顶点(per vertex)上,因此只需要对表面上的顶点之间做插值改变即可。如上图所示,红色箭头代表每个顶点上存储的法线方向,黄色箭头代表多边形区域上做插值改变后的法线方向。
什么是法线贴图?
通过使用一张纹理存储模型表面法线更改的信息,法线贴图对表面法线做更进一步的处理。一张法线贴图就是一张映射了模型表面的纹理图片,和普通的颜色纹理类似,只是法线贴图纹理上的每一点像素(称为纹理像素(texel))代表了表面法线方向与扁平多边形真正的表面法线之间的偏差值。
2D视图,三个多边形上的法线贴图分布在上图中,是3D模型表面上的三个多边形的2D表现,每一个橙色箭头都绑定到了法线纹理贴图上的一个像素。图的下面是一张法线纹理贴图的单像素切片。在图形中心,你能看到因为多边形表面上一对凸起的外观,法线被改变了。只有当光线照射在表面上时,这些凸起才会很明显,因为这些更改的法线只作用于光照计算。
一个原始法线贴图上的可见颜色主要是青蓝色调,并且没有包含任何实际的光暗阴影——这是因为颜色本身并没有打算被显示。取而代之的,每个纹理像素的 RGB 值代表了 X、Y 与 Z 轴上方向矢量的值,并被应用于多边形表面上平滑法线插值的更改。
一个法线贴图纹理的例子这是一个法线贴图的例子,包含了一些凸起矩形和文字的凹凸信息。这种法线贴图能被导入 Unity,并放置进标准着色器的法线贴图槽中。当和一张颜色贴图(反照率贴图(Albedo map))一起被合并进一个材质中,并且应用于圆筒网格表面上时,结果如下图所示:
法线贴图应用于圆通网格表面的例子再次说明,这么做并没有实际改变网格的表面性质,只是改变了光线在表面上的计算方式。表面上的凸起的单词和形状 不是真实的样子,并且从切线角去看,仍然能看到扁平多边形原始的样子。然而在大多数可视角度上,圆筒的表面看上去都具有类似浮雕的细节。
我们如何获取或创建法线贴图?
通常,法线贴图由3D或纹理艺术家协同他们制作的模型或者纹理的制作而成的,而且它们通常反映了反照率贴图(Albedo map)的布局与内容。它们有时由手工制作,有时由3D软件渲染而成。
如何从3D软件渲染发现贴图超过了本文档的范围,然而基本的概念是3D艺术家会制作两个版本的模型——一个非常高分辨率的包含了所有多边形细节的模型,以及一个低分辨率的准备用于游戏的模型。高分辨率模型细节太多以至于在游戏中不能很好地运行(网格中有太多三角面),但是可被用于3D软件中生成法线贴图。低分辨率模型可以忽略非常精细的几何细节,因为这些细节现在被存储在了法线贴图中,因此可以使用法线贴图来替代渲染。一个典型的应用案例是展示角色衣服上的折痕、按钮、带扣以及缝合处的凹凸细节。
有些软件包可以分析常规摄影纹理中的光照信息,并从中提取法线贴图。它的工作原理是假设一个固定光源照亮了原始纹理,然后分析光暗区域,推测出表面角度。然而,当实际使用一张凹凸贴图时,你需要确保反照率(Albedo)纹理图像上没有包含来自某个方向的光照信息——理想情况是,它应该呈现没有任何光照信息的表面颜色——因为光照信息将由 Unity 根据光的方向、表面角度,以及凹凸贴图的信息计算得出。
这里有两个例子,一个是简单的石头墙纹理及其相关的法线贴图;另一个是角色的纹理图集及其相关的发现贴图:
石头墙纹理及其法线贴图 角色纹理图集及其法线贴图凹凸贴图、法线贴图和高度图的区别是什么?
法线贴图(Normal Maps)和高度图(Height Maps)都是一种凹凸贴图(Bump Map)。它们都包含了代表简单多边形网格表面外观细节的相关数据,但是它们存储该数据的方式不同。
左边为用于石头墙凹凸贴图的高度图;右边为用于石头墙凹凸贴图的法线贴图上图左边是一张用于石头墙凹凸贴图的高度图。高度图是单纯的黑白纹理,纹理上的每个像素都代表了表面上该点应该升起的高度。其中像素颜色越白,该区域看上去升起得就越高。
一张法线贴图是一张 RGB 纹理,纹理上的每个像素代表了表面上该点相对于没有改变的法线的方向差异。这些纹理倾向于蓝紫色风格,就是因为这种将向量通过 RGB 值存储的方式。
现代实时3D图形硬件依赖于法线贴图,因为它们包含了那些修改光线如何从表面反射所需的向量。Unity 也能使用用于凹凸贴图的高度图,但是为了使用它们,在导入时必须被转换为法线贴图。
为什么是蓝紫色?
理解这点对使用法线贴图并不重要!因此可以跳过这段。然而如果你真的想知道:RGB颜色值被用于存储 X、Y、Z 方向向量,其中 Z 代表“上”(与 Unity 中通常约定 Y 代表“上”不同)。此外,纹理中的数值被当成已经减半,即乘以0.5。这允许存储所有方向向量。因此想要将一个 RGB 颜色转换为一个方向向量,你必须乘以2,再减去1。举个例子,一个为(0.5,0.5,1)的 RGB 值,即十六进制为 #8080FF,计算后结果为(0,0,1)向量,该向量就代表了法线贴图上的“上”——即代表了模型表面没有任何变化。这就是你在本页前面看到的法线贴图例子上扁平区域的颜色。
一个只使用 #8080FF 十六进制颜色值的法线贴图,转换为法线向量就是“笔直向上”的(0,0,1)。这没有对多边形的表面法线做修改,因此没有对光线做任何改变。任何与该颜色不同的像素值,都会导致那点的方向向量改变——因此那点的反射光角度在计算时会产生改变。一个(0.43, 0.91, 0.80)的值得到的是(-0.14, 0.82, 0.6)向量,这对表面是一个陡峭的改变。在石头墙法线贴图中,这样的亮蓝色代表了某些石头边缘的顶部。结果是光线在这些边缘的角度,相对于在石头平面的角度是非常不同的。
法线贴图中的亮蓝色区域代表了每块石头顶部边缘上表面多边形的陡峭改变,它们将以正确的角度捕捉光线。法线贴图
没有凹凸贴图效果的石头。石块的边缘与切面没有捕捉到场景中的太阳光。 同样的石头墙,但是具有凹凸贴图。面向太阳的石头边缘反射太阳光的效果,与石头平面及背阳处边缘非常不同, 同样的具有凹凸贴图的石头墙,但是在不同的光照情景中。一个火把点状光源照亮了石头。石头墙上的每个像素,根据光线照射到基本模型(多边形)上角度的不同,以及根据法线贴图中的向量进行调整,而被照亮。因此面朝光源的像素是明亮的,背离光源的像素则更暗或在阴影中。如何导入并使用法线贴图和高度图?
法线贴图可以通过将纹理文件像往常一样放入你的资源文件夹进行导入。然而,你需要告诉 Untiy,这张纹理是一张法线贴图。为了实现这点,你可以在导入检查器设置( import inspector settings)中,将“Texture Type”设置为“Normal Map”。
导入黑白高度图和导入法线贴图的操作步骤完全一样,除了需要勾选“Create from Greyscale(从灰度等级创建)”选项。
当“Create from Greyscale(从灰度等级创建)”被勾选,一个 Bumpiness (凹凸度)滑动条将出现在检查器中。当将高度图中的高度转化为法线贴图时,你可以使用该滑动条控制法线贴图中角度的陡峭程度。一个低的 Bumpiness 值将意味着即便是高度图中有强烈反差的地方,也将被转换为温和的角度与凹凸程度。一个高的 Bumpiness 值将创建夸张的凹凸程度,并且光线照射到凹凸表面时将具有非常强烈的反差。
当将一张高度图作为法线贴图导入时,低和高 Bumpiness 值的设置,以及反应在模型上的效果。一旦在你的资源中有一张法线贴图,你就可以在材质检查器中的法线贴图选项槽中配置它。标准着色器中就有个法线贴图槽,并且许多老版本着色器中也都支持法线贴图。
一个使用了标准着色器的材质,放置了一张法线贴图纹理在正确的选项槽中。如果你导入了一张法线贴图或者高度图,但是没有将它标记为一张法线贴图(通过将 Texture Type 选项选择为 Normal Map,上面提到了这点),材质检查器将发出警告,并如下图所示提供了解决该警告的途径:
当尝试使用一张法线贴图,却没有在检查器中标记过,那么 “Fix Now” 警告就会出现。点击 “Fix Now” 与在纹理检查器设置中将 Texture Type 选项选择为 Normal Map 具有相同的效果。如果你的纹理的确是一张法线贴图,那么就将起作用。但是如果它是一张灰度高度图,那么就不会自动检查这点——因此对于高度图,你必须谨记要在纹理检查器窗口中选择 “Create from Greyscale(从灰度等级创建)”。
二级(次级)法线贴图( Secondary Normal Maps)
你可能也注意到,在标准着色器的材质检查器中的最下方有个二级法线贴图选项槽。这允许你使用一张额外的法线贴图来创建额外的细节。你可以像向常规法线贴图选项槽中添加贴图一样,向该选项槽中添加法线贴图,但是要注意,你应该使用不同的缩放等级与平铺频率,因此这两张法线贴图将一起创建一个在不同缩放等级下的高度(形容词)的细节。
举个列子,你的常规法线贴图可以定义墙壁或者车辆上的镶板细节,以及镶板边缘的格栅。而二级法线贴图可以基于常规法线贴图的5到10倍来平铺,提供表面上划痕与磨损的非常精细的凹凸细节。这些细节可以十分精细,因为只有在近距离下观察才可见。如果是在基础法线贴图上实现如此数量级的细节,基础法线贴图的大小将急剧增加,然而通过在不同的缩放等级上使用两张相对较小的法线贴图纹理,就可以获得高度(形容词)的整体细节。
如果本文对你有帮助的话,点个赞或者评论一下吧!
网友评论