[翻译] 凹凸贴图(bump mapping) 节选自RTR 6.7

这一节特别有趣,而且目测比较难懂,决定发动翻译大法

6.7 综述

这一节描述了一系列的小尺寸细节表达技术,统称为凹凸贴图 bump mapping。所有这些技术都通过每像素着色的程序来完成的。它们可以给予一个比单独的贴图更3D的表现,但是不如真正的几何效果。
细节可以根据大小分为三种:大型特征(macro-feature)——覆盖了许多pixel,中性特征(meso-feature)——横穿一些pixel,小型特征(micro-feature)——大体上小于一个pixel。这些策略多少是不固定的,因为观察者可能在不同的距离观察同一个物体。
大型几何使用点和三角来表示,或者其他几何度量面元。当创建一个3D角色的时候,头和躯体通常用大型规模来创建。小型几何是一个通常被压缩进shader model,通常是pixel shader用纹理贴图作为参数。shading model计算一个表面在为关机和上的交互,例如,发光的物体在显微镜下时光滑的,漫反射的表面在显微镜下是粗糙的。人的皮肤和衣服会有许多不同的材质,因为使用不同的shader,或者至少是在这些shader中的参数不同。
中型几何描述了在这两种尺寸之间的所有。包括太复杂以致于无法使用单独的多边形高效渲染的,但是足够大以致于能让观察者看出几个像素之间变化的表面曲率。人脸皱纹、肌肉细节、衣服褶皱,都是中型尺寸。对于中等尺寸,可以使用一系列的凹凸贴图大法(bump mapping techniques)。它们会把着色参数控制在一个像素的级别,从而让观察者观察到基础几何之外的小扰动,虽然实际上是平的。这些bump mapping的主要区别就是它们如何表示细节。它们将使用诸如真实度等级、细节复杂度等参数。
Blinn引进了这种把中尺寸细节编码进二维数组中的观点。它观察到,如果我们在着色阶段将法线增加一个小的扰动,那么表面会产生一些小的细节。它把描述这个表面法线的扰动的数据存进数组。
所以关键思路就是,在照明等式中,我们使用贴图来改变表面法线,而非颜色。表面的几何法线不变,我们几乎不改变光照等式中的法线。这个操作不是物理上的等价,我们修改表面法线,但是表面在几何意义上还依然是平的。
对于凹凸贴图,法线必须关于参照系(frame of reference)来变化。于是切线空间基(tangent space basis)为此存储在每个顶点中。这个参照系被用来把光纤变换到表面所在位置的控件(或者反之)来计算法线扰动所产生的效果。这种在顶点法线的基础上,对多边形表面还有一个法线贴图的存储方式,称之为tangent and bitangent vectors。
tangent and bitangent vectors表示了在物体控件的法线贴图的轴,因为目标是吧光纤转换到与贴图相关。
这三个向量:normal n, tangent t, bitangent b,形成了一个矩阵基:
这里写图片描述
这个矩阵把一个颜色方向从世界空间变换到切线空间。这些向量不需要真的互相垂直,因为法线贴图自己可能也被扭曲以适应表面。实际上,tangent和bitangent通常是不相互垂直的,虽然他们通常都和normal垂直。一个节省内存的方法是,对顶点只存储tangent和bitangent,然后用他们的叉积来计算normal。不过,这个技术要求矩阵的左右手属性是一样的。一个模型经常是对称的,飞机、人、文件夹等,因为贴图消耗大量内存,所以它们通常被镜像为对称模型。因此,模型只有一边的贴图被存储,然后映射到两边。这种情况下,切线空间的左右手会不同,而且不能假定。不过我们依然可以通过存储一点点附加信息在每个vertex上,来指示它的左右手属性。常用的表示是-1或1,这个值被用来与叉积结果相乘来获得正确的法线。
切线空间的理念对其他程序也很重要。下一章将要讲到,许多着色式(shading equation)仅仅依赖于表面法线。然而,有些材质例如拉铝丝、天鹅绒,还需要知道相对于观察者和光线的方向。切线空间基,对于定义表面的材质的方向很有用[761,884],[1139]展示了一种运行时的切线空间,不需要存储预先计算的每顶点的tangent值。

