Home Forums GAMES在线课程(现代计算机图形学入门)讨论区 作业3 bump mapping中TBN的t 公式怎么推导的

Viewing 3 reply threads
  • Author
    Posts
    • #6827 Score: 0
      vincent
      Participant

      Let n = normal = (x,y,z)
      Vector t = (x*y/sqrt(x*x+z*z), sqrt(x*x+z*z), z*y/sqrt(x*x+z*z))

      其中normal是世界空间的法线吧?怎么直接计算出切线方向的呢?

    • #6854 Score: 1
      Panneiria
      Participant
      1 pt

      这里说是计算切线,其实更准确一点是在找一条切线然后跟n和它俩的叉乘构成一个Orthonormal basis。
      其实n定义了一个三维空间中的平面P,而P上的任意一条向量都与模型上的与法线n相对应的这一点相切。
      代码里这个t,我感觉其实是找了一个挺巧妙的向量。
      你可以这么想,n是由它在x-z平面上的投影和它的y-component构成的。你把这个投影旋转到与y轴重合,n的y-component就到了一个平行于x-z平面的平面上,那么它的x,z坐标,就是t的x,z坐标。然后很显然,t的y坐标就是n在x-z平面上的投影的模长。
      不过,代码框架里的这段应该是有点问题的,n跟t并不垂直。解出来的t的x,z坐标应该是-x*y/sqrt(x*x+z*z),-z*y/sqrt(x*x+z*z)。或者x,z是对的,那y就要变成负的。总之是有点问题。
      然后代码里选定了n为z轴,t为x轴,b为y轴(轴的选定满足了右手坐标系三轴的叉乘法则),所以才能看到TBN = [t b n]这段代码。这个TBN矩阵是用来把下面计算出来的perturbed normal从本地坐标系转化到世界坐标系的。

      然后我也有个问题想请教一下,rasterizer的代码里这段:
      Eigen::Matrix4f inv_trans = (view * model).inverse().transpose();
      应该是用来把模型的法线从模型空间转化到世界空间的,但是难道不是只要inverse就够了吗,为什么还要transpose一下?

      This post has received 1 vote up.
      • #6855 Score: 0
        vincent
        Participant

        非常感谢你的解释,至于你的问题,我也不清楚。

        • #6857 Score: 0
          Panneiria
          Participant
          1 pt

          我刚才突然开窍了哈哈,你试一下让inv_trans = view * model,效果是一样的。原理简单说的话,是我们在变换模型的缩放、位置和旋转的时候,只有旋转会真的影响到法线,因为法线是方向向量,w是0。
          解释清楚一点,就是我们想要view space里模型的法线在世界坐标中表示的方向。那模型经历了一系列的缩放、平移和旋转,而其中只有旋转会影响法线。当我们用view * model去乘法线的时候,法线就经历了与模型一样的旋转(缩放其实也会生效,但是反正要归一化所以无所谓),而平移是无效的。于是我们就有了法线在世界坐标中表示的方向。
          那原代码中的inv_trans其实我觉得有点怪怪的,虽然效果一样。如果我们不考虑平移,(view * model).inverse()这个矩阵会对法线进行与模型相反的缩放效果和相反的旋转效果,而inv_trans会对法线进行与模型相反的缩放效果(缩放效果在对角线上所以转置不影响)和与模型相同的旋转效果(旋转矩阵的逆与转置相同),那么我们也就得到了和对法线施加view * model这个矩阵一样的有效效果。

          • #9220 Score: 0
            shadowlr
            Participant

            不是喔 非一致缩放也会影响到法线

      • #6968 Score: 2
        Jamie Guan
        Participant

        谢谢你的推导!我这里画了一张图也许能够帮助更好地解释

        This post has received 2 votes up.
        Attachments:
        You must be logged in to view attached files.
      • #9241 Score: 0
        LunaJohn
        Participant

        把切线从模型空间转换到世界空间是不能直接用model矩阵转换的,只要model矩阵是各个分量不等拉伸的矩阵,变换之后原来的法线和原来的面就不会垂直了,这个你可以在2维空间画一下x*1,y*2的变换,还是很明显的。
        要得到正确的变换,就是要保证前后顶点切线和法线点乘为零,即TA cross NA = 0,TB(变换后的切线)=M1*TA,M1就是变换矩阵。那么可以得到 (M1*TA)^ * G*NA = 0(前面取转置默认3*1转为1*3),G就是法线变换矩阵,那么可以得到TA^(MA^ * G)N=0,那么我们可以知道当G为MA的逆转置矩阵时等式成立。

        ps:因为有些库帮我们处理了一些细节,3*1 * 3*3的计算是可以被当作1*3 * 3*3的,所以把矩阵 * 向量(m * v) 转化成 向量 * 矩阵(v * m) 相当于对矩阵transpose(v^ * m^)。

    • #6933 Score: 1
      zzb
      Participant
      13 pts

      关于inverse transpose的问题,可以参考博客:
      https://blog.csdn.net/chenhittler/article/details/51348209

      This post has received 1 vote up.
    • #8974 Score: 0
      yxsxy
      Participant

      感谢大佬的解释

Viewing 3 reply threads
  • You must be logged in to reply to this topic.