
Original Link: https://www.anandtech.com/show/212
Gouraud Shading
Gouraud Shading is used in virtually all single pass rendering engines. Its simplicity, speed, and flexibility make it perhaps the only type of lighting directly appliable by hardware 3D accelerators. The only problem with Gouraud shading is that it's, well, very fake.
As you can see from the shot above, Gouraud Shading (which can be used as lighting) isn't very pretty. Since the texture is supposed to be a shiny metal, you would expect the light to reflect off of the metal. Also, chances are you would expect a "highlight" (bright spot) in the middle of the scene above. [Textures used are from Planet Half-life's Texture Studio Pak]
Why?
Why is Gouraud Shading so fast, yet so ugly? Well, the algorithm for Gouraud Shading will explain. Gouraud Shading calculates an intensity at each vertex of a polygon, and then LINEARLY interpolates the intensities along polygon edges and across polygon rows. When it comes to lighting, chances are if you see the world linear, it is an approximation. While Gouraud Shading looks good for lit polygons viewed at an angle. Polygons straight in front of the light source are generally shaded w/the same color throughout, since the intensities are about the same at each vertex. (In reality, the center should be brighter, since the angle between the light source and the center of the polygon (assuming polygon is straight in front of the light) is much smaller (well, small depends on how you look at it). You can also used the intensity formula to see that in the middle of the polygon, the intensity is greater (intensity at a point = Light Intensity / (distance from light source)^2 ). The Math is below:
Not only does Gouraud not shade correctly for most cases (actually all cases, but polygons viewed from the side are relatively accurate, or, at least look good), Gouraud shading produces an intensity warp, since the intensities are LINEARLY interpolated, they do NOT take into account the 3D properties of the polygon. This leads to "warping" as seen in linear (sometimes called affine) texture mapping, though not as noticeable. "Perspective correct" Gouraud shading detracts from Gouraud shading's main advantage over other lighting methods, speed, so it is generally not used (maybe hardware does this, not sure).
Phong Shading and Angle Interpolation
Well, we know that Gouraud shading is extremely fast, but also extremely ugly. The main problem with Gouraud shading is the lack of highlights, where necessary. There is another shading model which will give us the cool highlights that we want. This algorithm would be called Phong Shading.
What is it?
Recall that with Gouraud shading, intensities are interpolated? Well, with Phong shading, the normal between the vertices and the light source are interpolated, and the color calculated from these normals, per pixel. Obviously, this approach is quite slow, but it is much more accurate than Gouraud shading, not to mention it looks much much better. (A common misconception is that Phong shading is "real" shading. This is not the case. Phong shading linearly interpolates between normals, since you can't linearly interpolate between normals without generating error, Phong shading, is, well, wrong)
What's wrong with Phong?
The problem with Phong shading is that it is very very slow. Phong shading interpolates between normal vectors to get a normal vector at each pixel. For each pixel, it then uses this normal vector to calculate the light intensity at that point. This calculation is quite hefty, considering it must be done for each pixel. Currently, real time phong shading a 5-10k polygon level is virtually impossible. Of course, it is possible to generate a low resolution (16x16 or so) "phong texture" and then blend it in during rasterization (displaying the polygon). Chances are, this approach will be much (probably 4x or so) faster than Phong shading per-pixel in the rasterization loop, plus it is the only method of doing Phong shading in hardware. (Since no hardware I know of does Phong shading)
Another way of getting the highlight
Even though Phong is so slow, that doesn't mean that there isn't a way to get that cool highlight which is at least relatively fast. That method is, Angle Interpolation. Angle interpolation works virtually the same as Gouraud shading; however, instead of interpolating intensities, one interpolates (I bet you can't guess this one :) angles. Angle interpolation requires 1 addition and 1 table look up (that gives the intensity at various angles). Obviously, this is MUCH faster than Phong shading. Of course, you can't linearly interpolate angles without error (bummer), so angle interpolation is an approximation. This method looks relatively good (not as good as Phong shading, but close enough), and is very fast. Using the texture blending method discussed above, angle interpolation can be combined with 3D acceleration to help make some very fast nice looking dynamic lights.
Radiosity, as close as it gets...
Ok, we know Phong shading is cool, Gouraud shading is fast, etc. But how do games like Quake2 and Unreal create such realistic environments? Well, they use a lighting method called radiosity. Unlike Phong shading, Angle interpolation, and Gouraud shading, Radiosity is NOT a real-time technique, and probably won't be for a long time. It takes hours to compute Radiosity lighting for moderately sized scenes. Ok, so we know it's slow as hell, but what exactly is radiosity lighting?
What it is...
Radiosity lighting not only takes into consideration the "obvious" light sources (i.e. a lamp), but also treats every reflective (ambiguous term, almost any surface can be said to reflect some light) surface (polygons) as a light source. (Since every object either reflects some light or gives off some light) Now, if we were to do calculations per polygon, that would be very ugly, since each polygon would be assigned one color. For this reason, in order to calculate radiosity lightmaps (yep, lightmaps are calculated and then blended in with the texture), we must divide the polygons into 'patches' (small pieces of polygons...sort of). After the polygon is divided into patches, each patch is lit by every light source and every other patch. Obviously, this approach is very slow, because a typical scene can have tens of thousands of patches (even more!). We have to check each patch with every other patch, which means, for 10,000 patch scene, 10,000*10,000 checks (O(n^2), for those of you who care :). Even though radiosity takes forever to calculate, and imposes the restriction of static environments, the benefits are tremendous. Take a look at the following screen shot, showing what radiosity lighting alone can do to enhance the realism of a scene.
taken from Thomas A. Funkhouser's
Database and Display Algorithms for Interactive Visualization of Architectural Models.
PhD Thesis, Computer Science Division, UC Berkeley, September, 1993. Click here for 167 page PS file
.
Which lighting method is the best?
As if you already didn't know what I was going to say... there is no "best" lighting method. Radiosity is by far the most realistic, but it imposes the restriction of a static environment, with static lights. This is acceptable for now, but soon, gamers will be demanding dynamic environments.
Phong and Angle Interpolation and Dynamic Environments
The remaining three lighting methods I talked about are fast enough for real time rendering of an arbitrary environment. Actually, that depends on the number of lights. For angle interpolation and Phong shading, using the texture blending method, 1 texture must be blended for every light source (which affects the polygon). Now, if we have 10 light sources, anything about 640x480 will slow to a crawl on current accelerators. 20 light sources on the same polygon will bring even the all mighty Voodoo2 SLI to its knees. The problem with multiple lights when using Angle interpolation and Phong shading is that complexity increases on the pixel level. Since there is no way to do some "average normal" calculation to find out 1 normal at each vertex which will take into account all the light sources shining on the polygon, we must deal with each light separately. (There might be some ugly method of finding an "almighty" angle (talking about angle interpolation) which will take into account all the light sources, but I doubt it.)
So what's left? (Gouraud)
Unlike Phong and Angle interpolation, It is very easy to calculate an "almighty" intensity which will consider all the slight sources on the polygon. This reduces the problem with multiple lights from the pixel level to the polygon level. The only task now is to calculate the intensities at each vertex based on all the lights shining on the polygon. Unfortunately, this isn't very fast either, but currently, Gouraud shading is the fastest most feasible dynamic lighting method for areas with many light sources.
Mixing it all together
Now, we don't want to start using Gouraud shading all over again just because we can't do dynamic lighting with Radiosity, so what do we do? We can mix Gouraud shading with precalculated lightmaps to do dynamic lighting quite nicely. Of course, this won't be entirely accurate (the radiosity lightmap should change if a light is moved), but it will look much better than Gouraud shading alone, especially in the areas where there is little dynamic lighting going on. Judging from the flash lights in games like Half life, Blood2, and Unreal, I am speculating that this is the lighting approach they use.
Conclusion
Ok, that's all about lighting for tonight. Now you probably understand the basics behind some of the "hyping" lighting terminology used by game developers to pimp their new games.