正确地改变表面法线

red*_*ish 6 opengl 3d

根据OpenGL红皮书附录F,常规3D变换矩阵M可用于计算法向量上的动作:

normalTransformed = transpose(inverse(M)) * normal
Run Code Online (Sandbox Code Playgroud)

然而,虽然与变换的法线相关联的正交平面确实与变换的表面平行,但是可能发生变换的法向量本身指向与我期望的相反的方向,即"进入"表面而不是"走出表面.

如果我希望normalTransformed指向正确的方向(即,当它所附着的表面未被转换时指向的方向相同),我应该如何在数学上做到这一点?

假设我的曲面法线是(0,0,1),而我的变换是Z方向上的平移10.然后,变换矩阵M是:

1 0 0 0
0 1 0 0
0 0 1 10
0 0 0 1

转置(反向(M))然后是:

1 0 0 0
0 1 0 0
0 0 1 0
0 0 -10 1

应用于表面法线(0,0,1),即齐次坐标中的(0,0,1,1),这给出:

normalTransformed =(0,0,1,-9)

从齐次坐标返回:

(0,0,-1/9)

标准化为长度1:

(0,0,-1)

与原始法向量(0,0,1)相比,它指向相反方向.

Nic*_*las 19

应用于表面法线(0,0,1),即均匀坐标中的(0,0,1,1)

好的,停在那儿.

如果你要将表面法线视为齐次坐标,你可以使用作为W分量,而不是1.现在,你可能会很快意识到你不能除以零,但这也是你为什么不这样做的原因对法线进行同质数学运算.

法线不是一个位置; 这是一个方向.方向没有位置,因此翻译它们毫无意义.W = 0的同质位置代表无限远的"位置"(这就是为什么你不能将它们分开).无限远的位置与每个有限点无限远.

因此,无穷远处的位置是一个方向:无论你从哪个(有限)位置看,它都不会改变方向.

现在,如果你有一个4x4矩阵并且需要用它来变换法线,那么你只使用W = 0,因为它可以解决数学问题.它摆脱了矩阵的平移分量.应完全忽略变换后的W分量.

因此,在转换之后,你得到这个:

normalTransformed =(0,0,1,-9)

忽略W组件后,变为:

normalTransformed =(0,0,1)


你的法线更有可能实际上没有指向正确的方向.当然,在没有代码和数据的情况下,可以说更多,但数学运算假设输入是合法的.

另外,不要在着色器中执行反转/转置.在CPU上执行此操作,并将生成的矩阵传递给着色器.

  • @reddish:因为它是*方向*.均匀方向仅在W = 0时有效.如果W是其他任何东西,它就不再是一个方向; 这是一个职位. (2认同)