法线贴图使用中的疑问(一)

1.为什么法线要保存在切空间中?

我们知道光照计算,只要保证各个向量在同一个空间坐标系下就可以算出正确的光照强度,那为什么我们在写shader的时候会在切空间进行光照计算呢?

在回答这个问题之前,我们先来看看为什么法线要存储在切空间中。我们用排除法来说明这个问题,如果法线存储在世界坐标系中,只要物体在世界空间中发生了位置变化,这张法线贴图就失效了。为了解决这个问题我们可以把法线存储在模型空间中,就和模型的顶点一样,当模型发生旋转,平移的时候,法线只需要乘上相应的变换矩阵就可以转换到世界坐标系下。这看起来很完美,但是我们忽略了一个问题。假设我们的模型都是刚体的话,这个方案没有问题。但是如果模型做了变形(想象一下皮球被按出一个坑)那每个顶点的法线该乘以一个什么样的矩阵才能转化到世界空间呢?

顶点从模型空间转换到世界空间,其实就是通过平移,旋转,缩放,三个因素确定一个变换矩阵,然后顶点乘以这个矩阵就转换到世界空间中了。但是皮球变形,这个即不是平移,也不是旋转,也不是缩放,之前的变换矩阵失效了。我们能不能找到一个变换矩阵来模拟变形的过程呢?答案是能,但不是一个变换矩阵,而是针对每个顶点的变换矩阵。这块有点抽象,我们回想一下,法线贴图中的每一个点都是一个向量,之前我们把法线存储在模型空间中,每个像素点就对应了模型空间中的一个向量。当模型发生移动时,每个顶点都会发生相同的移动,所以用一个变换矩阵就可以变换贴图中所有的点。但是模型做了变形,每个顶点的移动是不同的,这个时候就不能用一个变换矩阵去处理所有法线了。理所当然,我们要为每一个顶点寻找一个新的坐标系,也就是说法线贴图上的每一个像素点的坐标系都是不一样的。这个坐标系就是顶点的切空间。如果要把法线转换到世界空间中,它的变换过程就是切空间->模型空间->世界空间。而之前我们的转换过程是模型空间->世界空间。总结一下使用切空间法线的优缺点:

优点:

1.支持模型变形动画

2.可压缩,由于Tangent-Space Normal Map中法线的Z方向总是正方向的,因此我们可以仅存储XY方向,而推导得到Z方向。

3.可复用,比如,一个砖块,我们可以使用一张Normal Map,应用到不同的面上。

缺点:

1.空间变换需要额外计算TBN旋转矩阵

回答了法线为什么要存储到切空间,就可以回答为什么我们做光照计算要放到切空间中了。因为如果放到世界空间每个顶点的法线都需要转换到世界空间然后再做计算,而在切空间计算只需要把光源向量和视角向量转换到切空间就可以了。

2.法线的切空间是怎么计算出来的?

我们知道法线是垂直于三角面的一个向量,我们用N来表示法线,用T来表示切线,B来表示副切线。有了三个正交向量就能组成一个新的空间,TBN这个空间就是法线的切空间。

现在已知N这个向量,能和N组成正交向量的T,B,在空间上有无数种组合,我们应该使用哪一种组合呢?其实无论哪种组合都是可以的。我们之所以选出一种组合,是为了达成一种约定,无论是什么软件大家在计算切空间的时候都按照这种约定去计算,这样大家计算出来的结果是一致的。这样即便顶点中没有附带T,B信息,游戏引擎依然可以计算出对应的切空间。让我们看看都有哪些约定。

1.已知三角形的三个顶点在模型空间的坐标A(x0,y0,z0),  B(x1,y1,z1), C(x2,y2,z2)

2.已知三个顶点在纹理UV空间中的坐标<s0, t0>,  <s1, t1>, <s2, t2>

3.已知法线向量N(模型空间)

4.已知B,T和三角形共面

我们需要通过以上条件计算出一种“约定”的唯一解B,T,N。为什么叫约定的唯一解呢?因为上面的四组数据如果不约定的话是不能求出唯一解。而这个约定就是下面的代数公式。查看了很多文章,所有文章的公式推导都是基于下面两个代数方程。但是这两个方程是怎么来的,没有人回答,如果有大神知道的话还请赐教。我粗超的理解是,下面两个公式很像共面向量定理,也就是说E1,E2,T,B这四个向量共面。根据定理p=xa+yb,我们已知了x,y求a,b。这里的x,y的取值就是一种约定。

E1 = ΔU1T + ΔV1B

E2 = ΔU2T + ΔV2B

接下来的推导过程网上有很多,我就转载了一份附上转载链接:

https://blog.csdn.net/huangzhipeng/article/details/52915724

