我试图通过减少三角形数量来优化我的地形,同时保持尽可能多的细节。减少工作正常,我将顶点的数量减少了5,没有太多的视觉损失。这个新的非对称网格上的法线计算存在问题。
我有每个顶点的法线,这里是计算法线的片段:
private void calcNormal(Vector<Triangle_dt> triangles, Point_dt point) {
Vec3 normal = new Vec3(0, 0, 0);
for (Triangle_dt triangle : triangles) {
Vec3 a = getPos(triangle.p1());
Vec3 b = getPos(triangle.p2());
Vec3 c = getPos(triangle.p3());
Vec3 AB = b.subtract(a);
Vec3 AC = c.subtract(a);
normal = normal.add(AB.cross(AC));
}
setNormal(point, normal.getUnitVector());
}
其中三角形是连接到顶点(点)的三角形。我将所有三角形法线加在一起(不进行标准化以使最终向量按三角形区域加权),然后最终对最终结果进行标准化。
我相信计算是正确的,但结果中有令人讨厌的瑕疵(用方向灯照亮):
正如您可以看到顶点稀疏的不需要的线条。它是由于小点聚集在一起但远离下一组点而引起的(见下图)。怎么预防这个?这里的点渲染视图相同:
答案 0 :(得分:2)
感谢ybungalobill,我做了以下工作让它发挥作用:
从高度图计算法线
// Calculating normals from height map
public void calcNormals() {
Vec3 up = new Vec3(0, 1, 0);
float sizeFactor = 1.0f / (8.0f * cellSize);
normals = new Vec3[rows * cols];
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
Vec3 normal = up;
if (col > 0 && row > 0 && col < cols - 1 && row < rows - 1) {
float nw = getValue(row - 1, col - 1);
float n = getValue(row - 1, col);
float ne = getValue(row - 1, col + 1);
float e = getValue(row, col + 1);
float se = getValue(row + 1, col + 1);
float s = getValue(row + 1, col);
float sw = getValue(row + 1, col - 1);
float w = getValue(row, col - 1);
float dydx = ((ne + 2 * e + se) - (nw + 2 * w + sw)) * sizeFactor;
float dydz = ((sw + 2 * s + se) - (nw + 2 * n + ne)) * sizeFactor;
normal = new Vec3(-dydx, 1.0f, -dydz).getUnitVector();
}
normals[row * cols + col] = normal;
}
}
}
从法线创建图像
public static BufferedImage getNormalMap(Terrain terrain) {
Vec3[] normals = terrain.getNormals();
float[] pixels = new float[normals.length * 3];
for (int i = 0; i < normals.length; i++) {
Vec3 normal = normals[i];
float x = (1.0f + normal.x) * 0.5f;
float y = (1.0f + normal.y) * 0.5f;
float z = (1.0f + normal.z) * 0.5f;
pixels[i * 3] = x * MAX;
pixels[i * 3 + 1] = y * MAX;
pixels[i * 3 + 2] = z * MAX;
}
BufferedImage img = new BufferedImage(cols, rows, BufferedImage.TYPE_INT_RGB);
WritableRaster imgRaster = img.getRaster();
imgRaster.setPixels(0, 0, cols, rows, pixels);
return img;
}