Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement flat shading in OpenGL without duplicate vertices?

I am trying to render 3D prisms in LWJGL OpenGL with flat shading. For example, I have a cube indexed as following:

enter image description here

I only have 8 vertices in the vertex buffer, which I have indexed as above. Is there any way to implement flat normal shading on the cube such as below? I don't want to rewrite my vertex and index buffers to include duplicate vertices if possible.

like image 225
Sibh Avatar asked Feb 02 '20 01:02

Sibh


1 Answers

If you don't need any other attributes (e.g. texture coordinates), then there is an option to create a cube mesh with face normal vectors, by 8 vertices only. Use the flat Interpolation qualifier for the normal vector.

Vertex shader:

flat out vec3 surfaceNormal;

Fragment sahder:

flat out vec3 surfaceNormal;

When the flat qualifier is used, then the output of the vertex shader will not be interpolated. The value given to the fragment shader is one of the attributes associated to one vertex of the primitive, the Provoking vertex.
For a GL_TRINANGLE primitive this is either the last or the first vertex. That can be chosen by glProvokingVertex.

Choose the first vertex:

glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);

For the order of the points of your cube mesh (image in the question)

  front      back

  1     3    7     5
   +---+      +---+
   |   |      |   |
   +---+      +---+
  0     2    6     4

you have to setup the following vertex coordinates and normal vectors:

//  x   y   z   nx, ny, nz
    -1, -1, -1,   0, -1,  0,  // 0, nv front
    -1, -1,  1,   0,  0,  1,  // 1, nv top
     1, -1, -1,   0,  0,  0,  // 2
     1, -1,  1,   1,  0,  0,  // 3, nv right
     1,  1, -1,   0,  1,  0,  // 4, nv back
     1,  1,  1,   0,  0,  0,  // 5
    -1,  1, -1,   0,  0, -1,  // 6, nv bottom
    -1,  1,  1,  -1,  0,  0,  // 7, nv left 

Define the indices in that way, that the vertices 7, 3, 0, 4, 6, 1 are the first vertex for both triangles of the left, right, front, back, bottom and top of the cube:

0, 2, 3,   0, 3, 1, // front
4, 6, 7,   4, 7, 5, // back
3, 2, 4,   3, 4, 5, // right
7, 6, 0,   7, 0, 1, // left
6, 4, 2,   6, 2, 0, // bottom 
1, 3, 5,   1, 5, 7  // top

Draw 12 triangle primitives. e.g:

glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);

like image 199
Rabbid76 Avatar answered Oct 03 '22 03:10

Rabbid76