http://blog.csdn.net/huazai434/article/details/5650146
一,法线贴图实际上是一张纹理图,但纹理中存储的并不是颜色值,而是法向量坐标。这项技术的主要目的是实现物体表面的粗糙细节。
二,法向量在纹理中的存储形式。对于24位纹理格式,r g b 三个元素中分别存储了法向量的三个坐标值。
然而,法向量三个坐标值 的取值范围均为(-1.1),而纹理格式中rgb分量的范围是(0,255),因此我们必须做相应的变换。变换方程如下:
f(x)=(0.5x+0.5)*255
当我们从纹理文件中读取纹素值后,我们便需要将其从(0,255)转换成(-1,1)。由于tex2D函数返回值范围是(0,1)因此我们只需做如下的变换:
f(x)=2*x-1
三,如何生成法线贴图。
法线贴图通常由灰度高度图产生。在灰度高度图中,不同点的高度h是不同的。而各点的法向量便是法线贴图中对应纹素的法向量。
首先通过有限差分格式近似出两个切向量,然后叉乘求得法向量。公式如下:
dhOverdx=[f(xi+dx,yi)-f(xi-dx,yi)]/2dx
dhOverdz=[f(xi,y+dy)-f(xi,y-dy)]/2dy
u=(1,dhOverdx,0);
V=(0,dhOverdy,1);
n=cross(u,v);
注:我们还可以利用这个方法来计算TBN。
所谓TBN是指tagent,binormal 和normal。对于某一个顶点来讲,T 和B 是两个切向量,而N 是法向量。这三个向量组成一个坐标系的三个基,这个坐标系便是纹理坐标系。法线纹理中的向量便是相对于纹理坐标系的。
当然,TBN的计算方法可谓是多种多样,我看过各种各样的计算方法,但最基本的思路便是这个有限差分法。实际上,只要思路正确,采用哪种具体的计算方法并不重要,应为TBN本来就是近似的,没有精确值。而且,各种计算方法在效果上的差别甚微。
四,利用法线贴图计算光照值。
我们首先要解决的问题是坐标系不统一的问题。计算光照需要光线向量,视点向量,和法向量。前两者位于世界坐标系下,法向量则位于纹理坐标系下。因此需要将光线向量和视点向量从世界空间变换到纹理空间,然后进行光照计算。如何变换呢?
首先计算TBN。如果是自定义网格,则按照如上所述进行计算。如果是D3DXMesh类型,可使用如下函数:
D3DXComputeTangentFrameEx(参数略);这个函数的好处是可以对TBN进行插值,正如对法向量进行插值一样。
然后将TBN写成3x3矩阵形式:(TBN的坐标是相对于物体空间)
Tx Ty Tz
M = Bx By Bz
Nx Ny Nz
这个矩阵是从纹理空间到物体空间的变换矩阵。
其逆矩阵M-1即转置矩阵是从物体空间到纹理空间的变换矩阵。
这个过程在VS中完成,并将光向量和视点向量传递到PS,进行标准化后,便可进行Phong处理。