为什么使用模型视图矩阵的反转置转换法线?

问题描述 投票:41回答:5

我正在研究一些着色器,我需要改变法线。

我在几个教程中读到了变换法线的方法,你将它们与模型视图矩阵的逆的转置相乘。但我找不到为什么会这样解释,那背后的逻辑是什么?

opengl glsl game-engine game-physics
5个回答
26
投票

看看这个教程:

https://paroj.github.io/gltut/Illumination/Tut09%20Normal%20Transformation.html

您可以想象,当球体表面伸展(因此球体沿着一个轴或类似物体缩放)时,该表面的法线将全部“弯曲”为彼此。事实证明,您需要反转应用于法线的比例来实现此目的。这与使用反向转置矩阵进行变换相同。上面的链接显示了如何从中导出逆转置矩阵。

另请注意,当刻度均匀时,您可以简单地将原始矩阵作为普通矩阵传递。想象一下,沿着所有轴均匀地缩放相同的球体,表面不会拉伸或弯曲,法线也不会。


39
投票

它来自正常的定义。

假设您有正常的N和一个向量V,它是对象上与正常相同位置的切向量。然后根据定义N·V = 0

切线向量的运行方向与对象的表面方向相同。因此,如果表面是平面的,则切线是对象上两个可识别点之间的差异。因此,如果V = Q - R,其中QR是表面上的点,那么如果你通过B变换对象:

V' = BQ - BR
   = B(Q - R)
   = BV

通过考虑限制,相同的逻辑适用于非平面表面。

在这种情况下,假设您打算通过矩阵B转换模型。所以B将应用于几何。然后找出你需要为矩阵求解的法线要做什么,A这样:

(AN)·(BV) = 0

将其转换为行与列,以消除显式点积:

[tranpose(AN)](BV) = 0

将转置拉到外面,取消括号:

transpose(N)*transpose(A)*B*V = 0

因此,这是“正常的转置”[产品]“已知转换矩阵的转置”[产品]“我们正在解决的转换”[产品]“模型表面上的矢量”= 0

但我们首先说明transpose(N)*V = 0,因为那与说N·V = 0相同。因此,为了满足我们的约束,我们需要表达式的中间部分 - transpose(A)*B - 消失。

因此我们可以得出结论:

 transpose(A)*B = identity
 => transpose(A) = identity*inverse(B)
 => transpose(A) = inverse(B)
 => A = transpose(inverse(B))

26
投票

我最喜欢的证据是下面,其中N是法线,V是切线矢量。由于它们是垂直的,它们的点积为零。 M是任何3×3可逆变换(M-1 * M = 1)。 N'和V'是由M.转换的向量。

为了获得一些直觉,请考虑下面的剪切变换。

请注意,这不适用于切线向量。


1
投票

如果模型矩阵由平移,旋转和缩放组成,则无需进行逆移调来计算法线矩阵。简单地将法线除以平方尺度并乘以模型矩阵,我们就完成了。您可以将其扩展到任何具有垂直轴的矩阵,只需计算您正在使用的矩阵的每个轴的平方比例。

我在我的博客中写了详细信息:https://lxjk.github.io/2017/10/01/Stop-Using-Normal-Matrix.html


-2
投票

不明白为什么在与模型矩阵相乘之前不要将方向向量的第4个元素归零。无需反转或转置。将方向向量看作两点之间的差异。将两个点移动到模型的其余部分 - 它们仍然与模型处于相同的相对位置。获取两个点之间的差异以获得新方向,第四个元素取消为零。很便宜。

© www.soinside.com 2019 - 2024. All rights reserved.