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

Viewing 1 reply thread
  • 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: 0
      Panneiria
      Participant

      这里说是计算切线,其实更准确一点是在找一条切线然后跟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一下?

      • #6855 Score: 0
        vincent
        Participant

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

        • #6857 Score: 0
          Panneiria
          Participant

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

Viewing 1 reply thread
  • You must be logged in to reply to this topic.