6.7.1 Blinn方法(Blinn’s Method)

Blinn的最初的凹凸贴图方法,存储一张在每个点有两个有符号值的纹理。这两个值相当于图像的uv。亦即,这些纹理值,被典型的双重线性插值,用作度量两个与法线值垂直的向量。这两个向量被添加到法线上,来改变它的方向。bu和bv也描述了表面在这一点面向哪个方向。这种凹凸贴图也称为“offset vector bump map”或“offset map”。
另一种表示凹凸的方法是使用高度场(heightfield)来改变表面法线的方向。每一个单色贴图纹理值代表了一个高度,例如白色代表较高黑色代表较低(或者反过来)。在创建或者扫描一个凹凸贴图时是一个很常见的格式。heightfield被用来获得有符号的uv,通过把两个相邻值来获得[1127],[401]给出了一个更好的权重。

6.7.2 法线映射(Normal Mapping)

凹凸贴图一个流行的格式是直接存储法线贴图。因为存储法线扰动的三个分量的花费,比起两个offset或者单个高度图,已经没有那么昂贵,并且减少了shading时的计算。它的程序和结果与凹凸贴图完全一样,只是存储格式变了。
法线贴图把(x,y,z)映射到[-1,1]上,比如,一个8bit的贴图,x值0意味着-1.0,255意味着1.0。
法线贴图最初被提出的时候,是在世界空间下的。这实际中很少使用。这种情况下,扰动的计算很直接:每个像素直接从法线贴图拿到法线来使用,和光线方向一块,计算这个位置在表面上的着色。这能起作用,是因为法线贴图存储的值的z轴正方向是向上的,和square的旋转方向恰好一致,一旦square旋转到另一个位置,就不能再用了。如果square没有面向上方,其中一个解决方案是制造一个新的法线贴图,新贴图里边所有的点都是用新的旋转来变换一次。这个技术很少被使用,因为同一个法线贴图甚至不能在同一个墙的两个面使用。即使法线贴图被使用了一次,这个物体也就不能再改变旋转或者位置或者其他变形了。
法线贴图可以定义在物体空间下。这种法线贴图在刚体变换后依然保持有效,但是不能经过任何变形。这种法线贴图也同样不能被重复使用在一个物体的不同部位,或者不同物体。虽然光线方向需要被转换到物体空间,但是这可以在application stage中做,不需要给shader增加任何限制。
通常扰动法线是在切线空间中的,亦即,关于表面本身的。这使表面的变形以及重复使用成为可能。切线空间的法线贴图的压缩也更简单,因为z分量的符号通常可以被假定为正的。它的缺点是着色时需要更多的计算,因为参照系会在表面上变化。
在一个典型的shading model中,表面和光线都必须在同一个空间:切线、局部、世界。一种方法是变换每个光线的方向到切线空间(从vertex出发的),然后对这些已经变换过了的向量在三角形内插值。其他一些与光照相关的值,也在着色等式中,例如half vector,也可以被变换,以及即时计算。这些值然后就与法线贴图中的值一起计算着色。只有照射到那个点上的方向的光纤会对着色有影响,并不是它们的绝对位置。这里所考虑到的就是,光线方向在三角形面片内几乎不变,所以可以被插值。对于单个光线而言,这比把表面法线转换到世界空间要来的快。这是一个频繁计算的例子:把光线每vertex变换,而不是每pixel的法线变换。
然而,如果使用了许多光线,那么把法线贴图变换到世界空间会更快。使用上边那个矩阵的逆即可。不是对表面上的大量的光线进行插值,而是一个简单的把法线贴图变换到世界空间。另外,我们会在第八章看到,发现总是要在世界空间被使用的,所以把光线变换到切线空间没有什么好处。变换到世界空间也可以避免切线空间的失真[887]。法线贴图可以被用来大幅增强现实感。
对法线贴图滤波是个复杂的问题,比起颜色贴图而言。通常,法线与着色颜色并不是线性的,所以普通的滤波手段可能会导致讨厌的失真。想象观察白色光亮大理石上用区块(block)做出的台阶,在一些角度,台阶的上方和侧面可以捕捉到光线,反射处明亮的高光。但是,台阶的平均发现是45度角,将会导致完全不同的高光的方向。如果没有对高光凹凸贴图进行正确的滤波,就会出现烦人的闪烁,因为高光的闪烁取决于采样点碰巧到了哪里是降低的。
朗伯表面(理想散射表面)是一个特殊的情况,此时法线贴图对于着色而言有一个近乎线性的效果。朗博着色几乎是直接的点乘,这是个线性操作。把一组法线平均后点乘等于点乘后平均。不过注意平均后的向量并没有被归一化,所以也并不能说完全相等,因为郎伯着色时一个钳位的点乘(clamped dot product)。这个钳位使得它不线性。这在斜视向光线方向时,会使表面过度变暗。不过实际上这通常可以忍。一个警告是:一些典型的贴图压缩技术(比如用xy重建z)不支持非单位长度的法线,所以使用非归一化的法线贴图可能导致压缩问题。
对于非朗伯表面,可以通过把输入值和着色等式当做一个整体来滤波,从而达到更好的效果,而不是仅仅滤波法线贴图。7.8.1将会讨论这一技术。

