0
votes

In a THREE.js scene with a Geometry object containing a triangle mesh, I want to achieve smooth phong shading. This seems to require making sure the triangles are added with the correct orientation.

Here's a Code Pen showing the issue. The same surface is rendered twice, on the left with varying triangle orientations, and on the right with consistent triangle orientations:

enter image description here

In my real code, because of how I am generating the triangle geometry, it is hard to know what the correct orientation should be. How can I achieve smooth shading independent of the triangle orientation?

I am just using a simple phong material:

let material = new THREE.MeshPhongMaterial({
  color: new THREE.Color('#FFAA44'),
  side: THREE.DoubleSide,
  flatShading: false
});
1

1 Answers

0
votes

You're running into issues with the winding order of vertices.

Counter-clockwise:
  1
 / \
2———3

Clockwise:
  1
 / \
3———2

When you use counter-clockwise winding order, the geometry.computeVertexNormals() makes all normals point away in the direction the triangle is facing, let's call it "forward". However, when you use clockwise winding order, it makes the normals point away in the opposite direction, so they're pointing "backward".

The phong material you're using relies on these normals to give you smooth shading. When you flip-flop between forward- and backward-facing normals, the possibility for smooth shading goes out the window, and you get the checkered look you see in your example. Actually all meshes, by convention, have all triangles follow a uniform winding order. You could solve your unique problem by looking at your vertex positions, and swapping two if you find they're winding in a clockwise manner:

Since you're using something similar to a plane grid, you could use a simple if statement. Based on my diagram above, you could do:

if (v2.x > v3.x) {
    // Clockwise winding order! Must flip verts 2 & 3
}

It might vary which vertices you're comparing, based on how you're building them, but once all triangles are uniform, you can call computeVertexNormals();