Real-Time Shader Programming (The Morgan Kaufmann Series in Computer Graphics) - page 11


When you say "vertex," most people think that you're speaking of a location in 3-space—that is, an x, y, z triplet. In this book, that's called a point. A vertex in 3D graphics typically means all the properties that are used to describe that particular vertex—that is, all the information needed to describe a vertex so that it can be rendered. Of course, the most obvious one is its location—its "point." However, if I give you a vertex description consisting of just a position and tell you to draw it, what do you draw? No, it's obvious that you need more information in order to draw a vertex, be it the vertex color, material properties, texture coordinates, whatever. So in 3D graphics, a vertex is the vertex position and whatever other information is required to render that vertex. I should note that vertices themselves aren't rendered; they are typically grouped in threes and rendered as triangles—a triangle having enough information to describe a surface area.

This "other information" could be anything about that point that can be used to describe or calculate its final color value. In the simplest case, it's just the color information for that point (e.g., the point is red). Or the point may be part of a textured surface, in which case it might have texture coordinates instead of a color, in which case the color of the point is looked up from the texture. A vertex that's part of an illuminated surface (a "lit" surface in the vernacular) could have a set of material properties that are unique color values for diffuse, ambient, and specular properties plus the point's normal value. Thus when we talk about a vertex, we're not simply talking about the vertex's location, but also that we've specified enough information to draw it according to the situation we want to render it in, be that a textured surface, a lit surface, etc. In some parts of this text, I'll talk about a vertex and mean just the position part of the vertex; other times, I might be focused on the resultant color information, but the important thing is that a vertex is specified by more than just a point.


A point is a location in space, typically described by an x, y, z location—in other words, a location coordinate. It has no other properties. It can be translated to different locations or translated by application of a transformation matrix. Points (or coordinates) in 3D graphics are usually represented by homogenous coordinates, which represent the point as a location in 4D space through the addition of the w coordinate. For our purposes, this is just a semantic nicety that is taken care of by the graphics API, so we usually don't have to worry about it. Points are represented by the same structure we use for vectors, and many of the same mathematical operators can be performed on each, but be aware that though they look the same, they are very different.


In the mathematical sense, a vector is an array of numbers. We're going to use them in the 3D graphics shorthand, where vector means a direction vector. In this section, I want to cover some basic mathematical properties of vectors. One of the reasons that vectors and points are important is that in order to understand how to program shaders, you'll need to understand the math that's required to program some of the basics of shader programming. In order to do that, you need to have a basic understanding of vector and point math and to understand how these types of values are used in 3D graphics.

A vector is written a columnwise matrix, with elements x, y, and z.

Although this is fine for performing element-by-element analyses of what's going on, it's a bit tedious to read and write, so we'll usually just represent a vector by a bold lowercase letter.

Since both points and vectors are represented by a three- or four-element array of floating point numbers, we'll occasionally use the same math for them—for example, multiplying a point or a vector by a transformation matrix will transform either one. The math is identical, but it's good to keep in mind that though they might look the same, and can usually be treated the same, they aren't strictly interchangeable.

Vector Magnitude and Unit Vectors

Not only do direction vectors contain a direction, but they also encode a length or magnitude, which, depending upon what your vector represents, you can think of as the force of the vector in that direction. To compute the length of a vector, you take the sum of the squares of the vector's elements, and then compute the square root of the sum. Thus, the length or magnitude, | a |, of our vector, a, would be computed as

Another way of writing vector v is to break it into the magnitude (which is a scalar) and then the normalized or unit vector. A unit vector is a vector in which the magnitude of the vector is one. We'll write unit vectors in this book as a vector with a hat on it, for example, . A unit vector is computed (or normalized) from an unnormalized one by dividing each element of the vector by the vector's magnitude.

In most cases in 3D graphics, we just want a unit vector since we're usually interested in direction and not magnitude. Many of the lighting equations are simplified by using normal vectors.

Dot Product

The dot product is one of the more common things that you'll be using in shaders (hence the reason they are part of the shader language), so it's important to understand what they can tell us. I won't go into the derivation of the equations[2], but it's very useful to know how the dot product can be used to derive information about the relationship between two vectors. Now, given that we have two vectors, we can examine what the dot product tells us about the relationship between these vectors. Note that although the vectors in the illustrations are shown having a shared origin, this really isn't a requirement since a vector is a direction that's unrelated to any origin. This way it's easier to visualize the angle between the vectors, θ. To calculate a dot product, first we need two vectors, a and b (Figure 2.1).

