代码之家  ›  专栏  ›  技术社区  ›  jaho

如何实现平滑的切线空间法线?

  •  5
  • jaho  · 技术社区  · 11 年前

    我正在尝试将凹凸贴图功能添加到我的应用程序中,但我得到了非常多方面的模型:

    enter image description here

    之所以发生这种情况,是因为我在计算每个面的切线、副法线和法线,而完全忽略了从模型文件中获得的法线。

    该计算目前使用三角形的两条边和纹理空间向量来获得切线和副法线,然后使用它们通过叉积来计算法线。一旦加载模型,所有这些都在CPU上完成,然后将值作为模型几何图形的一部分存储。

        vector1 = vertex2.coords - vertex1.coords;      
        vector2 = vertex3.coords - vertex1.coords;
    
        tuVector = vertex2.texcoords - vertex1.texcoords;
        tvVector = vertex3.texcoords - vertex1.texcoords;
    
        float den = 1.0f / (tuVector.x * tvVector.y - tuVector.y * tvVector.x);
    
        tangent.x = (tvVector.y * vector1.x - tvVector.x * vector2.x) * den;
        tangent.y = (tvVector.y * vector1.y - tvVector.x * vector2.y) * den;
        tangent.z = (tvVector.y * vector1.z - tvVector.x * vector2.z) * den;
    
        binormal.x = (tuVector.x * vector2.x - tuVector.y * vector1.x) * den;
        binormal.y = (tuVector.x * vector2.y - tuVector.y * vector1.y) * den;
        binormal.z = (tuVector.x * vector2.z - tuVector.y * vector1.z) * den;
    
        D3DXVec3Normalize(&tangent, &tangent);
        D3DXVec3Normalize(&binormal, &binormal);
    
        D3DXVec3Cross(&normal, &tangent, &binormal);    
        D3DXVec3Normalize(&normal, &normal);
    

    有没有一种方法可以在每个顶点的基础上计算这些值,也许是使用模型提供的法线,或者以某种方式平滑它们,使模型不会出现多面?

    1 回复  |  直到 11 年前
        1
  •  4
  •   Community CDub    7 年前

    对于光滑表面(无边),我这样做:

    1. 为每个顶点创建空间

      double N[3]; //normal
      int cnt;
      
    2. 逐顶点初始化

      N={0.0,0.0,0.0}
      cnt=0;
      
    3. 计算每面法线

      法线必须规格化长度=1.0!!! 添加此 Normal 面和增量中使用的所有顶点 cnt 到面中使用的所有顶点

    4. 逐顶点规格化

      N/=cnt; // N = average normal from all vertex - neighbour faces
      

      意识到 cnt=0 对于未使用的顶点(除以零)

    5. 每个顶点 N 包含所需的法线

      现在计算 T,B 的矢量 待定 矩阵(每个顶点)

    6. 输出图像平滑

      我的地球预览(包括大气散射、凹凸贴图等)是 here

    希望有帮助