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

use*_*942 46 opengl glsl game-engine game-physics

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

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

Tom*_*mmy 43

它来自正常的定义.

假设你有一个法线,N和一个矢量,V一个与正常物体在同一位置上相同位置的切向量.然后根据定义N·V = 0.

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

V' = BQ - BR
   = B(Q - R)
   = BV
Run Code Online (Sandbox Code Playgroud)

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

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

(AN)·(BV) = 0
Run Code Online (Sandbox Code Playgroud)

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

[tranpose(AN)](BV) = 0
Run Code Online (Sandbox Code Playgroud)

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

transpose(N)*transpose(A)*B*V = 0
Run Code Online (Sandbox Code Playgroud)

因此,这是"正常的转置"[产品]"已知转换矩阵的转置"[产品]"我们正在解决的转换"[产品]"模型表面上的矢量"= 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))
Run Code Online (Sandbox Code Playgroud)


Inv*_*lid 31

看看这个教程:

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

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

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


wco*_*ran 28

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

在此输入图像描述

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

在此输入图像描述

请注意,这并不能适用于切向量.

  • 最后一个输错了.应该说$(M ^ -TN)^ T MV = 0 $(在前两个矩阵的产生周围缺少转置). (2认同)