We learned in the last chapter that we model shapes of objects by modeling their external surfaces. Normal vectors are common properties of surfaces that must be taken to account when creating any surface models.
We have seen the term "normal vector" before in Section 3.7.5. A normal vector to a plane is a vector that is perpendicular to it. A normal vector to a surface is a vector that is "perpendicular" to that surface in some sense. However, we have to be careful about its definition because a general surface is not completely flat like a plane, and so we cannot conveniently measure the angle between a vector and a surface to decide whether they are perpedicular to each other or not. (There is a way to extend the definition, of course!)
We care about normal vectors because they tell us about the "directions" of the surface. These directions can be used to perform (1) hidden surface removal (Chapter XXX) and (2) shading (Chapter XXX). Shading is largely about calculating how light interacts with a surface, and this interaction depends on the surface's geometry. The surface's directions, conveyed by normal vectors, are geometric information that plays a central role in lighting calculation.
Now, the confusing thing about normal vectors, at least in the field of computer graphics, is that there are multiple kinds of them. The normal vector we just talked about is called the surface normal vector. When we model shapes with triangle meshes, we deal with two more types: face normal vector and vertex normal vector. Let us now discuss them in turn.
A flat surface is a surface such that there is a 2D plane that contains it. Recall from Section 3.7.5 that a 2D plane in 3D space can be defined by (1) a point on the plane and (2) a vector called the "normal vector." The normal vector has the property that it is perpendicular to the plane, meaning that it is perpendicular to any vectors that is in that plane. Now, if a vector is perpendicalar to a plane, it is also perpendicular to any flat surface contained in that plane. So, we say that a normal vector to the plane is also a normal vector to the flat surface as well.
Let $\ve{n}$ be a normal vector to a flat surface. We know that it is not the only normal vector because because $2\ve{n}$, $3.14\ve{n}$, $-\ve{n}$, or any $c\ve{n}$ where $c \neq 0$ is also perpendicular to the flat surface.
To avoid ambiguity about the length of normal vectors, we often require that normal vectors be unit vectors. In other words, we prefer only to talk about $\ve{n}$ such that $\ve{n} = 1$. With this restriction, we have that a flat surface has two distinct (unit) normal vectors, and they point in the exact opposite direction.
The fact that there are two distinct normal vectors to a flat surface corresponds to the fact that surface has two sides. Now, we may choose to call one side the "front" side and the other the "back" side. This choice is arbitrary. After we have picked the side to call "front," we have decided the flat surface's orientation. In effect, we have chosen the way the flat surface is "facing." Picking the side to call "front" is equivalent to pick one of the two normal vectors to serve as "the" (one and only one) normal vector of the surface over the other. In this book, the normal vector is on the front side. In other words, the front side is the side we see when we look in the opposite direction of the normal vector. As a result, the choise of the normal vector reflects the orientation of a flat surface.
(a) | (b) |
So, from now on, the normal vector of a flat surface is the unit vetor that:
Let us stress that the normal vector to a flat surface is perpendicular to that surface as a whole. This means that we can place the normal vector anywhere on the surface, and the normal would be perpendicular to the surface at that point.
Curved surfaces such as spheres, ellepsoids, torii are used by artists approximate shapes of 3D objects. These surfaces belong to a class of surfaces called regular surface where the notion of normal vectors are well defined.
Intuitively, regular surfaces are surfaces that are "locally flat." This means that, when you pick a point on the surface and zoom in on it close enough, the surface in your vision should look flat. Another way to think about this is to imagine the surface to be very big and yourself to be a small creature standing on it. If the surface is a manifold, then it looks like you are standing on a flat plane. In fact, we all have this experience. The earth is round (i.e., its shape can be approximated quite well by a sphere or an ellipsoid), but we can hardly observe its curvature while standing at sea level. It took a long time for humanity to realize that the earth is not flat! (Sadly, some people believe it is even now.)
We will not, however, define the regular surface mathematically because doing so requires much mathematical machinery that we will not use again in the rest of the book.1
A regular surface has a property that allows it to have normal vectors. Each point $P$ of the surface has a plane called the "tangent plane" that "touches" the surface at $P$. For other types of surfaces, the existence of tangent planes are not gauranteed.
Formally, a secant plane to a surface is a plane that passes through three points of the surface. Let $P$ be a point on a surface $S$. We can force the three points to be closer and closer to $P$. Taking the limit of this process, the secant plane may approach a unique plane that contains $P$. This plane, if it exists, is called the tangent plane at $P$. It is the plane that best approximates the surface around $P$ among all the other planes. For a regular surface, a tangent plane exists for every point. As a result, a regular surface appears locally flat because the surface can be approximated locally by tangent planes.
(a) | (b) |
We say that a vector $\ve{v}$ is tangent to a surface $S$ at point $P$ if $\ve{v}$ lies in the tangent plane at $P$. We call such a vector $\ve{v}$ a tangent vector.
We say that a vector $\ve{n}$ is normal to a surface $S$ at point $P$ if the vector is perpendicular to the tangent plane at $P$. Such a vector is called a normal vector or a surface normal vector of $S$.
(a) | (b) |
If $S$ is a regular surface, then every point on it has a tangent plane and, consequentially, (infinitely many) normal vectors. Following the discussion in Section 6.1.1, we typically require that normal vectors be unit vectors. As a result, each point on $S$ has two normal vectors. One points away from the "front" side of the tangent plane, and the other from the "back" side.
Let us consider three simple regular surfaces and learn what their normal vectors and tangent planes are.
It is important to recognize that a plane is a regular surface. The plane is locally flat because it is globally flat. The tangent plane of the plane is the plane itself. The two unit normal vectors at all points are the same ones.
Let us consider an infinitely long cylinder or radius $r$ whose axis is the $z$-axis. The set of points that constitute the cylinder is given by $$ \{ (x,y,z) : x^2 + y^2 = r^2 \}.$$ Now, let $P = (p_x, p_y, p_z)$ be a point on the cylinder. It turns out that the vector $\ve{n} = (p_x,p_y,0)$ is a normal vector to the cylinder at $P$. So, the tangent plane at $P$ is given by: \begin{align*} &\{ (x,y,z) : ((x,y,z) - P) \cdot \ve{n} = 0 \} \\ &= \{ (x,y,z) : (x-p_x, y-p_y, z-p_x) \cdot (p_x, p_y, 0) = 0 \} \\ &= \{ (x,y,z) : (x - p_x)p_x + (y - p_y)p_y = 0 \} \\ &= \{ (x,y,z) : p_x x + p_y y - p_x^2 - p_y^2 = 0 \} \\ &= \{ (x,y,z) : p_x x + p_y y - r^2 = 0 \}. \end{align*} The last line follows from the fact that $(p_x,p_y,p_z)$ is a point on the cylinder, so it must be the case that $p_x^2 + p_y^2 = r^2$.
We can see a reason why the normal is $(p_x,p_y,0)$ by considering the cylinder's cross section. If we look at the intersection of the cylinder with the plane $z = p_z$, then we would see the cylinder's cross section as a circle of radius 1 whose center is the point $O = (0,0,p_z)$. The vector $(p_x, p_y, 0) = P - O$ is parallel to the line segment $\overline{OP}.$ Moreover, we know from Euclidean geometry that $\overline{OP}$ is perpendicular to the tangent line to the circle at $P$. So, $(p_x, p_y, 0)$ is perpendicular to the tangent line, which is a part of the tangent plane.
(a) | (b) | |
(c) | (d) |
Remember that $(p_x, p_y, 0)$ is but one of the infinitely many normal vectors at $P$. If $r \neq 1$, it is not a unit vector. If we restrict ourselves to talk only about unit normal vectors, then they are \begin{align*} \frac{\ve{n}}{\| \ve{n} \|} &= \frac{(p_x, p_y, 0)}{\sqrt{ p_x^2 + p_y^2 }} = \bigg( \frac{p_x}{r}, \frac{p_y}{r}, 0 \bigg), \\ -\frac{\ve{n}}{\| \ve{n} \|} &= \bigg( \frac{-p_x}{r}, \frac{-p_y}{r}, 0 \bigg). \end{align*}
Consider the sphere whose radius is $r$ and whose center is the origin is the point $O = (o_x, o_y, o_z)$. The sphere is the set \begin{align*} \{ (x,y,y) : (x - o_x)^2 + (y - o_y)^2 + (z - o_z)^2 = r^2 \}. \end{align*} Let $P = (p_x, p_y, p_z)$ be a point on the sphere. The vector $$\ve{n} = P - O = (p_x - o_x, p_y - o_y, p_z - o_z)$$ is a normal vector to the sphere at $P$. As a result, the tangent plane at $P$ is given by \begin{align*} &\{ (x,y,z) : ((x,y,z) - P) \cdot \ve{n} = 0 \} \\ &= \{ (x,y,z) : (x-p_x, y-p_y, z-p_z) \cdot (p_x, p_y, p_z) = 0 \} \\ &= \{ (x,y,z) : p_x x + p_y y + p_z z - p_x^2 - p_y^2 - p_z^2= 0 \} \\ &= \{ (x,y,z) : p_x x + p_y y + p_z z - r^2 = 0 \}. \end{align*}
A reason why $\ve{n} = P-O$ is a normal vector at $P$ is quite similar to that of the cylinder's normals. There are infinitely many planes that pass through $O$ and $P$. Picking one, the intersection of the plane and the sphere yields a great circle. Euclidean geometry again tells us that $\overline{OP}$ (and also $\ve{n}$) is perpendicular to the tangent line at $P$, which is a part of the tangent plane.
(a) | (b) | |
(c) | (d) |
In Section 6.1.2, we learned that the two unit normal vectors to a plane correspond to the plane's two sides. Moreover, we often pick one unit normal vectors to serve as "the" normal vector of the plane and thereby pick which side of the plane is the front side.
We can do the same to a regular surface. However, instead of picking only one unit normal vector, we need to pick a unit normal vector at each point on the surface because the tangent planes of different points can be different.
Because a regular surface contains infinitely many points, there are infinitely many decisions to make and therefore infinitely many ways to assign a unit normal vector to each point on the surface (Figure 6.9a). Nevertheless, the assignments are not equally good. We generally prefer assignments such that the normal vectors vary continuously across the surface. Such assignments are much easier to understand, and they avoid the problem of normal vectors dramatically switch direction as one move continuously from one point to another on the surface (Figure 6.9b). A consistent way to assign a unit normal vector at each point on the surface such that the normals vary continously is called an orientation of that surface (Figure 6.9c and 6.9d). If such as an assignment exist for a surface, we say that the surface is orientable.
(a) | (b) | |
(c) | (d) |
Regular surfaces that we have discussed so far—planes, infinite cylinders, spheres, and tori—are all orientable. A property of orientable surfaces is that they have two sides (Figure 6.10). The sides the normal vectors are on is the front, and the other side is the back.
An interesting fact is that not all surfaces are orientable. The Möbius strip is such a surface. If we pick a normal vector, say $\ve{n}$, for a point $P$, we find a loop on the surface that starts at $P$ and goes back $P$ that also forces us to pick $-\ve{n}$ as the normal vector at $P$ as well. In a sense, the Möbius strip is not orientable because it has only one side. In this book, we will not deal with unorientable surfaces.
Now, consider an orienable surface that is also closed, like a sphere. The surface splits space into two regions: the inside and the outside. The surface also has two sides: the front and the back. In computer graphics, it is common to require that the front side lies on the outside, or, in other words, the the normal vectors of a closed, orientable surface should point outward. In other words, we prefer the orientation in Figure 6.9c over the one in Figure 6.9d. As a result, for the infinite cylinder in Section 6.1.6.2, we prefer $(p_x/r, p_x/r, 0)$ over $(-p_x/r, -p_x/r, 0)$ as the normal vector because $(p_x/r, p_x/r, 0)$ points outside. For the sphere in Section 6.1.6.3, we prepare $(p_x/r, p_y/r, p_z/r)$ over $(-p_x/r, -p_y/r, -p_z/r)$ for the same reason.
Before going to the next section, let us take stock. We care about surface normal vectors because they inform us about the surface's geometry: the normal vector at a point on the surface immediately tells us what the tangent plane at that point is, and the tangent plane can be used to approximate the surface near the point. The normal vector also allows us to distinguish between the front and back sides of the surface. The knowledge is used for hidden surface removal (Chapter XXX), and it also allows us to shade the front side and the back side differently (Chapter XXX). Moreover, when the surface is closed, it also tells us which part of space is the inside and which is the outside. This is important for lighting calculation that involves the use of Snell's law (Chapter XXX).
It is also important to note that surface normal, as we have discussed so far, is a mathematical concept. On the other hand, the two other types of normals that we will discuss momentarily can be thought of as being both a mathematical concepts and concrete pieces of data stored in computers.
Face normal vectors are surface normal vectors when the surface is a mesh. While the graphics pipeline can only deal with triangle meshes, other 3DCG software (especiallying modeling software such as Blender, 3ds Max, or Maya) allows meshes where the primitives are general polygons: quadriliterals, pentagons, heptagons, and so on. Each polygon in a mesh is called a face. We will follow this nomenclature and call a triangle in a mesh a face too. A face normal vector is just a normal vector to a face.
When we specify a triangle, say $ABC$, we need to list its corner points in some order. Here, $A$ denotes the first corner, $B$ the second, and $C$ the third.
Example 6.1 For example, in the triangle mesh of Section 5.4.1, the $ABC$s of the two triangles are as follows:
We know from Section 3.7.5 that the vector \begin{align*} \widetilde{\ve{n}} = (B - A) \times (C - A) \end{align*} is a vector that is perpendicalar to the triangle. Dividing the vector by its length, we have that \begin{align*} \widehat{\ve{n}} = \frac{\widetilde{\ve{n}}}{\| \widetilde{\ve{n}} \|} = \frac{(B - A) \times (C - A)}{ \| (B-A) \times (C-A) \|} \end{align*} is a unit vector that is perpendicular to the triangle. However, we also know that \begin{align*} -\widehat{\ve{n}} = -\frac{(B - A) \times (C - A)}{ \| (B-A) \times (C-A) \|} = \frac{(C - A) \times (B - A)}{ \| (C-A) \times (B-A) \|} \end{align*} is another unit vector that is perpedicular to the triangle. Between $\widehat{\ve{n}}$ and $-\widehat{\ve{n}}$, which one we should pick as the normal vector of the triangle then?
In this book, we shall follow the convention is that the normal vector of triangle $ABC$, denoted by $\ve{n}$, is given by \begin{align*} \ve{n} = \widehat{\ve{n}} = \frac{\widetilde{\ve{n}}}{\| \widetilde{\ve{n}} \|} = \frac{(B - A) \times (C - A)}{ \| (B-A) \times (C-A) \|}. \end{align*}
Example 6.2 The normal vectors of the triangles of the mesh in Section 5.4.1 are as follows. \begin{align*} \mbox{Normal of Triangle #1} &= \frac{ \left( \begin{bmatrix}1 \\ 0 \\ 0\end{bmatrix} - \begin{bmatrix}0 \\ 0 \\ 0\end{bmatrix} \right) \times \left( \begin{bmatrix}1 \\ 1 \\ 0\end{bmatrix} - \begin{bmatrix}0 \\ 0 \\ 0\end{bmatrix} \right) }{\left\| \left( \begin{bmatrix}1 \\ 0 \\ 0\end{bmatrix} - \begin{bmatrix}0 \\ 0 \\ 0\end{bmatrix} \right) \times \left( \begin{bmatrix}1 \\ 1 \\ 0\end{bmatrix} - \begin{bmatrix}0 \\ 0 \\ 0\end{bmatrix} \right) \right\|} \\ &= \frac{ \begin{bmatrix}1 \\ 0 \\ 0\end{bmatrix} \times \begin{bmatrix}1 \\ 1 \\ 0\end{bmatrix} }{\left\| \begin{bmatrix}1 \\ 0 \\ 0\end{bmatrix} \times \begin{bmatrix}1 \\ 1 \\ 0\end{bmatrix} \right\|} = \frac{ \begin{bmatrix}0 \\ 0 \\ 1\end{bmatrix} }{\left\| \begin{bmatrix}0 \\ 0 \\ 1\end{bmatrix} \right\|} = \begin{bmatrix}0 \\ 0 \\ 1\end{bmatrix}. \\ \mbox{Normal of Triangle #2} &= \frac{ \left( \begin{bmatrix}1 \\ 1 \\ 0\end{bmatrix} - \begin{bmatrix}0 \\ 0 \\ 0\end{bmatrix} \right) \times \left( \begin{bmatrix}0 \\ 1 \\ 0\end{bmatrix} - \begin{bmatrix}0 \\ 0 \\ 0\end{bmatrix} \right) } { \left\| \left( \begin{bmatrix}1 \\ 1 \\ 0\end{bmatrix} - \begin{bmatrix}0 \\ 0 \\ 0\end{bmatrix} \right) \times \left( \begin{bmatrix}0 \\ 1 \\ 0\end{bmatrix} - \begin{bmatrix}0 \\ 0 \\ 0\end{bmatrix} \right) \right\| } \\ &= \frac{ \begin{bmatrix}1 \\ 1 \\ 0\end{bmatrix} \times \begin{bmatrix}0 \\ 1 \\ 0\end{bmatrix} } { \left\| \begin{bmatrix}1 \\ 1 \\ 0\end{bmatrix} \times \begin{bmatrix}0 \\ 1 \\ 0\end{bmatrix} \right\| } = \frac{ \begin{bmatrix}0 \\ 0 \\ 1\end{bmatrix} }{ \left\| \begin{bmatrix}0 \\ 0 \\ 1\end{bmatrix} \right\| } = \begin{bmatrix}0 \\ 0 \\ 1\end{bmatrix}. \end{align*} The normal vectors are the same. This is good because these two triangles are used to form a square, another flat surface. The square should have one normal vector rather than two.
A consequence of basing the normal vector $\ve{n}$ on $(B-A) \times (C-A)$ rather than other calculation is that one can determine the direction of the normal vector by looking at how the triangle's corners "swirl."
This is the because the direction of $(B - A) \times (C - A)$ is determined by the right-hand rule. Recall from Figure 3.19 that the direction of $(B - A) \times (C - A)$ depends on the rotation to get from $B-A$ to $C-A$. If the rotation is counterclockwise when we look at it, the cross production points towards us. If the rotation is clockwise, then the cross product points away from us.
Equivalently, we can trace the corners of the triangles in the specified order: from $A$ to $B$ to $C$ and then back to $A$ again. If the we see that the motion is a counterclockwise "swirling," then the triangle's normal vector would point towards us, and we are seeing the front side of the triangle. On the other hand, if the swirling is clockwise, the normal vector points away from us, and we are seeing the back side of the triangle.
(a) | (b) | (c) |
(d) | (e) | (f) |
When a triangle is a part of a mesh, the order of corners is determined by the order of the vertex indices in the index buffer. So, the order of vertex indices in the index buffer determines the direction of the normal vectors and the orientation of the faces.
There are as many normal vectors to a triangle mesh as there are faces. We want the face normals to be consistent to one another. The notion of consistency in question is inpired by the consitency of normal vectors in an orientation of a regular surface. It should be that, as we travel along the surface the normal vectors should not change abrubtly. To put it in another way, if we are a small creature standing on the front side of a mesh's face, we should not suddenly be on the back side if we walk to an adjacent face.
The above notion of consistency requires that the orders of vertex indices of the triangles be consistent with one another. More specifically, the vertices should be listed so that nearby triangles swirl in the same way. It should not be the case that, when we go from a triangle to another that is adjacent to it, one triangle swirl counterclockwisely, and the other swirl clockwisely.
For example, in Figure 6.13 below, we have two triangles that togehter form quadriliteral. The two triangles are formed by 4 vertices: $(-1,-1,0)$, $(1, -1, 0)$, $(0, 1, 0)$, and $(2, 1, 0)$. These vertices are numbered with integers from 0 to 3, respectively. The first triangle is formed from Vertices 0, 1, and 2, and the second triangle is formed Vertices 1, 2, and 3. Consider the following two ways of listing the vertex numbers in the index buffer.
[0, 1, 2, 1, 2, 3]
[0, 1, 2, 1, 3, 2]
The index buffers differ only at only the last two numbers. The two triangles have the same shape. However, Index Buffer #1 is to be preferred over Index Buffer #2. The reason is that the triangles in Index Buffer #1 swirl the same way, and so the normals are pointing in the same direction. On the other hand, in Index Buffer #2, one triangle swirls counterclockwisely, and the other swirls clockwisely. As a result, the normals point in different directions.
(a) | |
(b) | (c) |
(d) | (e) |
Another consistency issue to watch out for is when a mesh models a closed surface. In this case, we want the face normals to all point outward from the surface according to the convention in Section 6.1.7. To achieve this, we want to make sure that the vertex indices are ordered so that the vertices swirl counterclockwisely when you look at each triangle straight on from the outside of the mesh.
(a) | (b) |
Remember from the last chapter that the normal vector can be a vertex attribute. This attribute is what we mean by the vertex normal. This means that the vertex normals are data that the 3D modeler specifies as a part of the mesh they create.
Let us compare the vertex normal with the other two normals we previously introduce. The surface normal is a mathematical concept, and so it applies to abstract surfaces like the planes and the regular surfaces. The face normal is also another mathematical concept: it is the surface normal of a face in a mesh. Surface normals and face normals are not data. We never specify them directly inside a vertex buffer. In particular, face normals are defined implicitly by vertex positions and the order in which the vertices are listed in the index buffer.
Recall from the last chapter that, when WebGL draws a primitive, it must fill in points between the vertices of that primitive. The in-between points will inherit the vertex attributes. Points have positions because vertices have positions. We also saw in the last chapter (Figure 5.4 and Figure 5.5, in particular) that, when vertices have colors, points will also have colors. Similarly, when vertices have normals, points will also have normals. WebGL computes a point normal by interpolating vertex normals in the same way that it interpolates colors in the last chapter. (We will discuss how this interpolation is performed in the next chapter.) Figure 6.15 shows a triangle whose vertices have normals and the normals of some points on the triangle.
(a) | (b) |
The above figure, however, does not offer us the complete picture of what the interpolated normals are like as it only contains a sparse sample of points whose normals we visualize as arrows. It is hard to visualize all normals because arrows have volume. If we show too many arrows at once, they would end up intersecting and occluding each other, leading to a picture that is not at all understandable.
Fortunately, compute graphic practitioners have come up with a way to avoid this problem: representing normal vectors with colors. Because we require that normal vectors be unit vectors, it follows that each component of a normal vector must have value between $-1$ and $1$. Mathematically, if $\mathbf{n} = (n_x, n_y, n_z)$ is a normal vector, then it must be the case that $\| n \| = 1$ or \begin{align*} n_x^2 + n_y^2 + n_z^2 = 1, \end{align*} which implies \begin{align*} -1 &\leq n_x, \leq 1,\\ -1 &\leq n_y, \leq 1,\\ -1 &\leq n_z, \leq 1. \end{align*} This means that \begin{equation} \label{eq:normal-as-color} \bigg( \frac{n_x + 1}{2}, \frac{n_y + 1}{2}, \frac{n_z + 1}{2} \bigg) \end{equation} is a valid RGB color. Figure 6.16 shows the interpolated normals in Figure 6.15 visualized with the color scheme above. Notice that the color changes smoothly across the triangle, showing that the point normals vary continuously.
Note that we can also visualize the face normal of the triangle like in Figure 6.17. This time, all points have the same color because a triangle has only one face normal.
Notice the difference between Figure 6.16 and Figure 6.17. Looking at Figure 6.17, we understand immediately that the surface is flat because all points have the same surface normals. On the other hand, while the surface in Figure 6.16 is geometrically flat (because it is a triangle), the normal vectors vary across the surface like the way normal vectors of curved surface do. Furthermore, when we use these normals to compute the colors on the surface like in Figure 5.6 of the last chapter, the colors can convincingly fool the viewer that the surface is curved. Hence, vertex normals are a tool to make flat surfaces look curved. It is a key to model real-world objects with organic shapes with flat and straight mathematical objects.
Vertex normals are data, which means that the modeler can specify them any way they want. Arbitrary assignments, however, are almost always not useful, so we want more principled ways to specify the data. In computer graphics, there are at least two approaches.
This subsection discusses the former, and the subsection discusses the latter.
Treating vertex normals as samples of surface normals comes from a particular way we may think of a mesh: as an approximation of a curved regular surface. A curved regular surface has infinitely many points, all of which cannot be stored as computer data. We therefore sample a finite number of points from it, call these points "vertices," and connect the vertices to form primitives, thereby approximating the regular surface with many pieces of flat geometry. Because a vertice is originally a point on the regular surface, its position and its normal vector should agree with those of the corresponding regular surface point.
Let us look at a concrete example. Say, we want to create a mesh that approximates the sphere in Section 6.1.6.3. If we make a vertex out of a point $P$ on the surface of the sphere, then the vertex's normal vector should be $(P-O)/ \| P - O\|$ where $O$ is the origin of the sphere. We can see the consequence of specifying vertex normals in this way in Figure 6.18. Notice that, even with a few number of faces, the surface alreay looks curved. As we increase the number of faces, the faces become smaller, and the interpolate normals become more and more closer to the normals vectors of the sphere.
The drawback of this approach is that it only works when we know the normal vector of any point we want to make a vertex. This is only possible when we have mathematical formulas for everything. When this is the case, then the approach should be prefered because the normals would always have correct values.
Unlike the previous approach, this approach allows us to deal with arbitrary meshes that we have position data. What we do is very simple: make the normal at each vertex point in the same direction as the average of the face normals of all the faces that contain that vertex. The idea is that a vertex can be a part of multiple triangles. As a result, the vertex's normal vector can be any of the triangles' face normals. To reconcile between different options, we take the average of the normal vectors.
For example, let us say that we have a mesh with 3 triangles: $ABC$, $ACD$, and $ADB$ as shown in Figure 6.19. Let $\ve{n}_A$, $\ve{n}_B$, $\ve{n}_C$, and $\ve{n}_D$ denote the vertex normals, and let $\ve{n}_{ABC}$, $\ve{n}_{ACD}$, $\ve{n}_{ADB}$ denote the face normals. Then, \begin{align*} \ve{n}_A = \frac{\frac{1}{3}(\ve{n}_{ABC} + \ve{n}_{ACD} + \ve{n}_{ADB}) }{\| \frac{1}{3}(\ve{n}_{ABC} + \ve{n}_{ACD} + \ve{n}_{ADB}) \|} = \frac{\ve{n}_{ABC} + \ve{n}_{ACD} + \ve{n}_{ADB} }{\| \ve{n}_{ABC} + \ve{n}_{ACD} + \ve{n}_{ADB} \|}. \end{align*} because $A$ is a part of all three triangles. Similarly, we have that \begin{align*} \ve{n}_B &= \frac{\ve{n}_{ABC} + \ve{n}_{ADB} }{\| \ve{n}_{ABC} + \ve{n}_{ADB} \|}, \\ \ve{n}_C &= \frac{\ve{n}_{ABC} + \ve{n}_{ACD} }{\| \ve{n}_{ABC} + \ve{n}_{ACD} \|}, \\ \ve{n}_D &= \frac{\ve{n}_{ACD} + \ve{n}_{ADB} }{\| \ve{n}_{ACD} + \ve{n}_{ADB} \|}.\\ \end{align*}
(a) | (b) | (c) |
When we apply the approach to a mesh that approximates a regular surface that is finely triangulated enough, the vertex normals would yield interpolated normals that approximate the real surface normals well.
However, the result can be counter intuitive for coarse meshes. For example, the approach would try to make the box in Figure 6.21 look round while the silhouette is telling the viewer otherwise.
Real world objects do not always have smooth, curved surfaces. Man-made objects such as buildings, machines, and various types of food items can have flat faces and sharp corners or edges. When dealing with such objects, the two approaches for assigning vertex normals we have discussed about so far prove inadequate. Surfaces with sharp edges are not regular surfaces, so we cannot hope to find an underlying regular surface to take surface normal vectors from. Moreover, as can be seen in Figure 6.20, computing vertex normals from face normals will make the whole surface look round while we want each face individually to look flat.
The problem we face stems from the fact that vertices that are on sharp corners or edges must exhibit multiple normal vectors at once. For example, a corner of the cube in Figure 6.20 are a part of three flat faces with three different face normals. Unfortuately, a vertex has only one vertex normal attribute, so it cannot accommodate three normals at once.2
The solution, however, is incredibly simple. Whenever we have a vertex that needs to exhibit multiple normal vectors (or multiple values of any other attributes for that matter), split it into a number of distinct vertices that have the same positions but different normals. Now, when constructing triangles that meet at sharp corners or edges, we can use the appropriate vertex for that triangle. For example, instead of creating a cube in Figure 6.20 with only 8 corner vertices, we can instead model the cube as a collection of 6 flat faces where each face has its own 4 corner vertices (Figure 6.21).
(a) | (b) |
A mathematically inclined reader can consult standard textbooks on differential geometry such Manfredo P. do Carmo's Differential Geometry of Curves and Surfaces for a rigorous definition of regular surfaces.
Actually, it is possible to add more attributes to score the 2nd normal, 3rd normal, 4th normal and so on, but there are even more problems with this approach. First, we do not know in advance how many faces a vertex would be a part of, so we cannot know for sure how many attributes to allocated. Second, it becomes unclear which normal to use at which time.