根据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上执行此操作,并将生成的矩阵传递给着色器.