一些奇奇怪怪的贴图技术
工作中经常会遇到各种各样的mapping,比如displacement mapping、parallax mapping等,从字面上来看,很难一眼看清楚这些名词代表的是什么含义,为了能够对这些技术有一个粗浅的了解,这里单开一篇文章来将这些贴图的相关技术整理到一起。
这篇文章是一些特殊贴图技术的整合,会不定时的对内容进行更新,其中主要关注各类贴图技术的如下几个要点:
- 贴图技术的含义与作用
- 贴图技术的具体实现原理
- 贴图技术的局限性
一些常见的贴图技术如normal map,cubemap等就不放在里面了。
1. Displacement Mapping
Displacement Mapping是Cook在1984年提出的,跟normal map是通过对法线进行调整,用光影效果来模拟细节不同,Displacement Mapping最终是会对物件的几何形状进行调整(比如增加面片数)来提升真实感的技术。
那么Displacement Mapping长什么样,它是怎么实现细节提升的呢?这个贴图只使用一个通道,类似于Height Map,之后根据顶点的法线方向,使用uv采样得到的displacement对顶点的高度进行调整。
上图给出了Bump/Normal/Displacement Map的外观以及应用效果。
这里有个问题需要考虑: 既然是通过这种方式来对顶点进行调整,那么顶点数要足够多才能生成足够丰富的细节,从性能角度考虑,那么Displacement貌似并不占优势,为什么不直接使用高模进行渲染呢?
- 顶点是运行时通过tessellation生成的,可以节省顶点存储与CPU/GPU传输的消耗
早年没有tessellation shader的时候,displacement mapping的性能还是很成问题的,现在就好很多了。
上图中给出了Displacement Mapping作用后的绘制效果,可以看到不论是物件表面还是边缘轮廓,真实感都比较好。
2. Bump Mapping
跟Displacement Mapping不同,Bump Mapping是通过对顶点或者像素的Normal进行修正,之后将修正后的Normal用在光影计算中来fake(模拟)表面凹凸感的技术,其中Normal Mapping可看成是Bump Mapping的一个变种,是目前应用最广的Bump Mapping技术。
上图中左侧就是使用Bump Mapping后的渲染效果,虽然物件表面上是能看到比较明显的凹凸感,但是模型边缘细节以及阴影边缘细节还是光滑表面的效果,真实感还是存在瑕疵,此外,Bump/Normal Map也不能使用Mipmap来实现随着距离调整的平滑过渡效果。
3. Parallax Mapping
Parallax Mapping(视差贴图)也叫offset mapping或者Virtual Displacement Mapping,这种技术是对Bump/Normal Mapping无法实现随着视线变化而导致的遮挡效果的问题的补充处理方案。
这项技术是2001年由Tomomichi Kaneko et al.等人提出,可以用于实现比Normal Map更为真实的细节效果,这里有个视频展示了视差贴图输出的效果。
Paralax Mapping是通过对平面上像素的uv坐标进行调整来实现的,调整的输入参数有两个:
- tangent space(切线空间)下view angle(与表面法线之间的夹角)的函数
- 当前像素点的从height map中采样得到的height数值
此方案的实施流程与大致原理如上面两图所示。
从定性角度来看,当view angle越大(即与表面法线夹角越大),uv坐标的偏离程度也就越大,从而营造一种随着视角变化,看到的物件表面信息也随之变化的真实感错觉。
Kaneko给出的原始实现方案没有考虑遮挡信息,而后续的修正增强版本则在此基础上添加了遮挡处理以及更为精确的轮廓绘制效果。
上面介绍了parallax mapping的基本实现原理,具体的做法还没有解释清楚,下面通过几种常用的实现方案来解释这一部分内容。
Steep parallax mapping
也叫Relief mapping 或 parallax occlusion mapping,指的是通过ray marching策略为屏幕空间每个像素生成一条射线,之后计算这个射线与物件表面height field的交点,据此来调整此点的uv坐标的做法。
Parallax Mapping的实现性能主要取决于Ray Marching过程中的采样点确认方式上,下图给出了Relief Mapping中常用的线性查找与二分查找两种确认策略:
从表现来看,二分查找可以得到更为精确的匹配结果与更为优越的显示质量,不过二分查找也有其对应的问题,比如当射线与height field存在多个交点的时候,二分查找是有可能找到后面的交点,这是不正确的。
还有人通过Sphere Tracing[7]实现交点查询的,即根据当前射线采样点到当前采样点的高度只差作为下一个采样点的step进行查询,这个方案可以得到比二分查找更为精确的匹配结果:
除此之外,也有人[5]尝试使用上一个采样点的法线的切线与射线的交点作为下一个采样点的迭代查询方案,这个方案的优点是利用了法线信息来提升查询精度,从而不需要如Sphere Tracing一样进行额外的3D贴图采样,基本原理如下图所示:
Interval mapping
这个方案是对传统belief mapping方案的改进,传统方案是按照二分查找的方式来实现ray与height field碰撞点的计算,而Interval Mapping则是根据已知的height field内部以及外部点,(在内部点的heightfield上与外部点的height field上)构建一条直线,之后使用ray与这条直线的交点作为下一个待检测的计算点,下图(e)(参考文献[6])就指的是这种算法:
这里也顺便对上图中的其他几个小图的算法逻辑进行简单介绍吧:
- (a)图指的是inverse displacement mapping方法的基本原理,后面几张图是对这个方案中点查询算法的补充,总的来说可以分成两类,分别是root finding算法(前四种算法)与space leaping算法(后两种算法),后一种算法通常能够取得更高的精度与更优的性能,不过缺点就是可能需要进行一些预处理。
- (b)图指的是以上一个采样点对应height field上点的高度为水平线,计算其与射线的交点作为下一个采样点
- (c)图指的是使用定长作为采样step,当查找到一个处于height field内部的点如6时,就将这个点的位置与上一个点的位置连线,并以射线与这个连线的交点作为相交结果
- (d)图指的是先按照定长step进行相交检测,之后发现内部点时再采用二分查找匹配交点的Relief Mapping算法
- (f)图指的是一种叫做safety radius的交点检测方法,safety radius是通过对一张预先生成好的贴图进行采样得到的,给出了各个位置的safety radius,之后再遇到内部点的时候,还是需要通过二分查找来确认精确交点。
- (g)图指的是前面介绍过的Sphere Tracing方案
参考文献
[1] Displacement Mapping
[2] Bump Mapping
[3] How displacement maps work and how to optimize them in V-Ray Part 1
[4] Parallax mapping
[5] Iterative Parallax Mapping with Slope Information
[6] A Prism-Free Method for Silhouette Rendering in Inverse
Displacement Mapping
[7] Chapter 8. Per-Pixel Displacement Mapping with Distance Functions