Gouraud shading is a method for linearly interpolating a colour or shade across a polygon. It was invented by Gouraud in 1971. It is a very simple and effective method of adding a curved feel to a polygon that would otherwise appear flat. It can also be used to depth que a scene, giving the appearance of objects in the distance becoming obscured by mist. I suggest you also read the page on light sourcing if you do not already know the principles.

On the left is a curved surface rendered using flat shaded polygons, the other is Gouraud shaded. It is quite clearly smoother and more attractive and well worth spending the time to code.

Unlike a flat shaded polygon, you can specfy a different shade for each vertex of a polygon, the rendering engine then smoothly interpolates the shade across the surface. The technique is very similar to the standard scan converting, and can be handled very quickly with integer maths.

Some points to note though: It is best to restrict gouraud shading to three sided polygons. Sometimes polygons may not look quite as you expect when they have more than three vertices with very different shades.

## Scan converting

The scan converting algorithm is very similar to the flat shading algorithm, so I won't go into very much detail. In this case, you not only calculate the change in X value down the scanline, you also keep track of the shade. You do this in exactly the same way.

Now, before the horizontal strip is rendered to the screen, some small adjustments need to be made. It will help to have a picture here to clarify what's going on.

OK, the tiny polygon shown here is flat shaded just for clarity. Consider the line to be rendered, A-B. If this were a perfect world, it would be possible to render the line A-B. However, this is a pixelated screen, so it's only possible to render the line of three pixels C-D. The center of the first pixel, C, does not lie exactly on the point A, and pixel D does not lie exactly on the point B, so a slight adjustment is made for the sake of increased accuracy. Now, you may think this is just being pedantic, however, taking the trouble to increase the accuracy results in a much more beautiful polygon. This is especially true when you add texture mapping etc and the polygons are quite small.

So, how to make this adjustment. Firstly calculate the gradient of shade across the line as usual:

Gradient = (Bs - As) / (Bx - Ax)

Where As = shade at A, and Ax is the X value of A. Now calculate the exact value of the shade at C:

So, now you need to be able to render a strip of Gouraud polygon to the screen. This involves calculating the shade of each pixel and writing it to the screen. This is a simple process, since the shade changes linearly across the scanline. The process can be demonsrtated by a little pseudocode.

```Shade = Cs
loop X from Cx to Dx
plot pixel at (X,Y) with colour Shade
End of X loop
```
As usual, it's possible to reall crank up the speed of this algorithm by writing it in machine code. The algorithm given below will only really work on a PC in an 8-bit screen mode, but of course there are other methods for other platforms. Please note that this method is not perfect and will not produce perfect results where the rate of change of shade across a polygon is very small. But it is fine for most cases and faster than a Breshenham type mothod.

This method relies on the fact that the x86 series chips have 16 bit registers that can be treated as two 8 bit registers. In this implementation, the highest 8 bits of a regester are used as the integer part of the shade being interpolated, and the lower 8 bits are used as the fractional part.

This inner loop given just renders one horizontal strip of a polygon in an 8 bit screen mode. It uses 32 bit memory pointers. Because of the fact that it uses a fixed point value for the shade, it is possible to assign non-integer values for the shade values of the vertices, making for slightly more accurate rendering.

The routine requires a little setup code to begin with:

```length = Dx - Cx + 1
ScreenPtr = y*ScreenWidth + Cx
```
Now the inner loop:
```CX = length
AX = Cs * 256
EDI = ScreenPtr

top:
mov	[edi], ah		;write the pixel to the screen
inc	edi			;next pixel