6.7.3 视差贴图(Parallax Mapping)

法线贴图的一个问题是,凹凸的部位不会互相阻塞。如果顺着一个真正的砖墙看,在一些角度你会看不到砖块之间的灰浆。凹凸贴图不会展示出这样的现象,因为它几乎不改变法线。最好是能让凹凸真的有位置的影响。
视察贴图的想法在2001年被Kaneko引进,由Welsh重新定义并发扬光大。视差(Parallax)指的是当观察者移动的时候,物体之间的关联也会移动。当观察者移动,凹凸会互相遮挡,表现的就像有了高度。视察贴图的关键想法是,通过检查那个高度会发现什么东西,来猜测那个像素处应该看到什么。
对于视察贴图而言,凹凸定义在一个高度场纹理中。当观察表面上一个给定的像素,就取那个位置的高度场的值,移动纹理坐标,来取的表面的另一个位置。移动的大小基于高度值和表面到人眼的角度。如下图。
这里写图片描述
高度场的值可以被存储在一个独立的贴图中,也可以包裹进其他贴图的一个未使用的颜色通道中(注意当把不同纹理包裹起来的情况,可能对压缩质量造成不好的影响)。高度场的值在用来偏移的时候会先经过压缩偏斜。压缩决定了高度场应该高于或低于表面多少,偏斜是指不需要偏移的“海平面”高度。当给定一个位置p,矫正过的高度场高度h,归一化了的观察向量v(vx,vy,vz),新的视差校正过的位置p_adj为:
这里写图片描述
注意与大多数着色等式不同的是,这个等式在哪个空间会有影响:观察向量必须在切线空间。
在一个简单的近似中,这个偏移在实际中工作得相当好,如果凹凸高度变化的相对缓慢的话。附近的邻居texel会有几乎相同的高度,所以使用初始位置的高度作为新位置的高度也没什么。然而,这个方法不适用于能看到影子的角度。当观察向量几乎与表面水平时,一个小的高度会导致很大的纹理坐标移动。这个近似就会失败了,因为获得的新位置的高度也不必原位置的高度正确多少。
为了改善这个问题,Welsh引进了偏移限(offset limit)的想法。亦即把偏移限制得不大于获得的高度,亦即:这里写图片描述
注意这个等式比最初的等式更容易计算。它的几何意义是,高度定义了一个以他为中心的圆,所有偏移不能超出这个圆。
这里写图片描述
对于大的角度,这个等式几乎和最初一样,因为vz几乎是1,在小的角度,偏移值被限制在它的影响范围。观察结果是,让视差在小角度时效果削弱。但是这比本质上在贴图上随机采样要好多了。当市交变换的时候像纹理眩晕(texture swimming)这种问题依然存在,以及立体渲染(stereo rendering),当观察者有两个观察点,需要给予相同的深度值时。
即使有这些缺点,使用带偏移上限的凹凸贴图仅仅使用ps中的一点点附加消耗,就给予相当大的图像质量提升。出于这些原因,它在游戏中被广泛使用,并且被视作凹凸贴图的标准应用。

6.7.4 浮雕贴图(Relief Mapping)