Figure 2.1: The dot product can be used to calculate the angle between two vectors.

For any two vectors, the dot product describes a function of the magnitudes of the vectors times the cosine of the angle between them.

Thus the dot product (also called the inner product or the scalar product) gives us information about the angle between the two vectors and can be computed as the sum of the product of each element of the vectors. Note that the result from the dot product is a scalar value. Even more interesting is if and are unit vectors (which is typically the way we try to set things up for 3D graphics calculations), then the magnitudes of the vectors are one (and can be factored out), and the dot product gives us the cosine of the angle between the vectors directly.

You can also use trigonometry to show that the dot product can also be computed by computing the sum of the product of the individual elements of the vectors.

The preceding equation also illustrates that the dot product is order independent, or commutative, ab = ba. Getting the angle between two vectors allows you to calculate some very important information. Figure 2.2 shows you some of the information that the dot product tells you.

click to expand
Figure 2.2: The dot product lets you determine the relationship of two vectors.

Thus you can glean information about how vectors relate to one another. For example,

  • If the dot product is zero, then the vectors are parallel.

  • If vector b is the view direction, and vector a is the surface normal for a triangle, and if the angle is greater than zero, then you know the triangle is facing away from you—thus you could cull it or apply your back face material to it.

  • Another example would be if vector b were again the view direction, with the view origin at point o, and you have an object at point c. You can easily create a direction vector from the view origin to the object (assuming they are in the same coordinate system) by a=oc. Thus if a • b < 0, then the object is behind the viewpoint and you can cull it.

  • The dot product is used repetitively in lighting calculations to compute the intensity of a light shining on a surface.

Cross Product

The dot product is useful because it tells us about the relationship between two angles, but it doesn't tell us anything about how those angles are oriented in 3-space. If we have two nonidentical vectors, they define a plane in 3-space, and it's sometimes useful to know something about that plane. This is where the cross product comes in. Unlike the dot product, which gives a scalar value as a result, the cross product gives a vector as its result—hence it's also called the vector product.

The cross product of two vectors results in a third vector.

And this third vector c has the property that it's perpendicular to both a and b (Figure 2.3).

Figure 2.3: The cross-product of a × b is vector c, perpendicular to both.

This means that the dot products of vector c with the original two vectors are zero.

When I first learned to use the cross product, I was taught in the determinant notation, which looks like this.

This gives you another way of calculating the cross product by multiplying it out.

The cross product is also antisymmetric, meaning that the direction of the result is order dependent. If you reverse the order of the cross product, you'll get two vectors that are equal in magnitude, but point in opposite directions.

This is another way of stating that the cross product follows the right-hand rule. In Figure 2.4, we'd say that we're taking "a crossb." Thus if you take the fingers on your right hand and curl them from the first vector to the second—that is, sweep them from a toward b with your wrist at the junction—your thumb will point toward the c direction.

click to expand
Figure 2.4: The right-hand rule.

Or in math notation

The right-hand rule also means that you can generate the third vector given the other two.

If you take the length of the cross product of two vectors, you get the area of the parallelogram formed by those two vectors. Though we're usually interested in the area of the triangle, we can just take half that value to get the area of the triangle.

Thus if we have two vectors from point o on a triangle, we can compute the area of the parallelogram (the area in light blue in Figure 2.5) from the magnitude of the cross product of the vectors.

click to expand
Figure 2.5: The cross product lets you determine the area of the parallelogram formed by two vectors.

The area of the parallelogram is |b × a| = 2. (The area of the triangle formed by oab is thus 1.) It's also possible to calculate the area of the parallelogram by using the lengths of the vectors and the sine of the angle between them to get the following relationship:

which, if you square it and use the law of cosines, gives you what's called Lagrange's identity, which you'll note, now relates a cross product term to a dot product term.

Other useful formulas are the vector triple product

and the scalar triple product, v,

which gives you the area of the parallelepiped defined by vectors a, b, c (Figure 2.6). If v = 0, then this tells you that at least two of the three vectors lie in the same plane (assuming that none are zero). Note that the order is unimportant since the volume will remain the same no matter how you perform the multiplications.

click to expand
Figure 2.6: The scalar triple product lets you determine volumes.

For relating vectors using cross products, you have Jacobi's identity.

[2]For a good explanation of the basics of the dot product, see [FARIN 1998], p. 27, or [HILL 1990] p. 152.