我目前正在制作一款简单的游戏,我希望我的地形是平面阴影。我的地形目前如下所示:
正如您所看到的,颜色根据顶点颜色混合在一起。
我希望我的最终产品类似于以下内容:
所以我想知道如何实现这一目标?从gouraud阴影到平面阴影的步骤是什么?
以下是我如何创建我给网格的顶点:
public TerrainChunk() {
buildHeightmap();
buildIndices();
buildVertices();
calcNormals(indices, vertices);
}
public void buildHeightmap() {...}
private void buildIndices() {
int idx = 0;
short pitch = (short) (width + 1);
short i1 = 0;
short i2 = 1;
short i3 = (short) (1 + pitch);
short i4 = pitch;
short row = 0;
for (int z = 0; z < height; z++) {
for (int x = 0; x < width; x++) {
indices[idx++] = i1;
indices[idx++] = i2;
indices[idx++] = i3;
indices[idx++] = i3;
indices[idx++] = i4;
indices[idx++] = i1;
i1++;
i2++;
i3++;
i4++;
}
row += pitch;
i1 = row;
i2 = (short) (row + 1);
i3 = (short) (i2 + pitch);
i4 = (short) (row + pitch);
}
}
public void buildVertices() {
int heightPitch = height + 1;
int widthPitch = width + 1;
int idx = 0;
for (int x = 0; x < widthPitch; x++) {
for (int z = 0; z < heightPitch; z++) {
// POSITION
vertices[idx++] = scale * x;
vertices[idx++] = (float)Math.pow(1 + chunkDepths[x][z], strength));
vertices[idx++] = scale * z;
// NORMAL, skip these for now
idx += 3;
// COLOR
vertices[idx++] = getColor(;
// TEXTURE
vertices[idx++] = (x / (float) width);
vertices[idx++] = (z / (float) height);
}
}
}
/*
* Calculates the normals
*/
private void calcNormals(short[] indices, float[] verts) {
for (int i = 0; i < indices.length; i += 3) {
int i1 = getPositionStart(indices[i]);
int i2 = getPositionStart(indices[i + 1]);
int i3 = getPositionStart(indices[i + 2]);
// p1
float x1 = verts[i1];
float y1 = verts[i1 + 1];
float z1 = verts[i1 + 2];
// p2
float x2 = verts[i2];
float y2 = verts[i2 + 1];
float z2 = verts[i2 + 2];
// p3
float x3 = verts[i3];
float y3 = verts[i3 + 1];
float z3 = verts[i3 + 2];
// u = p3 - p1
float ux = x3 - x1;
float uy = y3 - y1;
float uz = z3 - z1;
// v = p2 - p1
float vx = x2 - x1;
float vy = y2 - y1;
float vz = z2 - z1;
// n = cross(v, u)
float nx = ((vy * uz) - (vz * uy));
float ny = ((vz * ux) - (vx * uz));
float nz = ((vx * uy) - (vy * ux));
// normalize(n)
float num2 = ((nx * nx) + (ny * ny)) + (nz * nz);
float num = 1f / (float) Math.sqrt(num2);
nx *= num;
ny *= num;
nz *= num;
addNormal(indices[i], verts, nx,ny, nz);
addNormal(indices[i + 1], verts, nx, ny, nz);
addNormal(indices[i + 2], verts, nx, ny, nz);
}
for (int i = 0; i < (verts.length / VERTEX_SIZE); i++) {
normalizeNormal(i, verts);
}
}
// Adds the provided value to the normal
private void addNormal(int vertIndex, float[] verts, float x, float y,
float z) {
int i = getNormalStart(vertIndex);
float rx = (float) ((x * Math.cos(180)) - (y * Math.sin(180)));
float ry = (float) ((x * Math.sin(180)) + (y * Math.cos(180)));
x = rx;
y = ry;
verts[i] += x;
verts[i + 1] += y;
verts[i + 2] += z;
}
/*
* Normalizes normals
*/
private void normalizeNormal(int vertIndex, float[] verts) {
int i = getNormalStart(vertIndex);
float x = verts[i];
float y = verts[i+1];
float z = verts[i+2];
float num2 = ((x * x) + (z * z)) + (y * y);
float num = (float) Math.sqrt(num2);
x *= num;
y *= num;
z *= num;
verts[i] = x;
verts[i + 1] = y;
verts[i + 2] = z;
}
// Gets the index of the first float of a normal for a specific vertex
private int getNormalStart(int vertIndex) {
return vertIndex * VERTEX_SIZE + 3;
}
// Gets the index of the first float of a specific vertex
private int getPositionStart(int vertIndex) {
return vertIndex * VERTEX_SIZE;
}
答案 0 :(得分:1)
最后,我改变了完全构建Mesh的方式。现在我用三角形构建网格。现在看来是这样的:。 它还不完美,因为没有对角色,但我对整体外观感到满意。
我是这样做的。 我创建了一个新类来保存我的变量
private Vector3 corner1;
private Vector3 corner2;
private Vector3 corner3;
private Vector3 corner4;
private Vector3 leftNormal;
private Vector3 rightNormal;
private Color color1;
private Color color2;
private Color color3;
private Color color4;
private Vector2 texturePos;
并像这样绘制它们:
// left triangle
VertexInfo v1 = new VertexInfo();
VertexInfo v2 = new VertexInfo();
VertexInfo v3 = new VertexInfo();
// right triangle
VertexInfo v4 = new VertexInfo();
VertexInfo v5 = new VertexInfo();
VertexInfo v6 = new VertexInfo();
v1.setPos(cell.getCorner1()).setNor(cell.getLeftNormal()).setCol(cell.getColor1()).setUV(cell.getTexturePos());
v2.setPos(cell.getCorner4()).setNor(cell.getLeftNormal()).setCol(cell.getColor1()).setUV(cell.getTexturePos());
v3.setPos(cell.getCorner2()).setNor(cell.getLeftNormal()).setCol(cell.getColor1()).setUV(cell.getTexturePos());
v4.setPos(cell.getCorner3()).setNor(cell.getRightNormal()).setCol(cell.getColor3()).setUV(cell.getTexturePos());
v5.setPos(cell.getCorner2()).setNor(cell.getRightNormal()).setCol(cell.getColor3()).setUV(cell.getTexturePos());
v6.setPos(cell.getCorner4()).setNor(cell.getRightNormal()).setCol(cell.getColor3()).setUV(cell.getTexturePos());
meshBuilder.triangle(v1, v2, v3);
meshBuilder.triangle(v4, v5, v6);
我计算三角形的面法线如下:
private Vector3 calcNormal(Vector3 p1, Vector3 p2, Vector3 p3) {
// u = p3 - p1
float ux = p3.x - p1.x;
float uy = p3.y - p1.y;
float uz = p3.z - p1.z;
// v = p2 - p1
float vx = p2.x - p1.x;
float vy = p2.y - p1.y;
float vz = p2.z - p1.z;
// n = cross(v, u)
float nx = ((vy * uz) - (vz * uy));
float ny = ((vz * ux) - (vx * uz));
float nz = ((vx * uy) - (vy * ux));
// // normalize(n)
float num2 = ((nx * nx) + (ny * ny)) + (nz * nz);
float num = 1f / (float) Math.sqrt(num2);
nx *= num;
ny *= num;
nz *= num;
return new Vector3(nx, ny, nz);
}