美文网首页
OpenGL中法线矩阵的证明

OpenGL中法线矩阵的证明

作者: constantine丶 | 来源:发表于2019-12-16 22:45 被阅读0次

    首先如果不使用法线矩阵,那么你可能会这样处理法向量

    Normal = mat3(model) * aNormal;
    

    大多数情况下,这是没有问题的,比如你只用到了位移和旋转变换,但是如果你使用了放缩(scale)就可能出现问题。


    normalmat1.gif

    在上图中,我们看到了一个三角形,其中包含法线和切线向量。
    下图显示了当模型视图矩阵包含不均匀比例时发生的情况。


    normalmat2.gif
    例如三角形顶点的坐标为(0,10,0,1),(0,0,0,1) ,(10,0,0,1) 法向量为(1,1,0)
    放缩变换的矩阵为

    (1 0 0 0
    0 2 0 0
    0 0 1 0
    0 0 0 1) -> 顶点变为(0 , 20 , 0 , 1) (0,0,0,1) (10,0,0,1)
    对于法向量 就会变成 (1,2,0),所以这个法向量显然是错的嘛...

    于是OpenGL中对于法线的处理有这么一条语句

    Normal = mat3(transpose(inverse(model))) * aNormal;
    

    它的意思是 模型矩阵左上角的逆矩阵的转置矩阵,即法线矩阵
    对这个矩阵进行变换,
    (1 0 0 0
    0 2 0 0
    0 0 1 0
    0 0 0 1)
    ->
    (1 0 0 0
    0 1/2 0 0
    0 0 1 0
    0 0 0 1)
    那么这一次,法线会变成 (1,1/2,0)这个结果是正确的,非常神奇!

    补充一下线性代数的前置知识

    逆矩阵(Inverse Matrix): AB=BA=E,E为单位矩阵,那么B为A的逆矩阵
    转置矩阵(Transpose Matrix):把A矩阵的行与列的元素互换
    转置矩阵的运算性质参考

    image.png
    1、乘积
    用于矩阵相乘,表示为C=A * B,A的列数与B的行数必须相同,C也是矩阵,
    2、点积
    用于向量相乘,表示为C=A . B,A与B均为向量,

    法线矩阵的推导过程

    假设矩阵G是转换法线向量的正确矩阵。有:
    (符号的意思结合上图来看,转换后的T' 和 N‘ 的点乘应该为0)


    image.png

    点积可以转换为矩阵的乘机,即把前面的向量转置,因此:
    这里的N,T代表的向量,GN,MT的结果也为向量


    image.png
    image.png

    因此如果,我们设:


    image.png
    则:
    image.png
    所以,(I为单位矩阵,即 NT * I * T = 0):
    image.png

    证毕

    即使是对于着色器来说,逆矩阵也是一个开销比较大的运算,因此,只要可能就应该避免在着色器中进行逆矩阵运算,它们必须为你场景中的每个顶点都进行这样的处理。用作学习目这样做是可以的,但是对于一个对效率有要求的应用来说,在绘制之前你最好用CPU计算出法线矩阵,然后通过uniform把值传递给着色器(像模型矩阵一样)。

    参考资料:
    http://www.lighthouse3d.com/tutorials/glsl-12-tutorial/the-normal-matrix/
    https://learnopengl-cn.github.io/02%20Lighting/02%20Basic%20Lighting/

    相关文章

      网友评论

          本文标题:OpenGL中法线矩阵的证明

          本文链接:https://www.haomeiwen.com/subject/xvcjnctx.html