本文已参与[新人创作礼]活动,一起开启掘金创作之路
转载请注明出处.
图形学的数学基础(三十三):纹理应用(中)
凹凸贴图(BumpMapping)
用于改变表面片元法线的技术统称为凹凸贴图(BumpMapping),凹凸贴图把各像素法线相关的信息存于一张Texture中,各像素的的法线通过这张纹理采样得到,使用采样得到的法线代替片元自身的法线进行着色光照计算,会看到凹凸不平的效果,是一种欺骗眼睛的效果。凹凸贴图思想最早由图形学大牛Jim Blinn提出,后来的Normal Mapping,Parrallax Mapping,Parallax Occulision Mapping,Relief Mapping,均是基于同样的思想,只是考虑的越来越全面,效果越来越逼真。
存储法线的几种方式
heightMap

heightMap存储的是表面的相对高度,该高度的变化实际上表现了物体表面凹凸不平的特质,但是高度值不能直接用来计算光照,必须先将其转换为法线,再通过法线计算光照,这就是heightMap的核心原理。但是有个问题是,我们如何通过高度值计算出法线呢?

要计算P点的法线,可以先求p点的切线,而切线正是函数曲线在p点的导数。
先拿二维的情况举例,点p的原始法线为(0,1),假设h为高度函数,根据差分近似求出点p的导数为:

dp=c∗(h(p+1)−h(p))
点p的切线矢量为:
tangent(p)=(1,dp)=(1,c∗(h(p+1)−h(p)))
将切线逆时针旋转90°,得到p点扰动后的法线。
normal(p)=[01−10]tangent(p)=[01−10][1dp]=[−dp1]=[−(c∗(h(p+1)−h(p)))1]
注:上述推导中c为常数,表示法线被扰动影响大小的因子。
将上述推导到三维过程,只需要计算uv两个方向的梯度,剩下的和二维一致,计算切线,逆时针旋转90°计算法线。
- 原始法线n(p)=(0,0,1)
- 分别计算nv两个方向上的梯度:
- dudp=c1∗(h(u+1)−h(u))
- dvdp=c2∗(h(v+1)−h(v))
- 被扰动后的法线: normal(p)=⎣⎡du−dpdv−dp1⎦⎤.normalized()
注:所有计算出的法线都是在切线空间下的,需要乘以TBN矩阵转换到世界空间!
BumpMapping
原始的凹凸贴图技术,由jim Blinn提出,后续的凹凸贴图技术都是基于其思想改进的。想法很简单,纹理贴图上每个像素点存储两个信息,一个是u方向的偏移矢量,一个是v方向上的偏移矢量。这样原始法线加上这两个矢量后自然得到了扰动后的法线。

NormalMap
我们知道Texture上可以存储三维的颜色作为漫反射系数,自然也可以存储法线向量的信息,利用(u,v)坐标查询每个点的法线向量,而不是用原始模型的法线信息,这就是normalMap。
明白了Normal Maps的原理之后,有一点重要的是,如何在存储这些法线信息呢?一种可选方案是存储对象空间下法线信息,这样在做完纹理查询后乘以世界空间矩阵直接就可以用了,但是不好的一点是,当对象空间发生变化时,那么该法线向量就不再正确了。更通用的做法是存储切线空间下的法线向量。
对象空间和切线空间法线贴图对比:

显然切线空间的存储方式更加灵活,不受制于种种限制,但是要付出的相应代价就是需要比较复杂的空间转换过程。
应用法线贴图后的渲染结果。

TBN空间
切线空间定义域每一个顶点之中,是由切线(Tangent),副切线(BiTangent),顶点法线(Normal)以模型顶点为中心的坐标空间。只需要下面两个步骤即可得到规范化的TBN矩阵。
E1=△U1T+△V1B
E2=△U2T+△V2B
一张图解释三种凹凸贴图的区别:

未完待续
参考
图形学基础 - 纹理 - 纹理映射盘点
Real Time Rendering
Normal Mapping
GAMES101 -现代计算机图形学入门-闫令琪