一、凹凸映射原理
凹凸映射[1]
主要用来模拟物体表面几何形状的凹凸起伏。其基本思想是通过扰动表面法向量,使得物体表面受光线照射的影响而产生视觉的变化,进而引起外观的改变,也就是生成视觉上假的凹凸效果。
步骤:
- 对输入的光滑表面计算法向量,并通过随机扰动改变法向。
- 使用新的法向替代原始光滑表面的法向,计算新的光照效果。
通常在第2步中采用局部着色技术(eg. Phong着色模型),就可以得到具有明显凹凸效果的物体外观。
法线贴图
每个fragment使用各自的法线,替代插值表面法线,并使用2D纹理来储存法线数据的技术叫做法线贴图(normal mapping)或凹凸贴图(bump mapping)。
法线方向的分量范围在 [ − 1 , 1 ] [-1,1] [−1,1],而像素范围为 [ 0 , 1 ] [0,1] [0,1]。因此,在shader中得到法线纹理的像素值后,需要做一个映射 n o r m a l = p i x c e l × 2 − 1 normal=pixcel\times 2-1 normal=pixcel×2−1,并归一化。
切线空间(tangent space)
法线贴图中的法线向量定义在切线空间中,在切线空间,三角面的切线永远指向
z
z
z方向。切线空间是位于三角形表面之上的空间——法线相对于单个三角形的本地参考坐标系。
TBN矩阵
TBN矩阵是一个基底变化矩阵,可以把切线空间的向量转变到世界坐标。构建TBN矩阵的三个向量:tangent(切线)、bitangent(副切线)和normal向量。
已知三角形的顶点和纹理坐标,可以计算得到tangent(切线)和bitangent(副切线)向量:
根据三角形顶点坐标,可求得边向量
E
1
E_1
E1和
E
2
E_2
E2,而
E
1
=
Δ
U
1
T
+
Δ
V
1
B
E
2
=
Δ
U
2
T
+
Δ
V
2
B
E_1=\Delta U_1T+\Delta V_1B\\ E_2=\Delta U_2T+\Delta V_2B
E1=ΔU1T+ΔV1BE2=ΔU2T+ΔV2B
解得(详细求解见[2])
[
T
x
T
y
T
z
B
x
B
y
B
z
]
=
1
Δ
U
1
Δ
V
2
−
Δ
U
2
Δ
V
1
[
Δ
V
2
−
Δ
V
1
−
Δ
U
2
Δ
U
1
]
[
E
1
x
E
1
y
E
1
z
E
2
x
E
2
y
E
2
z
]
\begin{bmatrix} T_x & T_y & T_z \\ B_x & B_y & B_z \end{bmatrix} =\frac{1}{\Delta{U_1}\Delta{V_2}-\Delta{U_2}\Delta{V_1}} \begin{bmatrix} \Delta{V_2} & -\Delta{V_1} \\ -\Delta{U_2} & \Delta{U_1} \end{bmatrix} \begin{bmatrix} E_{1x} & E_{1y} & E_{1z} \\ E_{2x} & E_{2y} & E_{2z} \end{bmatrix}
[TxBxTyByTzBz]=ΔU1ΔV2−ΔU2ΔV11[ΔV2−ΔU2−ΔV1ΔU1][E1xE2xE1yE2yE1zE2z]
-
如何使用TBN矩阵?
- 方案1:直接使用,把切线空间向量转换到世界坐标。把TBN矩阵传到fragment shader,采样得到的法线左乘上TBN矩阵,将法线转换到世界坐标空间,这样所有法线和其他光照变量就在同一个坐标系中了。
- 方案2:使用TBN矩阵的逆矩阵,把世界坐标空间的向量转换到切线空间。使用这个矩阵左乘其他光照变量,把他们转换到切线空间,这样法线和其他光照变量再一次在一个坐标系中了。
方案1实现起来简单,但是每个fragment都要将采样法线的转换到世界空间;而方案2只需要在vertex shader中将光照变量转换到切线空间即可,不需要每个fragment都计算一遍。所以本实验的做法是在vertex shader中计算切线空间的光照变量,发送到fragment shader。
视差贴图
高度贴图(Height Mapping),又名视差贴图(Parallax Mapping),模拟表面位移(Displacement),存储的是表面模型局部海拔高度的强度值(Intensity),颜色越深越凹,颜色越浅越凸。视差贴图背后的思想是根据观察方向和高度贴图修改纹理坐标,使一个fragment的表面看起来比实际的更高或者更低(利用高低信息实现遮挡效果)。
- 优点:直观展示模型表面的凹凸
- 缺点:实时计算时需要计算像素灰度值来得到法线信息,十分消耗性能。实际应用中,高度贴图通常与法线贴图一起使用,用于给出表面凹凸的额外信息。
原理
下图中,
V
ˉ
\bar V
Vˉ是观察方向,与模型平面相交于
A
A
A,此时观察者看到的是点
A
A
A,如果应用凹凸贴图,观察者本应看到的是点
B
B
B。视差贴图的目的就是在
A
A
A位置上的fragment不再使用点
A
A
A的纹理坐标而是使用点
B
B
B的。
如何得到
B
B
B的纹理坐标?
视差贴图通过对从fragment到观察者的方向向量 V ˉ \bar{V} Vˉ进行缩放的方式解决这个问题,缩放的大小是 A A A处fragment的高度 H ( A ) H(A) H(A),得到经缩放的向量 P ˉ \bar{P} Pˉ。这里使用切线空间下的 V ˉ \bar{V} Vˉ,这样 P ˉ \bar{P} Pˉ的 x x x和 y y y坐标值对应的就是相对于 A A A的纹理坐标偏移量。
陡峭视差映射
陡峭视差映射(Steep Parallax Mapping)通过增加采样数量提高精确性,是视差映射的扩展,采用多个样本来确定纹理偏移,即使在高度变化陡峭的情况下,也能得到不错的效果。其原理如图,将总深度范围划分为多个层,沿 P ˉ \bar{P} Pˉ逐层前进移动采样纹理坐标,直到我们找到一个采样低于当前层的深度值。
陡峭视差贴图同样有自己的问题。因为这个技术是基于有限的样本数量的,我们会遇到锯齿效果以及图层之间有明显的断层。可以通过增加样本的方式减少这个问题,但是很快就会花费很多性能。有些旨在修复这个问题的方法:在两个接近的深度层进行插值找出更匹配的
B
B
B,比如Relief Parallax Mapping和Parallax Occlusion Mapping。
视差遮蔽映射
视差遮蔽映射(Parallax Occlusion Mapping)和陡峭视差映射的原则相同,但不是用触碰的第一个深度层的纹理坐标,而是在触碰之前和之后,在深度层之间进行线性插值。
二、Demo功能(Qt+OpenGL)
Demo地址:https://github.com/messymorse/Parallax-Mapping-Demo
- 点击“凹凸映射 Demo”按钮:加载凹凸映射Demo
- 法线贴图(Normal Mapping)
- 视差贴图(Parallax Mapping)
- 陡峭视差映射(Steep Parallax Mapping)
- 视差遮蔽映射(Parallax Occlusion Mapping)
- 读取obj格式的mesh文件(支持漫反射贴图、光照贴图和法线贴图)
- 交互
-
拖动滑块控制模型旋转
-
控制相机移动
- 【W】【S】【A】【D】【Shift】【Space】进行前、后、左、右、上、下平移
- 鼠标滚轮zoom in/out
- 鼠标右键拖动视角
-
三、程序的输入输出格式
本次实验以长方形Mesh为例,其各个属性(位置Positions,法线normal,纹理TexCoords)在程序中给出。
输入:diffuse贴图,normal贴图,height贴图
输出:凹凸映射下的模型
四、参数的含义
程序可设置参数如图,具体说明如下:
- Rotate:模型绕轴(1,0,1)旋转的角度
- Normal Mapping:使用“normal_mapping”shader
- Parallax Mapping:使用“parallax_mapping”shader的普通视差贴图模式
- Deep Parallax Mapping:使用“parallax_mapping”shader的陡峭视差贴图模式
- Parallax Occlusion Mapping:使用“parallax_mapping”shader的视差遮蔽贴图模式
五、典型的效果
-
程序运行界面,其中白色方块是光源位置
-
无凹凸映射、Normal Mapping和Parallax Mapping对比(Blinn-Phong光照模型下)
左、中、右图分别是使用diffuse map、diffuse map + normal map和使用diffuse map + normal map + height map的效果
- 视差贴图、陡峭视差贴图和视差遮蔽贴图对比
六、分析优缺点
优点
- 包括法线贴图、视差贴图(基础视差贴图、陡峭视差映射、视差遮蔽映射)多种凹凸映射技术
- 可通过交互界面快捷地切换不同凹凸映射,拖动滑条旋转模型观察不同角度光照下的效果
缺点
- 只实现了基于平面的凹凸映射,对于网格模型只实现了法线贴图,这也是由于本程序只支持加载obj格式的模型,而一般obj模型不包含视差贴图。
Reference
[1]《现代计算机图形学基础》黄华
[2] OpenGL 教程 https://learnopengl-cn.github.io/ & https://learnopengl.com/Introduction
[3] OpenGL Qt实现入门篇 https://www.bilibili.com/video/BV1UL411W71w?spm_id_from=333.999.0.0