模型不等比缩放后法线不再垂直表面的问题

如果模型矩阵执行了不等比缩放,顶点的改变会导致法向量不再垂直于表面了。因此,我们不能用这样的模型矩阵来变换法向量。下面的图展示了应用了不等比缩放的模型矩阵对法向量的影响:

每当我们应用一个不等比缩放时(注意:等比缩放不会破坏法线,因为法线的方向没被改变,仅仅改变了法线的长度,而这很容易通过标准化来修复),法向量就不会再垂直于对应的表面了,这样光照就会被破坏。

 

修复这个行为的诀窍是使用一个为法向量专门定制的模型矩阵。这个矩阵称之为法线矩阵(Normal Matrix),它使用了一些线性代数的操作来移除对法向量错误缩放的影响。

法线矩阵被定义为「模型矩阵左上角的逆矩阵的转置矩阵」。

 

具体推导过程为:

vertexEyeSpace = modelViewMatrix * vertex;

modelEyeSpace = modelViewMatrix * vec4(normal, 0);

 

已知线段T = p2-p1;(P2和P1是两个顶点的位置)

T' = T * modelViewMatrix = (p2 - p1) * modelview;

= p2 * modelview - p1 * modelview;

也就是说相当于p‘2 - p'1

假设:

N = Q2-Q1;

因为线段和法线的点乘必须要为0

dot(T,N) = 0;

所以转换后的线段和法线的点乘也必须为0才是我们想要的

dot(T',N') = 0;

 

假设视图左上角的子矩阵为M

然后假设矩阵G是变换法向量的正确矩阵

得:

dot(G*N, M*T) = 0;

根据点乘公式得出dot(t,n)=|t|*|n|*cosα。

得:

dot(T', N') = dot(G*N, M*T) = inverse(GN) * MT;

 

已知矩阵GN和GN的逆矩阵的乘积为单元矩阵。

inverse(GN)*GN = I

同时正交矩阵的transpose(GN)*GN = I

两边都乘以转换矩阵时

transpose(GN)*inverse(GN) * GN = inverse(GN)

transpose(GN) = inverse(GN)

 

所以

dot(T', N') = transpose(GN) * MT;

拆解后得:

dot(T', N') = transpose(G) * transpose(N) * M*T;

 

假设transpose(G) * M = I时

dot(N', T') = dot(N, T) = 0;

所以得出我们要求的

G = transpose(inverse(M))

 

这就是“模型矩阵左上角的逆矩阵的转置矩阵”的整体推导过程。

 

另外:法向量只是一个方向向量,不能表达空间中的特定位置。同时,法向量没有齐次坐标(顶点位置中的w分量)。这意味着,位移不应该影响到法向量。因此,如果我们打算把法向量乘以一个模型矩阵,我们就要从矩阵中移除位移部分,只选用模型矩阵左上角3×3的矩阵(注意,我们也可以把法向量的w分量设置为0,再乘以4×4矩阵;这同样可以移除位移)。对于法向量,我们只希望对它实施缩放和旋转变换。

 

最终的做法是:

Normal = mat3(transpose(inverse(model))) * aNormal;

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值