法线贴图

来源:互联网 发布:小车巡线算法 编辑:程序博客网 时间:2024/04/30 00:04

今天终于做了个凹凸映射,前段时间又耍了不少,罪过啊。。。由于电子书上居然少了关键的一页,只好把推导记录在这个地方,顺便总结一下,也算是加深印象。

 

法线图的构造是从高度图中提取每个像素的高度,对每个像素的法向量,要计算U,V方向上的切向量,这两个切向量依赖于这个像素的相邻的两个像素的高度差,最后法向量等于这两个切向量的叉乘。由于法向量存储在纹理中,所以需要将值转换到0,255范围内。

 

 

凹凸映射的光照计算需要在切线空间(tangent space)中进行,所以需要将光线向量从模型空间(object space)转换到切线空间,以下是切线空间的构造方法:

 

我们需要的切线空间,它的X轴与贴到三角形上的纹理的U轴平行,它的Y轴与V轴平行。

假设向量T,B就是满足上面条件的两个向量,那么对于三角形内任意一点Q,都有:

 

Q − P0 = (u − u0)T + (v − v0)B,

 

 

P0是三角形的任意顶点,u0,v0是这个顶点的纹理坐标,u,v是Q点的纹理坐标。 这里相当于用T,B两个基向量来表示任一向量。

 

 


 

假设我们知道三角形三个顶点分别为 P0P1,  P2, 相应的纹理坐标为 (u0v0), (u1v1), (u2v2),这样计算可以更简单,有以下等式:

 

Q1 = P1 − P0
Q2 = P2 − P0

 

这是三角形顶点构成的两个向量

 

(s1t1) = (u1 − u0v1 − v0)
(s2t2) = (u2 − u0v2 − v0).

 

这是纹理坐标构成的两个向量,我们需要的就是把Q1 Q2变换到纹理空间上去,于是有以下等式

 

 

Q1 = s1T + t1B
Q2 = s2T + t2B
T,B就是用来完成这个变换的两个向量,是未知的,我们需要解上面这个方程来得到他们。
做点线性代数就能得到T,B了。
当需要找到某个顶点的切向量时,和法向量的处理方法一样,需要平均所有共享这个顶点的三角形的切向量。对于邻接的三角形面的纹理贴图不同时,共享的顶点一般都是被复制了的,有多组纹理坐标,这时不需要将不同纹理贴图的三角形进行平均。
最后,由法向量N(是顶点的原本的法向量),切向量T,副法线B组成矩阵
 Tx
Ty
TzBx
By
BzNx
Ny
Nz .
用于把向量从切线空间变换到模型空间。

要将向量从模型空间变换到切线空间只需要求矩阵的逆即可。由于三个向量N,T,B不一定会互相垂直,那么矩阵不一定正交,其逆阵就不等于它的转置,但是这三个向量一般接近于正交,所以用斯密特正交化,不会造成不可接受的结果。
T′ = T − (N · T)N
B′ = B − (N · B)N − (T′ · B)T′
 T′x
B′x
NxT′y
B′y
NyT′z
B′z
Nz     
这个矩阵就用来从模型空间转换到切线空间。
将光线向量从模型空间转换到切线空间后,只需要直接与法线贴图中的法向量相乘即可得到漫发射。也可以通过在原法向量和法线贴图中的法向量之间进行插值,来控制凹凸程度。注意对于未经扰动的法向量(0,0,1)经过转换成RGB颜色存储在法线贴图中变成了(0.5,0.5,1.0),所以在插值的时候不要弄错了。
成果图:
凹凸贴图
推导的原文在这里:http://www.terathon.com/code/tangent.html