在下图中,您将看到我当前的设置。我正在渲染一个带有高度图信息的球体。网格是围绕球体缠绕的正方形。光源直接位于摄像机位置。我目前遇到的问题是法线的计算。
从我发现的,在连续表面上得到法向量的一种方法是,对于每个顶点,找到与其相邻的所有顶点,在网格中(在我的情况下,我有6个相邻顶点)找到法线到他们正在形成的所有六个平面,然后将它们相加并正常化。
您可以看到以下代码。 不幸的是,对于地球上的某些地方来说,它似乎有效,但不是一切。还要注意看起来在纹理上对角线的奇怪阴影线。
任何想法可能导致这种行为?
编辑:该问题与最终正常计算中的adjecent平面的权重无关。
private Vector3f calcNormal(int x, int z)
{
if ( x<1 || x> RESOLUTION-2 || z<1 || z > RESOLUTION -2) {
Vector3f newNormal = new Vector3f();
newNormal = globe[x][z].sub(this.getTransform().GetPos()).normalize();
return newNormal;
}
Vector3f center = globe[x][z];
Vector3f up = globe[x][z-1];
Vector3f down = globe[x][z+1];
Vector3f left = globe[x-1][z];
Vector3f right = globe[x+1][z];
Vector3f rightUp = globe[x+1][z-1];
Vector3f leftDown = globe[x-1][z];
Vector3f dUp = new Vector3f(center).sub(up);
Vector3f dRightUp = new Vector3f(center).sub(rightUp);
Vector3f dRight = new Vector3f(center).sub(right);
Vector3f dDown = new Vector3f(center).sub(down);
Vector3f dLeft = new Vector3f(center).sub(left);
Vector3f dLeftDown = new Vector3f(center).sub(leftDown);
Vector3f normal = new Vector3f(dUp.cross(dRightUp)).
add(new Vector3f(dRightUp.cross(dRight))).
add(new Vector3f(dRight.cross(dDown))).
add(new Vector3f(dDown.cross(dLeftDown))).
add(new Vector3f(dLeftDown.cross(dLeft))).
add(new Vector3f(dLeft.cross(dUp)));
return normal.normalize();
}
答案 0 :(得分:0)
这可能不是您的代码的实际问题,但可能仍然很好知道:
这个简单的算法不会给你带来好的结果。您需要在每个相邻法线上使用一些加权因子,并将其考虑在内。#34;如何相邻&#34;一个三角形是你当前的顶点。例如,可以使用三角形的归一化入射角。 this presentation from Crytek中描述的问题非常好。
注意,由于你没有对相邻三角形的法线进行标准化,所以你已经这样做了,因为它们是由两个边向量所跨越的平行四边形的大小来缩放的。