【法线贴图原理】
如果法线处于世界坐标中的(world space),那称为world space normal。如果是处于物体本身局部坐标中的,那称为object space normal。
如果物体没有保持原来的方向和位置,那原来生成的normal map就作废了。
一张贴图只能对应特定的一个模型,模型不能有变形(deform)。
只需要计算面上的坐标系到世界坐标系的转换矩阵,那么定义在这个面上的点或坐标(固定的),乘以这个矩阵即可得到在世界中的坐标。这个坐标系术语里称为tangent space。
按照新方法每个面都有一个局部坐标系,当低模变形时,即三角面变化时,它的tangent space也会跟着变化,保存在贴图里的法线乘以低模这个面的tangent space到外部坐标系的转换矩阵即可得到外部坐标。
CG中顶点已经自带tangent、normal信息,TxN即可得到B。T、B、N即可构造出切换空间。
现在我们可以分析为什么tangent space法线贴图是偏蓝色了.因为这个面渲染时计算机认为这个面的"弯曲"程度很小,即面上各个点插值得来的法线相互间偏差很小.基本跟整个面的垂直方向不会差太多.因此在tangent space里,这些法线都跟z轴偏差较小.而z轴是被保存在贴图里的b字节处(蓝色通道)里.所以贴图显示出来的颜色就偏蓝了.
你会发现后一种方法不好.因为对于面上的每个点,都要计算一次normal到world space的转换.而前一种方法,对一个面上的所有点,只要计算一次光向量到tangent space的计算.然后再考虑到vertex shader与fragment shader的流程,你会发现刚好我们可以在vertex shader计算光线到tangent space的转换,在fragment sader取出法线值与前面得到的tangent space里的光线方向做计算即可.这里提醒一下,一般verteix shader中我们得到的光线方向是基于world space的,而法线贴图保存的是高模的object space内的方向然后再转换到tangent space,所以在vertex shader中,我们必须先把光线先转换到object space,再转换到tangent space.这样才能保证最终计算时,光线与法线是基于同一个坐标系的.这也是你在很多normal map的shader里,看到类似ToOjectSpaceDir(lightDir)之类函数的原因,正是要把光转换到object space.
参考: