Cone You Assign Normals to a Cone?
When making a simple 3D model, normals get assigned to each vertex so that lighting can be properly calculated. The normal of a vertex is just the (normalized) average of the normals (perpendicular outward-pointing vectors) of the faces that it’s a part of. To get the lighting for each pixel, the graphics engine interpolates the vertex normals of each vertex in the triangle that it’s part of.
For spheres, toruses, and other blob-like objects, this works just fine.
For un-tessellated polyhedra, though, it leads to an unwanted blob-like appearance despite the low number of polygons. This can be fixed by using face normals instead of vertex normals, resulting in the intended flat-looking faces. This is typically accomplished by splitting the edges so that each vertex is part of only one face.
For cylinders, a mix of both vertex normals and face normals is needed (due to flat caps but a round side), and splitting just the cap edges works.
But then we have cones. The base is easy enough. Just split all the edges around it. But the side (the actual cone-shaped part) is an anomaly. In all the shapes we talked about so far, the only areas with split normals are entire edges, which can be split. However, the cone has a vertex with split normals (the apex), and we can’t split vertices without splitting the neighboring edges. We also can’t just leave the apex unsplit.
If we have access to custom shaders, like any normal 3D graphics engine would have in 2024, we can fix this problem easily by customizing the normals in the shader program. Specifically, we add special code to set a vertex’s normal to \(\langle 0, 0, 0\rangle\) if it’s the apex. The fragment shader then, as usual, normalizes the normals after interpolation. (At this point, I will stop showing the face normals. I will also stop showing the apex normal because it’s weird, and you should experience the full glory of the spike that is the apex.)
We can also just use a normal map to transform the interpolated normals to the correct ones. Any normal 3D graphics engine in 2024 would at least let you set a normal map.
Unfortunately, it seems like graphics engines can’t agree on exactly how normal maps work, as this looked fine in Blender, but has slight seams here. But maybe that’s a topic for another post.
But what if for some reason you don’t have access to cool shader techniques like custom shaders and normal maps? What if you just had to work with the geometry? It turns out that, no matter how you triangulate the cone, and no matter which edges you choose to split afterwards, you cannot make the apex perfectly spiky while making every other point on the cone’s side perfectly smooth.
To see this, let’s look at how the apex and its neighborhood is handled. If there is no split edge adjacent to the apex, then because of interpolation, the apex is smooth. So there has to be a split edge touching the apex. Every point on that split edge (except the apex) has to be smooth. But if that’s the case, then because interpolation is a continuous function, the apex is also smooth (with respect to that split edge). So we have a problem indeed.
Instead, we have to compromise. For instance, we can subdivide the edges on the side of the cone. If we just do one subdivision near the apex, this is the result (only vertices are marked now):
Unfortunately, the shading looks weird. This is because the mesh is triangulated before it’s interpolated, and the side of the cone consists mostly of trapezoids with a certain pattern of normals on the vertices. To illustrate the problem, let’s look at some trapezoids:
The trapezoids that makes up the cone side have the same property: pairs of normals on the non-parallel opposite edges are the same. The trapezoids are triangulated, hence the weird-looking shading on the cone. To mitigate this, we can do more subdivisions:
The cone now looks very cony up until that last eighth at the top, at which point we go back to square one with the round-looking cone. We can split all the edges adjacent to the apex to mitigate this.
Wow! A beautiful looking cone!1 And it only has 254 triangles!
So, in the end, you can assign normals to a can. But cone you assign normals to a cone? No you cone-not, at least without clever tricks or a compromise.
And that’s the end!2