我有一堆网格体组成了一个地形。没有一个大网。它来自一个游戏,我正在为玩家制作一个计划战斗的工具。
网格包含的所有网格都是顶点和平均法线。无切线。
我可以很容易地创建切线和双切线,但是,它看起来很糟糕。像往常一样,它们需要平滑或平均在一起。我需要从小网格创建一个大网格来进行平滑。似乎白费了很多工作。
我的问题是,因为我已经有处于平滑/平均状态的法线,有没有办法使用它们来纠正切线?
我正在使用此方法在着色器中创建 TBN 矩阵。它有效,但是,开销很昂贵,因为我正在绘制数十万个 4 层,混合纹理,纹素。
更新
好吧......据我所知,不能为此使用正常值。 我昨天花了一整天的时间编写代码以在巨型网格上创建,然后将其转回其部分网格。 对于尼科·舍特勒:
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);
}
事实证明,有一种方法可以使用法线将切线和双切线与平均/平滑法线对齐。
这 2 条线迫使切线和双切线与法线成 90 度。 "格拉姆-施密特过程">
t = normalize(t-dot(n,t)*n);
b = normalize(b-dot(n,b)*n);