Chapter 6 – Texturing 贴图

6.7 Bump Mapping(凸起映射)

本小节我们将主要学习一些基于“微观”的技术,它们可以表现物体的细节,而本文将其统称为bump mapping。所有的这些方法都是通过修改每一个像素的着色等式来实现的,相较于单一的贴图映射,这一技术能够让物体更具有“三维表现力”。而且我们并不需要添加任何额外的几何体。

物体的细节可以被划分为三个范围:宏观,覆盖多个像素;中观(meso),覆盖几个像素;微观,实际上覆盖区域小于一个像素。由于玩家或者用户能以不同的距离来观察一个物体,这三个分类并不是固定的。

宏观上来说,我们通过顶点和三角形,或者其他几何图元来表示几何体。当我们创建一个三维的游戏角色时,手臂和头一般以宏观的尺度进行制作。微观上来说,几何体是封装在着色模式中的,其由像素着色器来处理并且使用贴图映射作为参数。我们采用的着色模式将会模拟物体表面在微观层面上的“交互”,例如,有光泽的物体在微观层面就是光滑的,漫反射表面在微观层面就是粗糙的。角色的皮肤和布料显示出不同的材质是因为它们使用了不同的着色器,或者至少他们着色模式中的参数是不同的。

中观(meso)这一概念位于宏观与微观之间。其包含那些对于使用单个三角形面来说太复杂,但是用户能够分辨出其中的区别。角色面部的皱纹,肌肉的细节以及布料的褶皱都属于这一范畴。而bump mapping也会应用于这一层面,其将会在像素层面改变着色参数使得观察者能够看到使用bump mapping的几何体与基本几何体的区别。因此,bump mapping并不会改变几何体的构造(不会改变顶点的位置或者增加顶点)。

1978年,Blinn提出了将“中观”层面的细节编码为贴图。他发现,如果我们使用各个方向的向量来表示物体表面的发现,那么物体表面能展现出更好的细节。他将物体表面的法线数据存储在数组中。

而我们读取贴图并不是为了改变着色模式中的颜色值,而是改变物体表面的法线向量。代表物体的几何体的法线并未改变(例如,网格模型由三角形组成,每个三角形所对应的法线向量并未改变),我们只是改变了光照等式中所使用的法线向量。因此,这一操作在物理上没有意义;模型的几何体并未发生改变。

对于bump mapping来说,我们读取的法线必须应用,或者说转换到某个坐标系中。因此每一个顶点都拥有一个被称为tangent frame或者tangent-space basis(切线空间)。我们将光线转换至该坐标系用以计算法线对于光照的影响。而我们不但拥有法线映射贴图中的法线,还会存储顶点的法线向量以及顶点的切线向量与双切线向量。

因为我们的目标是将光线转换至法线映射贴图所处的坐标系,所以切线向量与双切线向量表示法线映射贴图在物体本地空间中坐标系的轴向。如下图所示。

法线向量n,切线向量t,和双切线向量b,共同组成了一个基本矩阵:

该矩阵有时也会被缩写为TBN,其将光线的方向(基于一个给定的顶点)从世界空间转换至切线空间。这三个向量并不需要互相垂直,因为法线映射贴图中的法线并不一定垂直于几何体的表面(三角形面)。但是一个非正交的基本矩阵会造成贴图的偏差,这也意味我们需要更多的存储空间,其还会影响性能,例如,我们不能通过矩阵的转置来表示逆矩阵。为了节省存储空间,一种办法是每个顶点只存储切线和双切线向量,之后在将两个向量进行叉乘以求出法线向量。但是,这一技术必须保证只使用右手法则或者只是用左手法则(两个向量的叉乘是有法向的,其可以指向“前方”也可以指向“后方”)。一般来说,模型都是对称的:一架飞机,一个人,一个文件箱等等。因为在渲染管线中,贴图将消耗大量的内存空间,所以贴图通常会被镜像翻转(mirror)到模型上。也就是说,我们只存储了一半的贴图,但是贴图映射则会运用于模型对称的两边。这种情况下,模型两边将分别使用左手法则和右手法则,也就是说,两边的切线空间也是不同的。不过我们只要在每个顶点内存储一个位信息(0或者1)来表示切线空间使用的是左手法则或是右手法则(例如,为0,那么我就要对切线向量与双切线向量的叉乘值乘以-1),这样我们仍旧只要一半的法线贴图。如果切线空间的三个轴向是互相垂直的,那么我们还能将其存储在四元数中,这样更能够节省存储空间并且减少运算。

