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

jah*_*aho 5 c++ math directx 3d hlsl

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

在此处输入图片说明

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

计算目前使用三角形的两条边和纹理空间向量得到切线和副法线,然后通过叉积计算法线。模型加载后,这一切都在 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);
Run Code Online (Sandbox Code Playgroud)

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

Spe*_*tre 5

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

  1. 为每个顶点创建空间

    double N[3]; //normal
    int cnt;
    
    Run Code Online (Sandbox Code Playgroud)
  2. 每个顶点初始化

    N={0.0,0.0,0.0}
    cnt=0;
    
    Run Code Online (Sandbox Code Playgroud)
  3. 计算每个面的法线

    正常必须标准化 length=1.0 !!! 将其添加Normal到面中使用的所有顶点并增量cnt到面中使用的所有顶点

  4. 每个顶点标准化

    N/=cnt; // N = average normal from all vertex - neighbour faces
    
    Run Code Online (Sandbox Code Playgroud)

    注意cnt=0未使用的顶点(除以零)

  5. 每个顶点N包含您想要的法线

    现在像现在一样计算TBNT,B矩阵(每个顶点)的向量

  6. 输出图像平滑

    我的地球预览(包括大气散射、凹凸贴图等...)在这里

希望能帮助到你