凹凸贴图自己并不考虑高度场,所以并不改变纹理坐标。视察贴图提供一个简单的的高度场效果的近似,基于一个pixel处的高度近似于另一处的假定。这个假定可能很快崩溃。而且,偏斜(bias,i.e. “sea-level”)的设置会影响到高度场的显示效果。我们想要的是在pixel出可见的是什么,亦即,视线第一次与高度场的交汇。
这个问题有许多不同方向的研究。所有的的方案都采用了沿着视线向量,进行近似的光线追踪,直到找到交点。在一个传统的光线追踪器中,程序会顺着光线遍历格子,产生高度场,检查相关几何体在哪个格子相交。GPU-based方案通常使用一个不同的方案,影响ps获得贴图数据的能力。
在计算机图形选,一如其他领域,有时候时间也在为一个与众不同的想法做准备。三组互相独立的研究者们几乎同时探索出了浮雕贴图的想法。Brawley和Tatarchuk展示了一种直接找交点的方法,稍后用求根(root finding)进行了扩展;Policarpo[1020,1021]和McGuire和McGuire[846]独立的发现了类似的方法。这些算法有许多名字:视察闭塞映射(parallax occlusion mapping / POM),浮雕贴图(relief mapping),以及陡峭视差映射(steep parallax mapping),不过本质上是同样的方法。简称浮雕贴图。有趣的是,沿着光线采样纹理的基本程序在13年前就被Patterson发现了,又称逆位移映射(inverse displacement mapping)。这些新的研究者都没有在研究视察映射的时候注意到它。它们无疑是被人遗忘的基于CPU的研究的璞玉,为GPU做了准备。
这里的关键想法是,在投影向量上取固定数量的贴图采样。在切线角(grazing angle)的位置会有更多采样,以保证不错过最近的交点。取每个纹理坐标并处理,决定它是高于还是低于高度场。如果发现了一个低于高度场的采样,而且前一个采样更大,那么这个采样就被置为相交位置。
这里写图片描述
于是,新的相交位置就被用作表面着色、相关的法线贴图、颜色贴图,等等。多层高度场(multiple layered heightfield)可以被用作产生悬垂效果(overhang)、独立的重叠表面、双面浮雕映射的假象,参见10.8。
高度场寻迹方法(heightfield tracing approach)也可以使凹凸表面上产生阴影,软阴影[1021,846]和硬阴影[1244,1248]皆可。对比图如下:
这里写图片描述
计算两个固定采样的交点,是一个求根问题。实际中,高度场(heightfield)更多是被当做深度场(depthfield),由多边形平面定义表面的向上方向的上限。这时,表面上的最初的点是高于高度场的。在找到最后一个大于的点,和第一个小于的点,在高度场表面上,Tatarchuk[1244,1248]使用一步割线方法(secant method)来找到一个近似解。Policarpo[1021]使用一个二分查找(binary search)在两个点之间找到一个近似解。Risser[1068]使用遍历的割线方法(iterating using a secant method)加速了这个收敛(convergence)。这里有一个折衷:规则的采样可以在视差里做到,然而遍历的方法需要更少的纹理读取,但是需要等待结果,而且是更慢的独立贴图读取。
对高频率的高度场的采样相当重要。McGuire和McGuire[846]提出了一种把mipmap的上方向(lookup)偏移,使用各向异性的mipmap来保证高频率的高度图也正确采样,比如钉子和头发。也可以通过将高度图存储为比法线贴图更高分辨率。最后补充下,有些渲染系统甚至不支持法线贴图,而倾向于在计算式对高度图进行一个叉积滤波。
另一个提升效果和采样频率的途径是,在一开始不要用一个固定的间距对高度场采样,而是跳过中间的空白(intervening space)。Donnelly[271]预处理高度贴图到一个立体像素(voxel)的集合,每个立体像素中存储了它距离高度场表面有多远。用这种方法,中间空白可以被快速的跳过,代价是每个高度图使用更高的存储。Wang[1322]使用一个五维的位移映射(displacement mapping)策略来保存从各种方向和位置到表面的距离。这使得复杂曲面、自阴影(self-shadowing)、以及其他效果成为可能,代价是相当大的内存。由Dummer[283]引进,由Policarpo和Oliveira[1023]改进了,一个称之为圆锥台阶映射(cone step mapping)的想法。这里的理念是给每一个高度场的位置,储存一个圆锥半径(cone radius)。这个半径定义了,在这个距离上,至多会与高度场有1个交点。这使得快速跳过光线而不会错过任何一个可能的交点,代价是需要读取一个独立的贴图。另一个缺点是需要计算并创建出一个cone step map,使得这个方法不适用于动态变化的高度场。Schroeders和Guilik[1134]提出了四叉树浮雕贴图(quadtree relief mapping),这是一个分层方法(hierarchical method),在遍历时跳过大块(volume)。Tevs[1264]使用“maximum mipmaps”来使得预计算的费用最小化。
虽然这是一个研究活跃的领域,而且与特定GPU架构息息相关,根据初步测试,其中一个在时间和空间上都很高效的浮雕映射方法是,Tatarchuk[1244]的线性光线行进和单步正割校正(linear ray-marching with single-step secant correction)。更新的方法,例如圆锥步进(cone-stepping)和四叉树浮雕映射(quadtree relief mapping),都不在这个不完全统计中。不可置疑的是,这一领域还会有更多的研究来持续改进算法。
浮雕贴图方法的一个问题是,图像会在物体的轮廓边缘处露馅儿,显现出原始表面的平滑轮廓。
这里写图片描述
这里的关键是,所要渲染的三角形决定了那个像素会被ps计算,而不是表面实际上位于哪里。而且,对于曲面,这个轮廓问题更加明显。其中一个方法由Oliveira和Policarpo[964,1334]剔除,这个方法使用一个四叉树轮廓近似技术(quadratic silhouette approximation technique)。Jeschke[610]和Dachsbacher[223]给出了一个更一般更健壮的方法来处理轮廓和曲面。首先由Hirche[552]探索的一个想法,挤出网格中的每一个多边形,形成一个棱镜(prism),渲染这个棱镜将强制计算所有高度场可以达到的地方。这种途径也叫作剥皮映射(shell mapping),因为扩张的网格在原始表面上形成了一个独立的外壳。通过保留棱镜与光纤相交时非线性的特点,无伪影(artifact-free)的高度场渲染成为了可能,虽然计算昂贵。
综上所述,看下图吧。
这里写图片描述

