How to calculate Tangent and Binormal?

后端 未结 3 1572
悲&欢浪女
悲&欢浪女 2020-11-28 03:45

Talking about bump mapping, specular highlight and these kind of things in OpenGL Shading Language (GLSL)

I have:

  • An array of vertices (e.g. {0.2,0.5,0
3条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-11-28 04:11

    Generally, you have 2 ways of generating the TBN matrix: off-line and on-line.

    • On-line = right in the fragment shader using derivative instructions. Those derivations give you a flat TBN basis for each point of a polygon. In order to get a smooth one we have to re-orthogonalize it based on a given (smooth) vertex normal. This procedure is even more heavy on GPU than initial TBN extraction.

      // compute derivations of the world position
      vec3 p_dx = dFdx(pw_i);
      vec3 p_dy = dFdy(pw_i);
      // compute derivations of the texture coordinate
      vec2 tc_dx = dFdx(tc_i);
      vec2 tc_dy = dFdy(tc_i);
      // compute initial tangent and bi-tangent
      vec3 t = normalize( tc_dy.y * p_dx - tc_dx.y * p_dy );
      vec3 b = normalize( tc_dy.x * p_dx - tc_dx.x * p_dy ); // sign inversion
      // get new tangent from a given mesh normal
      vec3 n = normalize(n_obj_i);
      vec3 x = cross(n, t);
      t = cross(x, n);
      t = normalize(t);
      // get updated bi-tangent
      x = cross(b, n);
      b = cross(n, x);
      b = normalize(b);
      mat3 tbn = mat3(t, b, n);
      
    • Off-line = prepare tangent as a vertex attribute. This is more difficult to get because it will not just add another vertex attrib but also will require to re-compose all other attributes. Moreover, it will not 100% give you a better performance as you'll get an additional cost of storing/passing/animating(!) vector3 vertex attribute.

    The math is described in many places (google it), including the @datenwolf post.

    The problem here is that 2 vertices may have the same normal and texture coordinate but different tangents. That means you can not just add a vertex attribute to a vertex, you'll need to split the vertex into 2 and specify different tangents for the clones.

    The best way to get unique tangent (and other attribs) per vertex is to do it as early as possible = in the exporter. There on the stage of sorting pure vertices by attributes you'll just need to add the tangent vector to the sorting key.

    As a radical solution to the problem consider using quaternions. A single quaternion (vec4) can successfully represent tangential space of a pre-defined handiness. It's easy to keep orthonormal (including passing to the fragment shader), store and extract normal if needed. More info on the KRI wiki.

提交回复
热议问题