0
votes

Using OpenGL shaders, I want to render a cube and apply diffuse illumination. My cube consists of 8 vertices, and 12 triangles. I calculate the normal of each triangle by finding the cross product between two of the edges of the triangle. Then, the normal of each vertex is the weighted (by area) average of the triangles it touches. In the vertex shader, to compute the illumination of each vertex, I then calculate the cosine of the angle between the vertex's normal, and the light vector.

However, the problem with this is that whilst each face of my cube is flat, the illumination for each pixel on the face is calculated be interpolating between its four vertices. Given that each vertex has a different normal, the illumination for the face varies smoothly between each vertex, whereas in reality there should be a single illumination value for the entire face.

What should I be doing to resolve this? Or is it impossible to deal with this without adding additional vertices along the cube faces?

2

2 Answers

3
votes

You use the term "vertex" inconsistently, meaning one thing in one location but another elsewhere.

A "position" is exactly that: a location in space. A "vertex", when dealing with rendering, means the position, normal, texture coordinate, and whatever else is needed as input to the vertex shader. Your vertex shader takes a single vertex as input and outputs data for a single vertex.

A cube has 8 positions. But each of the 6 faces has a different normal. Since your vertices must have a position and a normal, if you want the vertices for each face to use the same normal value, you must replicate data.

The number of unique combinations of positions&normals (ie: the number of vertices) must be 24: 4 for each of the 6 faces. You will use the same position and normal values, but your vertex arrays must duplicate the data. So the first four vertices would use 4 different positions, but they would have the same normal value replicated 4 times. That would cover one face.

So you have to do that, for each face.

1
votes

The usual way to handle this issue is to duplicate your corner vertices, one for each distinct normal you need on a primitive containing that vertex. There isn’t a reasonable way to make an individual vertex have distinct normals per-primitive.