作者:i_dovelemon
日期:2017-03-07
来源:CSDN
主题:Normal Map, Normal Mapping, Tangent Space
引言
GraphicsLab(GLB)代码库之前只支持Diffuse贴图和Alpha贴图,想要做出更加精细的效果,需要增加对其他类型贴图的支持,所以最近将Normal贴图也整合到GLB中去。通过使用Normal贴图,在结合Normal Mapping的技术,我们就能够渲染带有更多微小细节的物体。
凹凸映射(Bump Mapping)
自然界中存在很多具有丰富细节的表面,如石板面和墙壁:
如果我们要以三角形建模的方式来对这种细节进行建模的话,一方面很复杂,另一方面如此细小的几何体渲染出来的效果应该也很杂乱。所以,图形学家便想出了通过一个二维数组来编码保存一个几何体表面细节的方案,以此来模拟具有丰富表面的物体。最初的时候,是通过一张高度图来保存一个物体表面高低不平的高低信息,然后以此信息作为渲染的依据,从而渲染出表面的微小细节。此种技术被称为Bump Mapping,后来衍生出更多的算法来模拟表面细节,并且将这些模拟表面细节的技术都统称为Bump Mapping。我们今天要讨论的主题Normal Mapping就是Bump Mapping的一种。
更多关于Bump Mapping的信息,可以查看
wiki上关于它的描述。
法线映射(Normal Mapping)
Normal Mapping是Bump Mapping的一种。这种技术将一个粗糙表面上各个微小的细节编码成法线,保存在一张法线贴图上,然后在进行光照计算的时候,不使用从顶点属性插值过来的法线,而是从这张法线贴图上获取对应位置的法线进行光照计算。
大体的思路就是上面描述的那样,从中可以看出一个很明显的要点,那就法线贴图是什么?
法线贴图(Normal Map)
我们知道,一个归一化的法线,它的XYZ坐标分量都在[-1,1]这个范围里面。而在渲染中创建查找表的方式,都是将我们所需要的信息放在一张纹理上,毕竟GPU能够很方便的访问纹理贴图。
所以,我们将法线的XYZ值进行编码,以便于存放在对应纹素的RGB中。虽然纹理的格式有很多,但是我们一般都选择使用R8B8G8的格式,也就是说我们需要将[-1,1]的范围映射到[0,255]的范围里面来。这个映射可以通过简单的线性变换得来,即对于法线的每一个分量进行(N + 1) * 128这样的计算,那么结果自然就在[0,255]之间。同样的,当我们在GPU中访问该纹理的时候,也可以通过逆向的运算来得到实际的法线分量值,即:(T - 0.5) * 2.(注:shader中访问纹理的结果在[0,1]的范围里面)。
相对于一个表面来说,一个指向它正半空间的法线才是有效的法线(回忆一下光照方程就知道这点),所以法线值的Z分量总是为正值,所以法线贴图总体呈现蓝色(B分量总是大于128),如下图所示&#x