Gollum seems intent carrying on with himself. As he sits by the shore, debating his friends' demise, eyes wide with anticipation of holding the ring once again, the camera moves close. Closer. Now you are within mere inches of his face. You can see every detail of his wreched translucent skin gleaming in the moonlight. How can this creature look so real? The stunning image you are looking at is the result of hundreds of hours of work with shaders.
Today, shaders have found their place in nearly every industry, most notably the entertainment industry, where they make their showcase in the form of stunning visual effects, pushing the line between fiction and reality. Their single solitary task is to define the appearance of surfaces. For example, the above spheres are all identical with the exception of the shader applied to them. Shaders have the ability to make any surface look like it is made of anything, and because of this, they have played a central role in the design of cinema special effects and game graphics.
When a computer draws a 3D object, it does it with something called a renderer. The renderer's job, put simply, is to talk to the shaders about all of the objects in the scene and draw what the shaders say to draw. The renderer figures out which objects are 'underneath' which pixels. It then asks an object's shader what color the object should be at a given pixel, and the shader answers back. The renderer plots that color, and moves onto the next. That is the basic idea behind it all.
Most shaders are based on lights. That is, they determine how to color a surface by looking at how the surface is oriented toward lights in the scene (see the image at the left). This shading model, or algorithm, is called the Lambertian shading model. The Lambertian shading model says the amount of light hitting a given point on a surface depends on the position of the lights around the surface and the direction the surface is facing. This is, not surprisingly, quite obvious when you think about it. Bring a candle up to an apple, and the apple will be lit where it more directly faces the candle's flame.
A shader, of course, doesn't have to literally 'shade'. It could just as easily make every spot on a surface the same color. These kinds of shaders actually have a use, and are usually called "flat" or "constant" shaders (see the image on the right). For example, they are useful for making the background behind some subjects one solid color, or for giving the appearance that something is emitting light. Sometimes it is useful to set some objects one solid color so that you can find their contours easily without getting confused by their 3D shape. This is usually only done during production, though, so you almost never see the output from flat shaders in a final image.
As I said a moment ago, the Lambertian shading model lives at the heart of nearly every shader used. This is because, quite simply, people want their shaders to reflect the real-world quality of lighting. They want their objects to be shaded according to the lights around them. In order to understand how this model works, and how exactly you can shade by using lights, you have to learn a little about vectors. Vectors are really very simple in concept. They are simply things that point. Yep. That's it. They are like arrows pointing in a direction. There are some nice operations for comparing vectors too, which you will see soon.
Remember, Lambertian shading compares the lighting direction with the direction the surface faces. Well, those are actually two vectors. The surface's facing direction at any point is called its surface normal. The surface normal is a vector that points in the direction the surface is facing. That's all it ever does. See the image to the left? Those green lines are the surface normals of the sphere. Now, we also have our second vector. This vector points from the surface to a light. This is the orange line you see to the left. By comparing the angle between a surface normal and a lighting vector, you can determine how much light is hitting that point on our surface (see the image to the right). The method used to compare the angle between two vectors is called the dot product. When the two vectors are pointing in very different directions, the dot product gives a very low number. When the vectors are pointing in similar directions, the dot product approaches the number one. So, knowing this, if we were to ever take the dot product between the surface normal and the lighting vector, and wind up with the number one, we would know that spot on the surface is facing directly at a light.
Now that you know how the Lambert shader works, it's time to take a look at some of the other basic types of shaders. They all build upon the idea of the Lambert shader, but add their own features on top of it, like specular highlights, or fresnel reflectivity. Basically, lots of interesting words which might not mean much right now.
Throughout the rest of this document, I'm going to make a change. Instead of using boring old spheres as test images, I'm going to use a little piggy bank. Now, I've decided to go against decades of computer graphics tradition and not use the good old teapot. Too bad! I wanted something a little more interesting than a plain old sphere, but not so cliche as the "computer graphics teapot", and I had this piggy bank sitting on my desk.
First off, I am going to introduce to you the major components of a "modern" shader. These components work together to give a surface the overall appearance of resembling some material. The first components I'm going to cover here are the most basic and common: Color, Incandescence, Specularity, and Reflectivity.
Color is perhaps the most basic attribute of any shader. You get the color of a point on a surface by multiplying a solid color by the output of the Lambert shading function. For example, if you want to color an object solid bright red (R1, G0, B0), and the point you're shading has 65% light falling on it (0.65 from the Lambert function), then you plot the color (1*0.65, 0*0.65, 0*0.65), to get (0.65, 0, 0). So that point is 65% red. By doing this, you have both Lambert shading and color working together.
Shading formula with just color
Where "Shading" is the value from the Lambert formula.
Incandescence is actually very, very simple. It ignores lighting entirely, and simply adds a whole color to every point on a surface. This gives the appearance of the surface actually luminous.
Shading formula including incancescence;
Specularity is an extension of the Lambert shading method. It attempts to mimic the highlights you see on shiny objects. Unlike the Lambert shading formula, specular highlights are dependent upon the location of the camera. They use the location of the light source, the surface normal, and the location of the camera to figure out how much light from the light source is being reflected towards the camera. Specular highlights are added back to the color of an object much like Incandescence. Specular highlights are also usually multiplied by a color to give them a tint.
Shading formula including Specularity:
Reflectivity is used to integrate light reflected from the scene into the final shaded color. Reflectivity, like Specularity and Incandescence, is also merely added. Reflected colors are usually multipled by the amount of specularity, as well, since the specularity of a surface is related to how reflective it would be.
Shading formula including Reflectivity:
If you were to look at all of the vectors used to figure out all of these shading components, it would look like this:
Here you can see the first two vectors we covered earlier, the Lighting Vector (L) and the Normal Vector (N). Remember that comparing the directions of these two vectors tells us how much light is falling on that point. I will briefly describe these vectors again, as well as the new ones we see.
Normal Vector (N) - Points in the direction the surface faces at a given spot.
Lighting Vector (L) - Points from a spot on the surface to a light source.
Camera Vector (V) - Points from a spot on the surface to the camera viewing it.
Reflection Vector (R) - This vector is used to determine what part of the scene is being reflected off of a certain spot on the surface. It points from the surface out into the scene. Whatever it hits is reflected at that spot. It can be found by reversing the camera vector (V) so that it points at the surface, then adding 2 * ( N * dot(N, V) ). Confusing? Here's a step-by-step:
Half Vector (H) - The Half Vector is used for calculating the brightness of the specular highlight. By comparing its direction to the Normal Vector (N) (using the dot product) the specular value can be found. As H gets closer to N, the specular highlight at that point gets brighter. It is created by adding the Camera Vector (V) to the Lighting Vector (L), and dividing by 2. Thus, this vector is the average between L and V. Specular Value = dot(N, H), and H = (L + V) / 2.