I am currently working on a simple game and I would like to my terrain to be flat shaded. My terrain currently looks like the following:
As you can see the colours blend toghether depending on the vertice colours.
I would love for my end product to resemble the following:
So I was wondering how can I achieve this? What are the steps to go from gouraud shading to flat shading?
Here is how I go about creating the vertices I give to my mesh:
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;
}