In this segment, we are going to go into detail about Gouraud and Phong shading. Let's first talk about Gouraud shading which is the standard smooth shading.
Note also that is a lecture that actually talks about the operations that happen in rasterization. In a standard vertex or pixel shader you would just give the colors for I_1, I_2, and I_3, and after you've done that you would expect the rasterization hardware and OpenGL to do the interpolation. So you don't need to worry about the details of this for Gouraud shading.
However, we are interested in learning for this course what actually goes on under the hood. So here you have three vertices, I_1, I_2, I_3, and those correspond to the colors here. So, we assume I_1 is the color at vertex 1, I_2 is the color at vertex 2, I_3 is the color at vertex 3. Notice that the vertical extent goes from y_1 all the way to y_3.
So we want to find first the, to find the color of I_P, we first want to find the colors at I_a and I_b, and then we want to interpolate them. So let's first talk about the color at I_a.
I_a lies between I_1 and I_2, so if you want to do the interpolation, we do it along the vertical direction. Look at the length of this region and the length of this region. So, the length of this region is y_1 minus y_s. The length here is y_s minus y_2.
The total length of course is Y1 minus Y2. Now it's just a question of doing the standard interpolation formula. Which will mean that I_1, because it's further away from I1, it will be multiplied by the smaller quantity. So this will get I_1. And this quantity will multiply I_2.
Indeed, that's the formula here. I_1 times y_s minus y_2 plus I_2 times y_1 minus y_s. And divide the whole thing by the total length here, which is y_1 minus y_2. That's the formula for I_a.
We can similarly get a formula for I_b. Which is, will be equal to I_1 times, in this case, y_s minus y_3, and I_3 times y_1 minus y_s. And now you normalize by y_1 minus y_3.
Once you have the formulae for I_a and I_b, the question is what do you get for I_p? And in order to consider that one needs to consider the X coordinates. Because one is interpolating within a scan line. So we can consider this as being the x of a (x_a). And we can consider this as being x of b (x_b). Here of course you have X of P (x_p).
So the interpolation idea is the same. You have this length, which is x_p minus x_a, and you have this length which is x_b minus x_p. So I_a will be multiplied by x_b minus x_p and I_b will be multiplied by x_p minus x_a. Indeed this is what happens here. So you have I_a times x_b minus x_p, plus I_b, which is multiplied by x_p minus x_a. Again you normalize by x_b minus x_a. So it's just interpolation first in the vertical direction in order to get the locations for the endpoints of the scan line, and then interpolation along the scan line to get the, horizontally to get the final color of I_p.
The actual implementation of this is much more efficient than the formulae lead you to believe. For example I can precompute the division by y_1 minus y_2, I can find the reciprocal of that, y_1 minus y_3, x_b minus x_a and moreover you see as we go from one scanline to the next, the multiplicative factors, they reduce to addition.
And therefore there are very efficient algorithms that in fact don't involve multiplication or division at all, that just incrementally add quantities as you go from one scanline to the next. And this is a process which is generally known as scan conversion. But it also does the interpolation which is needed for Gouraud shading.
Errors, we've already talked about those in the previous segment. So here is an extreme case where I_1 and I_2 are 0 because either the light is pointing backwards or the eye does not see the point.
And now you have zeroes in both cases and you want to interpolate to make a highlight. Of course that is not going to happen; if you have zero in the two vertices the interpolation is also zero and so Gouraud can have problems. Moreover, the day we implemented it where we went vertically and then horizontally means the shading is not rotationally invariant, so if you were to rotate a point you would actually see the shading change.
For all of these reasons, Gouraud shading is useful only when you have relatively smooth shading effects. Mostly for diffused shading. But prior to the advent of fragment shaders, is you also needed to use Gouraud shading for specular highlights. And the way you handled that was by tessellating or breaking the model into enough triangles that relative to the size of the triangles, the shading is still smooth.
Next we consider the Phong Illumination Model, which is really the motivation also for the use of Phong shading and the use of fragment shaders.
And this corresponds to a specular or glossy material where you have highlights. At the bottom I've just showed some renderings I made many years ago where you've taken a lighting environment or a light probe that was acquired at Berkeley by Paul Debevec. It's in the Grace Cathedral in San Francisco. And I've rendered images with many different roughness settings, and you'll see from left to right it starts off being a mirror, then it gets blurred out and eventually on the right it almost looks like a diffuse surface.
And that, the amount of roughness controls the width of the highlights and your perception of how shiny the object is. Examples of specular, glossy materials are polished floors, glossy paint, white boards.
Furthermore, highlights behave somewhat differently from plastics or dielectric materials as opposed to metals. So on plastics, the highlight is the color of the light source, not the body color of the object. And this is a very common thing. You can have a green ball and you can look at the highlight, it's still white. Because the light source is white.
Metals, on the other hand, the highlight depends on the surface color and is modulated by the surface color. We don't have time to go into the physics of all of these effects. Hopefully that's something you can look up or we can cover in a future course. But these are basic properties of illumination and highlights, and it's also possible to regard them really as blurred reflections of the light source. If you look in the bottom panel, you can consider that the light source has just been blurred out as you go from left to right.
So Phong illumination, coupled with Phong shading is the appropriate way to make highlights, and again it's worth noting the distinction between these, they are commonly used together but technically they are different aspects.
The idea of Phong shading is simply that instead of interpolating the colors, what one actually does is interpolate the normals. So here we have the color was 0, but there is a correct normal at both of these locations. You interpolate the normal, and so you get the correct normal at the center and therefore you can evaluate the illumination model and get a highlight. So the entire lighting calculation is performed for each pixel.
In old-style OpenGL there was no Phong shading, it was just Gouraud shading, and therefore you would have to break this geometry up into enough triangles that it did actually compute the shading at each vertex. But in modern OpenGL in homework 2, you just write the fragment shader, and in this way you can do perfect Phong shading.
Let's talk about the vertex shader that's used in mytest3. Again you will be adapting the mytest3 shaders. They are very good background material for the shaders you need to write for homework 2.
So we start off with defining the version and again I have gone for a very old version to be backward compatible. Whether this should be varying or attribute or in or out depends on your system and use the skeletons and all of you are set up now. But, essentially it's saying there are these three variables: color, mynormal, and myvertex, that I'm actually going to pass on to the fragment shader.
So let's see what the main routine does. This is a texture coordinate, so it sets the texture coordinate from what you get from OpenGL, that's this gl_MultiTexCoord0, that's texture 0.
So you can have multiple textures, that's why we use the MultiTexCoord. We'll get into texture mapping later. You then set the gl_Position as projection matrix, modelview matrix times the vertex, and then this just defines standard OpenGL variables: the color, the normal the vertex. But I've given my own variable to illustrate that what OpenGL is now going to do is interpolate these values from the vertices and the interpolated value will be available at the fragment for me to write my fragment shader.
The next thing we're going to talk about is the type of different lighting and materials. Lights: points and directional, and shading: ambient, diffuse, emissive, and specular.