切线空间的原理对于其他算法也极其重要。我们将在下一章节中看到,还有许多着色等式都是基于表面的法线向量的。此外,有些材质,例如,拉丝的铝或者天鹅绒布料,还需要知道观察者的视角以及光线的入射角。而切线空间能用于定义材质在表面上的各种方向。Schuler提出了一种方法,能够在像素着色器中计算切线空间的坐标轴,而无需在每个顶点中存储切线空间坐标轴。Mikkelsen改进了这一技术,其使用表面坐标位置的导数和高度的导数以计算法线向量。但是这一技术与传统的切线空间映射相比,所呈现的物体表面的细节更少,也会造成美术工作流程的一些问题。

6.7.1 Blinn方法

原始的Blinn bump mapping方法将在贴图的每一个纹理中存储两个带有符号的值,bubv。这两个值对应三角形的法线向量在贴图的u轴和v轴上的改变量。通常来说,这两个值是线性插值的,且用于缩放两个与法线向量垂直的向量。这两个向量将加上法线向量以改变其方向。下图展示了bubv是如何修正法线向量的。这一类bump map被称为offset vector bump map(平移向量bump map)或者offset map

上图左侧,法线向量nu轴和v轴的方向上移动了(bu,bv),而该值存储在bump贴图中,最后我们得到新的法线向量n’(需要注意,平移后的向量不再是标准化向量)。

另一种表示物体表面凹凸属性的方法是使用heightfield来改变法线的方向。而该贴图是黑白的,每一个纹理值都表示高度,所以白色的纹理所表示的高度将大于黑色的纹理。上图右侧则展示了heightfield以及其对于着色法线向量的影响。

6.7.2 法线映射

bump mapping常用的方法是直接存储一张法线映射贴图(normal map)。数学上来说,其算法与结果与上一节BIinn的方法相同;只是其存储格式与在像素着色器中的计算方法不同。

法线映射贴图将会把(x,y,z)编码入[-1,1],例如,对于一个8位贴图来说,x轴的坐标值为0则表示其为-1,而x轴坐标值为255则表示其为1。法线贴图中的颜色值[128,128,255],浅蓝色,其表示一个普通平面,若将其转换为法线向量,则是[0,0,1]。

最初法线映射贴图表示一个世界空间内的法线,其在实践中并不实用。对于这一类法线映射贴图,我们只需要在处理每一个像素时读取法线贴图中的法线向量并在着色等式中直接使用该向量即可。法线映射贴图还能定义在物体的本地空间,这样当模型发生位移或者转动时法线贴图中的法线仍然是有效的。但是,无论是定义在世界空间内的法线贴图还是定义在物体本地空间内的法线贴图,都将贴图与特定的模型进行了绑定,这无疑限制了贴图的再利用。

相反,物体表面的各个法线通常定义在切线空间内,也就是说其基于物体表面。这意味着物体的表面可以随意变形,也增加了法线贴图的实用性。切线空间的法线映射贴图还能进行较好的压缩,因为z轴坐标(平行与物体表面的宏观法线向量)通常是正数。

法线映射贴图能够很好的增加物体的现实表现。但是相较于颜色贴图的filter,对法线贴图进行filter更为困难。因为,一般来说,法线向量与最终的着色颜色并不构成线性关系,所以一般的filter方法可能会造成显示错误的问题。假设,场景中的物体是由白色花岗岩制成的阶梯。在某种角度下观察这个阶梯,我们可能会看到白色的镜面反射高亮。但是,如果阶梯的平均法线与表面的夹角为45°;那么平均法线所产生的高亮将完全不同于原始的阶梯表面。当我们进行渲染时不进行修正,就会造成各种错误效果。

Lambertian表面是一种特例,在这种情况下,法线映射贴图几乎与着色等式有着线性关系。这是因为Lambertian着色几乎是一个点乘运算,其是一个线性的运算。

需要注意的是,平均后的向量在使用前并未进行标准化。上述等式表明,标准的filter与mipmap几乎能够生成Lambertian表面的正确结果。我们这里使用几乎这一词,这是因为Lambertian着色等式并不完全是一个点乘运算;其会进行clamp运算——max(l·n,0)。而clamp这一运算将使得等式不一定是线性的。如果光线的方向是倾斜的,那么岂会使得表面比实际情况更暗,但是,在实践中,这一区别很难被发现。我们需要注意的是,有些法线映射贴图所使用的贴图压缩技术(例如,基于另两个变量重构z轴坐标)并不支持非单位长度的法线向量,所以使用非标准化的法线映射贴图将会增加压缩的难度。

如果物体表面并不是基于Lambertian的,那么我们可以将一组数据作为filtering的输入参数,而不是单单一张法线映射贴图。我们将在第九章学习该技术。

最后,我们可以通过height map(高度映射贴图)来求出法线映射贴图,h(x,y)。首先,求出x轴方向与y轴方向的导数:

那么,纹理(x,y)处的非标准化法线为:

水平映射贴图(Horizon mapping)可以进一步增加法线映射贴图的效果,其使得凸起部分能够在自身表面投影出阴影。我们将在第十一章中学习该技术。

留下评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据