凹凸映射
纹理的一种常见的应用:凹凸映射。
我们知道,一般情况下,模型面数越高,可以表现的细节越多,效果也越好。但是,由于面数多了,顶点多了,计算量就大了。为了解决该问题就出现了凹凸映射。
凹凸映射就是通过修改模型表面的法线让模型看起来好像是“凹凸不平”的样子,增加细节层次感,达到高模的效果。但是可以从模型的轮廓边缘处看出“破绽”。
一:Bump Map(凹凸贴图)
凹凸贴图和纹理图很相似。但是不同的是,凹凸图包含的不是颜色信息,而是凹凸信息。最通常的方法是通过存储高度值实现。我们可以直接通过一张灰度图,默认为黑色,越凸起的地方颜色越亮.
二:Normal Map(法线贴图
与之前通过灰度表现界面的凹凸程度,进而修改法线的方式完全不同,这种Normal Map直接将法线存储到了法线贴图中,也就是说,我们从法线贴图读取的法线直接就可以使用了,而不是需要像上面那样,再通过灰度渐变值来修改法线。这种法线对于制作来说,没有灰度图那样直白,但是却是真正的法线贴图技术,所谓烘焙法线,烘焙的就是这个。
法线向量是个几何工具,而纹理通常只用于储存颜色信息,用纹理储存法线向量不是非常直接。如果你想一想,就会知道纹理中的颜色向量用r、g、b元素代表一个3D向量。类似的我们也可以将法线向量的x、y、z元素储存到纹理中,代替颜色的r、g、b元素。法线向量的范围在-1到1之间,所以在使用时我们先要把法线贴图采样得到的法线值从(0,1)映射到(-1,1)的范围:
//RGB映射到法线方向
float3 normal = rgb_normal * 2 - 1; // 从 [0,1] 转换至 [-1,1]
这是一种偏蓝色调的纹理,这是因为所有法线的指向都偏向z轴(0, 0, 1)这是一种偏蓝的颜色,这是因为在切线空间下,法线方向就是z轴的方向(0,0,1)经过映射后存储在纹理中就对应了RGB(0.5,0.5,1)淡蓝色。法线向量从z轴方向也向其他方向轻微偏移,颜色也就发生了轻微变化,这样看起来便有了一种深度。
//法线方向映射到RGB
float3 rgb_normal = normal * 0.5 + 0.5; // 从 [-1,1] 转换至 [0,1]
三:切线空间
法线一般是存储在切线空间下的,对于模型的每个顶点,它都有一个属于自己的切线空间,这个切线空间的原点就是该顶点本身,而z轴是顶点的法线方向(n), x轴是顶点的切线方向(t),而y轴可由法线和切线叉乘得到,也被成为副切线(bitangent)或副法线,这种纹理被称为 “Tangent-Space Normal Map”。
还有一种 “Object-Space Normal Map”,即该法线是存储在模型空间中的。
法线存储在模型空间中虽然更简单,直观,计算高效,但是它有一个非常大的弊端,就是该贴图和当前环境之间耦合太大了,一旦模型稍微做些改变,就需要更换法线贴图,不能复用。如果应用到其他模型上效果就完全错误了。
而 Tangent-Space Normal Map,它的优点非常多,自由度很高,即使把该纹理应用到另一个模型上也能得到一个比较合理的结果。可重用性高。
左边是Object-Space Normal Map,原因是它是基于Object Space存储的,方向各异。
右边则是Tangent-Space Normal Map,是偏蓝色的