Tangent Space的基向量计算方法

本文详细介绍了在CG中如何利用TangentSpace进行坐标变换,特别是针对BumpMapping中NormalTexture的应用。通过解析三角面的几何信息,构建TangentSpace,并求解过渡矩阵,实现了ObjectSpace与TangentSpace之间的坐标变换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在CG中,基于Per-Pixel的算法经常会涉及到Tangent Space的坐标变换,比如Bump Mapping,需要将Object Space的Light Vector转换到Tangent Space,然后在和该Pixel上的Normal Vector进行计算,因为Normal Vector是在Tangent Space中的。


像上面的Bump Mapping,对于Normal Texture,如果Normal Vector(这里的Normal Vector不是指Vertex上的)是设计在Mesh的Object Space中的话,一方面,Mesh的复杂度导致Normal Vector不方便设计;另外,如果Mesh的形状发生改变,那么原来的Normal Vector将不能够适用。所以,将Normal Vector的设计就放在统一的一个空间里面(Tangent Space)中,然后通过一个Triangle Surface上的几何信息,进行几何变化,最后在同一个坐标空间来使用。

对于一个Normal Texture的图示,他里面所有像素上的Normal Vector都在u,v,n坐标系上的,这也就是Tangent Space:

当将一个Normal Texture贴到Mesh上后,单考虑一个Vertex,他对应于Normal Texture上的一个点(具体在哪由这个Vertex的Texture Address u-v指定),而他的法向量就对应了Tangent Space中的n,经过该Vertex,垂直于n可以构造出Tangent Space中的u-v平面,这实际上也就在Object Space中构造出了Tangent Space。如图所示,V1为该顶点,淡蓝色矩形框平面为对应的u-v平面:


在Object Space和Tangent Space两个坐标系下进行坐标变换必须找到这两个坐标系之间的过渡矩阵。
根据变换等式
<xo, yo, zo>*T = <xt, yt, zt>
<x0, y0, z0>  : 为Object Space中的基向量,实际上就是一个单位矩阵
T             : 过渡矩阵
<xt, yt, zt>  : 为Tangent Space的基向量

可见T = <xt, yt, zt>构成的矩阵,所以这里要求的就是这三个基向量

zt这里就是这个Vertex上的n。xt,yt分别对应于u,v两个基向量,这是后面要求的两个向量。
根据一个Triangle上面的贴图,可以构建这个模型:
记:
Vertex1 : V1(x1, y1, z1), T1(u1, v1), N1(nx1, ny1, nz1)
Vertex2 : V2(x2, y2, z2), T2(u2, v2), N2(nx2, ny2, nz2)
Vertex3 : V3(x3, y3, z3), T3(u3, v3), N3(nx3, ny3, nz3)


记:
T21 = T2-T1 = (u21, v21)
T31 = T3-T1 = (u31, v31)

V21 = V2-V1
V31 = V3-V1

则有
V21_ = V21-V21*N1*N1                        V21*N1*N1是V21在u-v平面上的投影向量
V31_ = V31-V31*N1*N1
V21_和V31_分别为V21和V31在u-v平面上的投影向量

在图中的
v21 = Len(V21)*Nor(V21_)
v31 = Len(V31)*Nor(V31_)
Len()为计算对应向量的长度,Nor()为单位化对应向量, v21v31 分别为将V21和V31"拉到"u-v平面上去的向量。

根据在tangent space和Object Space两个空间是同构的,可以列出下面的等式:
u*u21 + v*v21 = v21
u*u31 + v*v31 = v31

解该方程,得到 u,v,并单位化两个向量

通过上面的过程也就得到了<u,v,n>--->过渡矩阵T。
得到过渡矩阵T后,就可以任意的转化两个坐标系中的坐标。

其他:
1:<u,v,n>并不一定是标准正交基,所以T的转置矩阵并不一定等于T的逆矩阵。u,v的关系如何这要取决于上面的三个顶点的T1,T2,T3。
2:上面的计算过程是基于Vertex的,可以采用基于一个Triangle的计算方法,过程和上面是一致的,不同点在于这个时候u,v平面和Triangle平面重合。
3:在DirectX中有D3DXComputeTangent API对计算这三个基向量的支持。但是在他的描述中使用的是Tangent Vector(也就是u),Binormal Vector(也就是v)和Normal Vector(也就是n),且B = N Cross T





博客推荐文章

 

http://blog.chinaunix.net/uid-26651460-id-3083223.html

### 解决3D图形中的切线错误 在处理3D图形时,遇到切线(tangent)错误的情况并不少见。这类问题通常源于模型的空间变换或法线计算不当。 对于无法对几何体作切线的问题,在三维环境中确实存在特殊性,因为平面里的切线概念转化为3D环境下的切面[^1]。这意味着传统的二维切线工具可能不再适用,需要采用专门针对3维对象设计的方法来解决问题。 当涉及到具体软件应用如3DMAX时,可以利用顶点切线控制插件VertexTangants来进行调整。该插件允许用户通过预设值和参考更精确地调控样条线上各顶点的位置,从而间接影响到整个物体表面的平滑度以及由此产生的切线方向[^2]。 另外,从技术角度出发,如果要修正由坐标系转换引起的切线误差,则需关注于构建正确的变换矩阵\(M\)。此矩阵用于将模型空间(Object Space)内的数据映射至切线空间(Tangent Space),其构成要素包括经过标准化后的切向量\(T'\)、副法向量\(B'\)及法向量\(N\)三者共同形成的底集合\[ \begin{bmatrix} T'_x & B'_x & N_x \\ T'_y & B'_y & N_y \\ T'_z & B'_z & N_z \end{bmatrix}\][^3]。确保这些矢量正交且单位长度一致能够有效减少因坐标变化带来的失真现象。 为了更好地理解和解决实际项目中存在的切线错误: - **检查输入文件**:确认导入的数据源本身不存在缺陷; - **验证算法实现**:仔细审查负责生成/更新切线的相关程序逻辑; - **优化参数设置**:适当调整涉及切线计算的各项系数直至获得满意效果; ```cpp // 示例代码片段展示如何规范化一组给定的方向向量作为新的局部坐标轴 void NormalizeAxes(Vector& tangent, Vector& binormal, Vector& normal){ // 首先使normal成为单位向量 normal.Normalize(); // 让binormal垂直于normal,并保持原有朝向关系 float dotProduct = Dot(binormal, normal); binormal -= (dotProduct * normal); binormal.Normalize(); // 构建完整的右手坐标系 Cross(normal, binormal, tangent); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值