您的位置:首页 > 移动开发 > Unity3D

法线贴图

2016-06-14 19:52 302 查看
1. 个人理解法线贴图

  在做动画的时候,面会变形,顶点关系改变了,即面的形状,方向改变了,如果面上存在一个固定的坐标系,那当物体变形,移动,旋转时,这个坐标系必定跟着面一起运动,那么在这个坐标系里的某个点或向量(比如我们把高模法线转换到这个坐标系里),不需要变动,当整个面发生变化时,我们只需要计算面上的坐标系到世界坐标系的转换矩阵,那么定义在这个面上的点或坐标(固定的),乘以这个矩阵即可得到在世界中的坐标,这个坐标如何构造目前对我们不重要,请务必理解这个概念.我们不过是寻求一个局部坐标系,局部坐标系中的点坐标,乘以局部坐标系到世界坐标系的转换矩阵(这个矩阵是低模渲染时动态计算的的),得到局部坐标系中的点在世界坐标系中的坐标,这样法线贴图中存储的固定的值(法线方向),才能进行有意义的计算。

   看到这里很明显的,这种做法需要数千个不同的定义在面上的坐标系。低模上有多少个面,就得有多少个这样的坐标系。这种方法的计算量自然是比object space normal map要大一些的,在低模的每个面上,要构造出这个坐标系。这个坐标系术语里称为tangent space。

法线贴图保存的是高模的object space内的方向然后再转换到tangent space,所以在vertex shader中,我们必须先把光线先转换到object space,再转换到tangent space.这样才能保证最终计算时,光线与法线是基于同一个坐标系的,这也是你在很多normal map的shader里,看到类似ToOjectSpaceDir(lightDir)之类函数的原因,正是要把光转换到object space。

  低模上的这个tangent space,也必须与高模上的坐标系tangent space。因为低模上的一个面,可能对应了高模上的几个面(精度高),按照新方法每个面都有一个局部坐标系,那对于低模上的每个面,高模因为存在好几个面,就会出现好几个局部坐标系,这肯定是不行的.所以高模所用的tangent space,就是低模上的,生成法线贴图,必定会确认高模上哪些面都对应低模上的哪个面,然后高模上的这几个面的法线,都会转换为低模这个面上所构建的tangent space的坐标.这样,当低模变形时,即三角面变化时,它的tangent
space也会跟着变化,保存在贴图里的法线乘以低模这个面的tangent space到外部坐标系的转换矩阵即可得到外部坐标,顺便再提一点,高模保存的这个法线,是高模上object space里的法线,看到这里你该明白这是自然而然的。你搜索文章时可能会看到什么把光转换到tangent space里,确保处于同一个坐标系下的话.确实是这样.但初次接触却还是模糊.我以为确保tangent sapce重合及做法,才是让人顿悟tangent space的诀窍点.

总结:法线纹理的RGB通道存储了在每个顶点各自的Tangent Space中的法线方向的映射值。

2.  UnpackNormal 的作用

因为一个向量每个维度的取值范围在(-1, 1),而纹理每个通道的值范围在(0, 1),因此我们需要做一个映射,即pixel = (normal + 1) / 2。这样,之前的法线值(0, 0, 1)实际上对应了法线纹理中RGB的值为(0.5, 0.5, 1),而这个颜色也就是法线纹理中那大片的蓝色。这些蓝色实际上说明顶点的大部分法线是和模型本身法线一样的,不需要改变。

总结一下就是,法线纹理的RGB通道存储了在每个顶点各自的Tangent Space中的法线方向的映射值,所以,UnpackNormal 就是把RGB中(0, 1)的值转换实际用的(-1, 1)的法线的值。

参考网址:

写给笨人的法线贴图原理  :
http://www.cnblogs.com/flytrace/p/3387748.html

【Unity Shaders】法线纹理(Normal Mapping)的实现细节 : http://blog.csdn.net/candycat1992/article/details/41605257

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  unity3d