6.7.5 高度场纹理

渲染模型凹凸的一个显然的方法是作为真的几何体来渲染,使用一个非常好的网格。一个空间更有效的选择是,使用顶点纹理获取特性(vertex texture fetch feature)——在SM3.0中被引进的——来在一个平坦的网格多边形上获取一个高度场纹理。从这个纹理上获取的高度场,被vs程序用来改变顶点的位置。这个方法通常被叫做位移映射(displacement mapping),然后这个高度场被称为位移贴图(displacement texture)。使用贴图可以更快的改变数据,例如博文模拟(wave simulation)和其他网格动画。这些技术在内存和处理上都会昂贵,因为网格上的每个顶点都需要三个附加的浮点数,每个都必须被访问(越少内存被摸到越好)。对于较大的范围,例如地表和海洋,使用细节技术来把复杂度降低,才能适用。参见12.5.2。GPU对统一的shader和实时曲面细分(tessellation on the fly)有了改进,天平似乎已经向着这种方法倾斜了。它会很容易编程,在新的GPU上也很少有缺点。这很有可能:当最小的GPU也需求支持快速访问顶点纹理的时候,这种技术将更流行。Szirmay-Kalos和Umenhoffer[1235]有一个优秀且透彻的关于浮雕贴图和位移方法的纵览。
虽然浮雕和位移贴图提供了更多的现实感,这些技术还是有一些缺陷。事实上基础的未扰动的表面可能进行碰撞检测(collision detection),这使得物体相交变得更加有挑战性。例如,如果一个位移贴图被用来在地面上进行扰动而生成一个石头,那么想要让人物的脚停在合适的位置就需要额外的工作。并非与网格进行一个简单的检测,网格的高度也会需要被访问。
另一些不是简单四边形的位移贴图也可以使用。在13.5.6将会讲述它用在细分曲面(subdivision)上。在13.6,我们将会展示硬件曲面细分(hardware tessellation),那里位移映射也会被使用(displacement mapping)。

【完】

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值