johnsoncodehk 发表于 2021-11-16 11:19

为什么计算法线不用unity_ObjectToWorld,而用unity ...

公式编辑器用的不习惯,排版有点乱,见谅。
--------------------------------------------
因为,模型在进行左边变换的时候,可能包含缩放操作。
如果unity_ObjectToWorld,在当前模型计算时存在 不等比的缩放,那么法线方向将不再与切线方向垂直(图中右侧可以理解为,直接用unity_ObjectToWorld,可能导致的结果)。如图所示。


此时 要得到法线那么就要保证变换过后的法线 N' 与 变换过后的切线方向T’依然垂直。
由于N ·T = 0, 所以应满足N' ·T' = 0。
切线方向了来自于模型顶点的位置,所以假设T' = MT,M相当于 unity_ObjectToWorld。
那么设N'=GN;
则(GN) · (MT)=0 ;解出G即可。由于(GN) 和 (MT) 实际上都是列向量。则 可将 GN转置。得到


去括号,变为连续的矩阵乘法


N·T=N·T=0,则要满足上面的式子,需要


左右除M,然后 转置之后得到


即,法线变换矩阵是顶点变换矩阵的逆矩阵的转置。这就是上面的答案了。

闲鱼技术01 发表于 2021-11-16 11:20

公式编辑器用的不习惯,排版有点乱,见谅。
--------------------------------------------
因为,模型在进行左边变换的时候,可能包含缩放操作。
如果unity_ObjectToWorld,在当前模型计算时存在 不等比的缩放,那么法线方向将不再与切线方向垂直(图中右侧可以理解为,直接用unity_ObjectToWorld,可能导致的结果)。如图所示。


此时 要得到法线那么就要保证变换过后的法线 N' 与 变换过后的切线方向T’依然垂直。
由于N ·T = 0, 所以应满足N' ·T' = 0。
切线方向了来自于模型顶点的位置,所以假设T' = MT,M相当于 unity_ObjectToWorld。
那么设N'=GN;
则(GN) · (MT)=0 ;解出G即可。由于(GN) 和 (MT) 实际上都是列向量。则 可将 GN转置。得到


去括号,变为连续的矩阵乘法


N·T=N·T=0,则要满足上面的式子,需要


左右除M,然后 转置之后得到


即,法线变换矩阵是顶点变换矩阵的逆矩阵的转置。这就是上面的答案了。

Doris232 发表于 2021-11-16 11:28

单从结果上来看unityWorldToObject与unity_ObjectToWorld是互逆的,但是想transpose(unityWorldToObject) = unity_ObjectToWorld 只有一种可能就是unityWorldToObject是正交矩阵,但是既然是缩放矩阵(排除100,010,001因为无意义),都不是正交矩阵,所以transpose(unityWorldToObject) != unity_ObjectToWorld

johnsoncodehk 发表于 2021-11-16 11:36

法线的变换是乘以对应变换矩阵逆的转置 而在无缩放的情况下 矩阵(向量只需要和3×3的矩阵进行计算)逆的转置就是他本身 Unity shader入门精要里面也专门讨论这个
页: [1]
查看完整版本: 为什么计算法线不用unity_ObjectToWorld,而用unity ...