使用现有法线平滑切线。 OpenGL Lighting

时间:2017-03-20 01:15:45

标签: opengl math graphics

我有一堆构成地形的网格物体。不是一个大网格。这是来自游戏,我正在为玩家制定计划战斗的工具。

包含的所有网格都是顶点和平均法线。没有切线。

我可以很容易地创建切线和Bi-Tangents但是看起来很糟糕。像往常一样,它们需要被平滑或平均在一起。我需要从小的网格创建一个大网格来做平滑。好像很多工作都没有。

我的问题是,因为我已经处于平滑/平均状态的法线,有没有办法用它们来校正切线?

我使用This Method在着色器中创建了TBN矩阵。它可以工作但是,由于我正在绘制成千上万的4层,混合纹理,纹素混合,所以头顶很昂贵。

更新

好的......我不能告诉你使用正常的... 我昨天花了一整天的时间编写代码来创建巨型网格,然后将其转回到其网格中。 对于Nico Shhertler:

for(int i = 0; i < getVerts().length; i += 3) {
     Vector3f v0 = getVerts()[i].getVectorXYZ();
     Vector3f v1 = getVerts()[i + 1].getVectorXYZ();
     Vector3f v2 = getVerts()[i + 2].getVectorXYZ();

     Vector2f uv0 = getVerts()[i].getVectorUV();
     Vector2f uv1 = getVerts()[i + 1].getVectorUV();
     Vector2f uv2 = getVerts()[i + 2].getVectorUV();

     Vector3f n = getVerts()[i].getVectorNXYZ();

     Vector3f deltaPos1 = new Vector3f();
     Vector3f.sub(v1, v0, deltaPos1);
     Vector3f deltaPos2 = new Vector3f();
     Vector3f.sub(v2, v0, deltaPos2);

     float deltaUv1 = uv1.getY() - uv0.getY();
     float deltaUv2 = uv2.getY() - uv0.getY();

     // Tangent
     float tx = (deltaPos1.getX() * deltaUv2) - (deltaPos2.getX() * deltaUv1);
     float ty = (deltaPos1.getY() * deltaUv2) - (deltaPos2.getY() * deltaUv1);
     float tz = (deltaPos1.getZ() * deltaUv2) - (deltaPos2.getZ() * deltaUv1);
     Vector3f t = new Vector3f(tx, ty, tz);

     // Bitangent
     Vector3f b = new Vector3f();
     Vector3f.cross(n, t, b);

     // Final tangent
     Vector3f smoothTangent = new Vector3f();
     Vector3f.cross(b, n, smoothTangent);
     smoothTangent.normalise();

                   // These are where I store all the vertex data, so it's one tangent per vertex.
     getVerts()[i].setTXYZ(smoothTangent);
     getVerts()[i + 1].setTXYZ(smoothTangent);
     getVerts()[i + 2].setTXYZ(smoothTangent);
  }

1 个答案:

答案 0 :(得分:0)

事实证明,有一种方法可以使用法线将切线和比特点与平均值/平滑法线对齐。

这两条线使Tangent和BiTangent与法线成90度。 &#34; Gram-Schmidt过程&#34;

t = normalize(t-dot(n,t)*n);
b = normalize(b-dot(n,b)*n);