令ABC内的某个点为Q,其uv坐标为<s, t>,  让Q用如下代数式表示:
Q - A  =  (s - s0)  * T  +  (t - t0) * B
已经知道了B, C两点,所以有方程组:
B - A  = (s1 - s0) * T  + (t1 - t0) * B                                (1)
C - A  = (s2 - s0) * T  +  (t2 - t0) * B                               (2)
如果T, B是可以求出来的,那么就说明是可以推导出的。
      
先求T,由(1)&(2)得:
==>(B - A) * (t2 - t0) =  (t2 - t0)  * (s1 - s0) *T+  (t2 - t0) * (t1 - t0)  * B  (3)
      (C - A)* (t1 - t0) =   (t1 - t0)  * (s2 - s0) *T+  (t2 - t0) * (t1 - t0)  * B  (4)

==>(B - A) * (t2 - t0) - (C- A) *(t1 - t0) = [  (t2 - t0) * (s1 - s0)  - (t1 - t0)  * (s2 - s0) ] *T
==>T  = ( (B - A) * (t2 - t0) - (C-A) *(t1 - t0) ) /  (  (t2 - t0) * (s1 - s0)  - (t1 - t0) * (s2 - s0))  (5)
      
再求B, 由(1)&(2)得:
==>(B - A)  * (s2 - s0) = (s1 - s0) * (s2 - s0) *T   +  (t1 - t0) * (s2 - s0) * B  (6)
      (C - A) *  (s1 - s0) = (s1 - s0) * (s2 - s0) *T   + (t2 - t0) * (s1 - s0) * B  (7)

==>(B - A) * (s2 - s0) - (C -A) * (s1 - s0)   =  [ (t1 - t0) * (s2 - s0)  - (t2 - t0) * (s1 - s0) ]  *B
      B =  (  (B - A) * (s2 - s0) - (C -A) * (s1 - s0)  )  /  ((t1 - t0) * (s2 - s0)  - (t2 - t0) * (s1 - s0) )  (8)
对(8)调整一下分母的符号,保持与(5)的分母一致,可得:
B =  - ( (B - A) * (s2 - s0)  - (C -A) * (s1 - s0)  )  /  ( (t2 - t0) * (s1 - s0)  -  (t1 - t0) * (s2 - s0) )  (9)

通过上述的方程组,求得唯一的B, T.   那么B, T 是互相垂直的吗? 答案是:不一定!
为了得出一个正交的坐标系,我们需要对B, T, N 进行施密特正交化。
新的切向量T' B'(尚未normalize):
T'=T-(N*T)N
B'=B-(N*B)N - (T'*B)T'
这样我们就得到了N, B', T' 作为我们的新坐标系基本轴向量。

这里有两个有两个细节问题。

1.为什么求出的B,T不是互相垂直的?

没有为什么,谁说这个公式推导出的结果就是正交向量了,不要被网上T就是U轴,B就是V轴搞混。

2.B,T,N为什么可以进行施密特正交化。

因为BTN这三个向量线性无关,TB和三角形共面,N是三角形的法线,所以TBN三个向量不共面,这三个向量线性无关,可以进行进行施密特正交化。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是我为你制定的学习计划: 第一部分:基础建模 1. Blender界面介绍和基础操作 - 了解Blender软件的界面和主要功能区域 - 学习Blender的基本操作,例如选择、移动、旋转、缩放等 2. 基础建模技巧 - 学习如何使用基本几何体进行建模 - 学习如何使用编辑模式进行细节处理 - 掌握添加、删除、合并等操作 3. 高级建模技巧 - 学习如何使用曲线、NURBS等进行建模 - 掌握如何使用Modifiers进行建模 第二部分:纹理制作 4. UV展开 - 学习如何进行UV展开 - 掌握如何使用纹理贴图 5. 法线贴图 - 学习如何使用法线贴图进行高保真度纹理制作 6. 烘焙 - 学习如何使用Blender进行模型烘焙,例如法线烘焙、AO烘焙等 第三部分:渲染和后期处理 7. 材质和贴图 - 学习如何使用材质和纹理贴图 - 掌握如何创建材质和贴图 8. 灯光设置 - 学习如何使用不同类型的灯光 - 掌握如何进行灯光设置 9. 渲染设置 - 学习如何设置渲染参数,例如分辨率、采样率等 - 掌握如何进行渲染设置 10. 后期处理 - 学习如何使用Blender自带的后期处理功能 - 掌握如何使用外部后期处理软件进行处理 对于每节课的重点和难点,你可以在学习过程自己记录笔记,对于比较难的部分可以多花些时间和精力去理解和掌握。建议你在学习过程多动手实践,例如可以根据教程做一些练习题或者自己设计一些模型进行练习。同时,如果遇到问题可以多使用网络资源和社区进行交流和求助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值