为什么要通过模型视图矩阵的逆矩阵的转置来变换法线?

问题描述 投票:0回答:6

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

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

opengl glsl game-engine game-physics
6个回答
62
投票

它源自法线的定义。

假设您有法线

N
和向量
V
,即与法线位于对象上相同位置的切向量。那么根据定义
N·V = 0

切向量与物体表面的方向相同。因此,如果您的表面是平面,那么切线就是物体上两个可识别点之间的差值。因此,如果

V = Q - R
其中
Q
R
是表面上的点,那么如果通过
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))

47
投票

我最喜欢的证明如下,其中 N 是法线,V 是切向量。由于它们是垂直的,因此它们的点积为零。 M 是任何 3x3 可逆变换 (M-1 * M = I)。 N'和V'是M变换后的向量。

enter image description here

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

enter image description here

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


42
投票
看看这个教程:

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

您可以想象,当球体的表面拉伸(因此球体沿一个轴或类似的轴缩放)时,该表面的法线将全部朝彼此“弯曲”。事实证明,您需要反转应用于法线的比例才能实现此目的。这与使用

逆转置矩阵进行变换相同。上面的链接显示了如何从中导出转置矩阵。

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


4
投票
如果模型矩阵由平移、旋转和缩放组成,则不需要进行转置来计算法线矩阵。只需将法线除以平方尺度并乘以模型矩阵即可。您可以将其扩展到具有垂直轴的任何矩阵,只需计算您正在使用的矩阵的每个轴的平方比例即可。

我在博客中写了详细信息:

https://lxjk.github.io/2017/10/01/Stop-Using-Normal-Matrix.html


0
投票
transpose(N)*V = 0; //OK transpose(N)*invert(M)*M*V = 0; //OK (transpose(N)*invert(M))*(M*V) = 0; //OK (transpose(N)*invert(M))*S' = 0; //(1) OK transpose(N')*S' = 0; //(2) OK transpose(N') = transpose(N)*invert(M); **// Why??? Not OK**
    

-3
投票
不明白为什么在与模型矩阵相乘之前不将方向向量的第四个元素清零。不需要逆或转置。将方向向量视为两点之间的差异。将这两个点与模型的其余部分一起移动 - 它们与模型的相对位置仍然相同。取两点之间的差值以获得新方向,第四个元素抵消为零。便宜很多。

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