我正在尝试在 Java 中为我的 LWJGL 引擎添加照明。我使用地球的高度图来渲染地形,我想添加一个太阳/光源,但出于某种原因,可能是因为我搞砸了一些东西,照明无法正常工作。
这是地图的图像,我目前删除了大海,因此照明更清晰。(它是 imgur,因为它说我需要 10 个声望才能发布图像)
http://imgur.com/A0e4gIi
黄色的东西是光源。如您所见,两侧出现两条“阴影”线,我不知道为什么。我的猜测是法线不正确。
这是靠近瓷砖的另一张图像,我使用 2 个三角形在高度图上渲染一个像素。
http://imgur.com/v3VSnBP
您可以看到其中一个三角形确实“正确”渲染,但另一个没有,它们都是相同的灰色/绿色。
加载高度图并创建tiles[][]和normal[][]的代码:
public void createMap(File heightmap) {
try {
BufferedImage image = ImageIO.read(heightmap);
tiles = new float[image.getWidth()][image.getHeight()];
normals = new Vector3f[image.getWidth()][image.getHeight()];
int rgb;
for(int x = 0; x < image.getWidth(); x++) {
for(int y = 0; y < image.getHeight(); y++) {
rgb = image.getRGB(x, y);
tiles[x][y] = (rgb >> 16) & 0xff;
}
}
} catch(Exception e) {
e.printStackTrace();
}
for(int x = 0; x < tiles.length - 1; x++) {
for(int z = 0; z < tiles[x].length - 1; z++) {
try {
Vector3f p1 = new Vector3f(x, tiles[x][z] * MODIFIER, z);
Vector3f p2 = new Vector3f(x, tiles[x][z+1] * MODIFIER, z+1);
Vector3f p3 = new Vector3f(x+1, tiles[x+1][z] * MODIFIER, z);
normals[x][z] = UtilMath.getNormal(p1, p2, p3);
} catch(Exception e) { e.printStackTrace(); }
try {
Vector3f p1 = new Vector3f(x+1, tiles[x+1][z+1] * MODIFIER, z+1);
Vector3f p2 = new Vector3f(x, tiles[x][z+1] * MODIFIER, z+1);
Vector3f p3 = new Vector3f(x+1, tiles[x+1][z] * MODIFIER, z);
normals[x+1][z+1] = UtilMath.getNormal(p1, p2, p3);
} catch(Exception e) { e.printStackTrace(); }
}
}
}
创建显示列表以呈现地图的方法:
public void createDisplayList() {
Random rand = new Random();
int mapDisplayList = glGenLists(1);
glNewList(mapDisplayList, GL_COMPILE);
glPushMatrix();
{
for(int x = 0; x < tiles.length - 1; x++) {
for(int z = 0; z < tiles[x].length - 1; z++) {
glColor3f(0, 0.75f, 0);
try {
glBegin(GL_TRIANGLES);
glNormal3f(normals[x][z].x, normals[x][z].y, normals[x][z].z);
glVertex3f(x, tiles[x][z] * MODIFIER, z);
glVertex3f(x, tiles[x][z+1] * MODIFIER, z+1);
glVertex3f(x+1, tiles[x+1][z] * MODIFIER, z);
glEnd();
} catch(Exception e) { e.printStackTrace(); }
try {
glBegin(GL_TRIANGLES);
glNormal3f(normals[x+1][z+1].x, normals[x+1][z+1].y, normals[x+1][z+1].z);
glVertex3f(x+1, tiles[x+1][z+1] * MODIFIER, z+1);
glVertex3f(x, tiles[x][z+1] * MODIFIER, z+1);
glVertex3f(x+1, tiles[x+1][z] * MODIFIER, z);
glEnd();
} catch(Exception e) { e.printStackTrace(); }
}
}
}
glPopMatrix();
glEndList();
}
最后,我用来计算法线的方法:
public static Vector3f getNormal(Vector3f p1, Vector3f p2, Vector3f p3) {
try {
Vector3f normal = new Vector3f();
Vector3f calU = new Vector3f(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
Vector3f calV = new Vector3f(p3.x - p1.x, p3.y - p1.y, p3.z - p1.z);
normal.setX(calU.y*calV.z - calU.z-calV.y);
normal.setY(calU.z*calV.x - calU.x-calV.z);
normal.setZ(calU.x*calV.y - calU.y-calV.x);
return (Vector3f) normal.normalise();
} catch(Exception e) {
e.printStackTrace();
}
return null;
}
我知道我可能对法线犯了一个错误。
我希望你们中的任何人都知道我做错了什么以及如何解决这两个问题。