3
\$\begingroup\$

I'm generating a relatively low-poly terrain for my game using the code below:

for (int z = 0; z < VERTEX_COUNT; z++) {
    for (int x = 0; x < VERTEX_COUNT; x++) {
        final float posX = x / ((float) VERTEX_COUNT - 1) * SIZE;
        final float height = generateHeight(x, z);
        final float posY = height;
        final float posZ = z / ((float) VERTEX_COUNT - 1) * SIZE;
        final Vector3 nor = getNormals(x, z);
        final float norX = nor.x;
        final float norY = nor.y;
        final float norZ = nor.z;
        final float texU = x / ((float) VERTEX_COUNT - 1);
        final float texV = z / ((float) VERTEX_COUNT - 1);

        // Create vertex
    }
}

for (int z = 0; z < VERTEX_COUNT - 1; z++) {
    for (int x = 0; x < VERTEX_COUNT - 1; x++) {
        final int topLeft = (z * VERTEX_COUNT) + x;
        final int topRight = topLeft + 1;
        final int bottomLeft = ((z + 1) * VERTEX_COUNT) + x;
        final int bottomRight = bottomLeft + 1;

        //Triangle 1: topLeft - bottomLeft - topRight
        //Triangle 2: topRight - bottomLeft - mottomRight
    }
}

private Vector3 getNormals(final int x, final int z) {
    final float heightL = generateHeight(x - 1, z);
    final float heightR = generateHeight(x + 1, z);
    final float heightD = generateHeight(x, z - 1);
    final float heightU = generateHeight(x, z + 1);
    return new Vector3(heightL - heightR, 2f, heightD - heightU).nor();
}

This works perfectly fine and generates a smooth terrain mesh. The problem is I want this mesh to use flat shading; i.e. I don't want vertices to be shared between triangles. But I don't know how I would duplicate the vertices and find the appropriate indices to properly index the mesh. Any help?

Here's in image from google in case it wasn't clear (left shading is what I want, right is what I have): example


P.S. I found this code for the Unity scripting language:

Vector3[] oldVerts = mesh.vertices;
int[] triangles = mesh.triangles;
Vector3[] vertices = new Vector3[triangles.Length];
for (int i = 0; i < triangles.Length; i++) {
    vertices[i] = oldVerts[triangles[i]];
    triangles[i] = i;
}
mesh.vertices = vertices;
mesh.triangles = triangles;

Perhaps this is the solution I'm looking for? If so, how can I translate this code to using float[] instead of Vector3[] array for my vertices? And what is the triangles array, the indices?

\$\endgroup\$
2
\$\begingroup\$

This can be achieved in 2 ways.

The first is very simple, and is how ThinMatrix did it in his game. When you pass the normal from the vertex shader to the fragment shader, apply the flat attribute to it:

flat in vec3 normal;

The second way is harder and uses more resources, but it's more flexible. You basically have to insert every triangle separately. Your VBO should look something like this:

0, 0.5, 0,  // pos1  }
0, 0.6, 1,  // pos2  }  first triangle
1, 0.7, 0,  // pos3  }

1, 0.7, 0,  // pos 4 }
0, 0.6, 1,  // pos 5 }  second triangle
1, 0.7, 1   // pos 6 }

You don't need an index buffer if you do this, you can use glDrawArrays.

\$\endgroup\$
  • 2
    \$\begingroup\$ What does the flat qualifier do? Disable interpolation? And what GLSL version do I need to use flat? \$\endgroup\$ – Charanor Apr 30 '17 at 13:40
  • \$\begingroup\$ I tried using the flat qualifier, but it doesn't seem to have worked. I used it like this flat varying vec3 v_normal; in my fragment shader. When it didn't work I also tried applying it in my vertex shader like this flat varying vec3 v_normal; with no results. Also, it seems like I have to write #extension GL_EXT_gpu_shader4 : require for flat to work in the first place. What's up with that? \$\endgroup\$ – Charanor Apr 30 '17 at 14:26
  • \$\begingroup\$ @Charanor 1.) the varying qualifier is deprecated, use in and out 2.) You have to put it before both the in and out statement and you need to have at least glsl version 150. \$\endgroup\$ – Bálint Apr 30 '17 at 15:57
  • \$\begingroup\$ I was just going to post an update when you commented! I changed the version to 330 and it still doesn't work. Also changed varying to in or out as well with no result. \$\endgroup\$ – Charanor Apr 30 '17 at 15:59
  • \$\begingroup\$ @Charanor If you're sure you have flat out vec3 v_normal and flat in vec3 v_normal in the vertex and fragment shader in this order, than there's probably a compatibility issue somewhere, try checking which version of glsl your GPU supports. \$\endgroup\$ – Bálint Apr 30 '17 at 16:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.