xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0">

<?dbhtml filename="Tutorial 09.html" ?>

- <para>Thus far, our lighting models </para>

+ <para>The diffuse lighting model works reasonably well for a smooth, matte surface. Few objects

+ in reality conform to this archetype. Therefore, in order to more accurately model real

+ objects, we need to improve upon this. Let us focus on making objects appear shiny.</para>

+ <para>Shiny materials tend to reflect light more strongly in the opposite direction from the

+ angle of incidence (the angle between the surface normal and the incoming light direction).

+ This kind of reflection is called a <glossterm>specular reflection.</glossterm> A perfect

+ specular reflector would be a mirror.</para>

+ <para>One way to show that an object is shiny is to model <glossterm>specular

+ highlights.</glossterm> A specular highlight is a bright highlight on an object caused

+ by direct illumination from a light source. The position of the highlight changes with the

+ view direction as well as the light direction.</para>

+ <para>Modelling true specular reflection would require reflecting all light from objects in the

+ scene, whether direct or indirect. However for many objects, like shiny plastics and the

+ like, indirect specular reflections are very weak. Thus, by modeling direct specular

+ reflections, we can make an object appear shiny without having to do too much work.</para>

+ <para>We will look at several models for specular highlights and reflection. The Lambertian

+ diffuse reflectance model was reasonably good for modelling diffuse lighting, but there are

+ several models for specular reflection that should be considered. They vary in quality and

+ <para>Note that these models do not throw away diffuse lighting. They all act as supplements,

+ adding their contribution into the overall result for the lighting equation.</para>

+ <title>Microfacets</title>

+ <para>All of these specular reflection models work based on an assumption about the

+ characteristics of the surface. If a surface was perfectly smooth, then the specular

+ highlight from a point light would be infinitely small (since point lights themselves

+ are infinitely small).</para>

+ <!--TODO: Show a perfectly smooth surface with reflection from a light source. Have several camera positions.

+Position A should be in view of the reflection at the point P, while position B should not.-->

+ <para>Notice that the intensity of the reflected light depends not only on the angle of

+ incidence, but only the direction to the viewer. This is called the <glossterm>angle of

+ view</glossterm> or <glossterm>viewing angle</glossterm>. Viewing position A detects

+ the light specularly reflected from the surface, but the viewing position B does

+ <para>Surfaces however are rarely perfectly smooth. Surfaces that seem smooth from far away

+ can be rough on closer examination. This is true at the microscopic level as well, even

+ for surfaces that look quite smooth. This roughness can be modelled by assuming that a

+ surface is composed of a number of <glossterm>microfacets.</glossterm></para>

+ <para>A microfacet is a flat plane that is oriented in a single direction. Each microfacet

+ reflects light perfectly in that direction. A surface with microfacets would look like

+ <!--TODO: show two 2D surface with microfacets, one relatively rough and one smooth.-->

+ <para>It is part of the microfacet model's assumption that many microfacets on a surface

+ will contribute to the light returned under a single pixel of the final image. So each

+ pixel in the rendered image is the result of an aggregate of the microfacets.</para>

+ <para>The average normal of the microfacets is the surface normal at that point. The

+ relative smoothness of a surface can be modeled as a statistical distribution of the

+ orientation of microfacets on the surface. A smooth surface has a distribution close to

+ the average, while a rough surface has a broader distribution.</para>

+ <para>Thus, a model of specular reflections includes a term that defines the overall

+ smoothness of the source. This is a surface characteristic, representing the

+ distribution of microfacets using whatever statistical distribution the particular

+ specular model is using. One of the main differences between specular models is the kind

+ of statistical distribution that they use.</para>

+ <para>Specular highlights are formed because, even though the surface normal may not be

+ oriented to directly reflect light from the light source to the viewer, some microfacets

+ may still be oriented to reflect a portion of that light. A microfacet distribution

+ model determines the proportion of microfacets that happen to be oriented to reflect

+ light towards the viewer.</para>

+ <para>Smooth surfaces, those who's microfacets do not deviate much from the surface normal,

+ will have a small, bright highlight. Rough surfaces, who's microfacets are oriented in

+ wildly divergent directions, will have a much dimmer, but larger specular highlight.

+ These highlights will have positions and shapes based on the angle of incidence and the

+ <para>Note that specular reflectance models do not become diffuse reflectance models when

+ taken to the extreme case of maximum roughness. Specular reflection represents a

+ different mode of light/surface interaction from diffuse reflection.</para>

+ <title>Phong Model</title>

+ <para>The simplest model of specular illumination is the <glossterm>Phong model</glossterm>.

+ The distribution of microfacets is not determined by a real statistical distribution.

+ Instead it is determined by... making things up.</para>

+ <title>On Phong and Nomenclature</title>

+ <para>The term <glossterm>Phong shading</glossterm> was once commonly used to refer to

+ what we now know as per-fragment (or per-pixel) lighting. That is, evaluating the

+ lighting equation at every fragment over a surface. This term should not be confused

+ with the Phong specular lighting model. Because of this, the term <quote>Phong

+ shading</quote> has fallen out of common usage.</para>

+ <para>The Phong model is not really based on anything real. It doesn't deal in microfacet

+ distributions at all. What the Phong model is is something that looks decent enough and

+ is cheap to compute. It approximates a statistical distribution of microfacets, but it

+ is not really based on anything real.</para>

+ <para>The Phong model states that the light reflected in the direction of the viewer varies

+ based on the angle between difference between the view direction and the direction of

+ perfect reflection. Mathematically, the Phong model looks like this:</para>

+ <!--TODO: Show the phong equation. Phong term = cos(V, R) ^ s-->

+ <para>The brightness of the specular highlight for a particular viewing direction is based

+ on raising the cosine of the angle between the view direction and the reflection

+ direction to a power. As previously stated, this model is not based on anything real. It

+ simply creates a bright somewhat-circular area on the surface. This area gets dimmer as

+ the viewer is farther from the direction of perfect reflection.</para>

+ <para>The <varname>s</varname> term in the equation represents the roughness of the surface.

+ A smooth surface, which should have a smaller highlight, has a large

+ <varname>s</varname>. Since the cosine of the angle is a number on [0, 1], taking it

+ to a power greater than 1.0 will make the number smaller. Therefore, a large

+ <varname>s</varname> exponent will make for a small highlight.</para>

+ <para>The specular exponent can range from (0, ∞). A small exponent makes for a rougher

+ appearance, while a large exponent suggests a shiny surface.</para>

+ <title>Specular Absorption</title>

+ <para>The Phong term computed above is then multiplied with the light intensity. This

+ represents the maximum light reflected along the view direction.</para>

+ <para>However, just as with diffuse lighting, surfaces can absorb some quantity of the

+ light that would be specularly reflected. We could use the diffuse color here,

+ multiplying it by the specular term. But this would not be physically correct for

+ many kinds of objects.</para>

+ <para>Many surfaces, particularly certain man-made pigments and plastics, have multiple

+ layers to them. The top layer will specularly reflect some portion of the light.

+ However, it will also let some portion of that light reach lower layers. These

+ layers have stronger diffuse reflectance. So the specular absorption on the surface

+ has different characteristics than the diffuse absorption in the lower layers.

+ Usually, the specular layer reflects equally on all wavelenths, so the specular

+ highlight tends to be the color of the light itself.</para>

+ <para>Notably, metals do not do this. Their diffuse absorption tends to be the same as

+ their specular absorption. So while blue plastic under white light has a white

+ specular highlight, gold metal under white light has a gold highlight.</para>

+ <title>Drawing Phong</title>

+ <para>The <phrase role="propername">Phong Lighting</phrase> tutorial demonstrates the

+ Phong specular model.</para>

+ <!--TODO: Show a picture of the tutorial.-->

+ <para>The tutorial is controlled similarly to previous lighting tutorials. The

+ <keycap>W</keycap>, <keycap>A</keycap>, <keycap>S</keycap>, and

+ <keycap>D</keycap> keys control the orientation of the cylinder. Pressing the

+ <keycap>T</keycap> key will swap between the scaled and unscaled cylinder. The

+ <keycap>Y</keycap> key toggles the drawing of the light source. The

+ <keycap>B</keycap> key will toggle the light's rotation on/off. Pressing the

+ <keycap>Space Bar</keycap> toggles between drawing the uncolored cylinder and

+ the colored one.</para>

+ <para>The light's position is mostly controlled as before, with the

+ <keycap>I</keycap>,<keycap>J</keycap>, <keycap>K</keycap>, and

+ <keycap>L</keycap> keys. The specular value is controlled by the

+ <keycap>U</keycap> and <keycap>O</keycap> keys. They raise and low the specular

+ exponent. Using <keycap>Shift</keycap> in combination with them will raise/lower the

+ exponent by smaller amounts.</para>

+ <para>The <keycap>G</keycap> key toggles between a diffuse color of (1, 1, 1) and a

+ darker diffuse color of (0.2, 0.2, 0.2). This is useful for seeing what the specular

+ would look like on a darker surface color.</para>

+ <para>The <keycap>H</keycap> key selects between specular and diffuse, just specular and

+ just diffuse. The ambient term is always used. Pressing <keycombo>

+ </keycombo> will toggle between diffuse only and diffuse+specular.</para>

+ <para>The rendering code is nothing you have not seen in earlier tutorials. It loads 6

+ programs, and uses the various controls to select which to use to render.</para>

+ <para>There are two vertex shaders in use. One that takes the position and normal

+ attributes, and one that takes them plus a per-vertex color. Both of them output the

+ camera-space vertex normal (computed with a normal matrix), the camera-space vertex

+ position, and the diffuse color. In the case of the shader that does not take a

+ per-vertex color, the diffuse color output is taken from a uniform set by the

+ <para>The fragment shaders are more interesting. They do lighting in camera space, so

+ there is no need for the reverse-transform trick we used previously. The shaders

+ also use light attenuation, but it only varies with the inverse of the distance,

+ rather than the inverse squared.</para>

+ <para>The main portion of the specular+diffuse fragment shader is as follows:</para>

+ <title>Phong Lighting Shader</title>

+ <programlisting language="glsl">vec3 lightDir = vec3(0.0);

+float atten = CalcAttenuation(cameraSpacePosition, lightDir);

+vec4 attenIntensity = atten * lightIntensity;

+vec3 surfaceNormal = normalize(vertexNormal);

+float cosAngIncidence = dot(surfaceNormal, lightDir);

+cosAngIncidence = clamp(cosAngIncidence, 0, 1);

+vec3 viewDirection = normalize(-cameraSpacePosition);

+vec3 reflectDir = reflect(-lightDir, surfaceNormal);

+float phongTerm = dot(viewDirection, reflectDir);

+phongTerm = clamp(phongTerm, 0, 1);

+phongTerm = cosAngIncidence != 0.0 ? phongTerm : 0.0;

+phongTerm = pow(phongTerm, shininessFactor);

+outputColor = (diffuseColor * attenIntensity * cosAngIncidence) +

+ (specularColor * attenIntensity * phongTerm) +

+ (diffuseColor * ambientIntensity);</programlisting>

+ <para>The initial section of code should be familiar. The Phong specular computations

+ start with computing the direction to the camera. Since we are working in camera

+ space, we know that the camera is at the origin (0, 0, 0). The direction from point

+ A to point B is the normalization of B - A. Since the destination point is at the

+ origin, that becomes simply -A, normalized.</para>

+ <para>The next line computes the direction of perfect reflection, given the light

+ direction and the surface normal. The function here, <function>reflect</function>,

+ is a standard GLSL function used for precisely this purpose. Notice that the

+ function in question requires the that the light direction is the direction

+ <emphasis>from</emphasis> the light. Our light direction is the direction to the

+ light. This is why it is negated.</para>

+ <para>Using the function is useful, but it is important to know how to compute the

+ reflection direction on your own. Here is the formula:</para>

+ <!--TODO: equation of the reflection direction computation.-->

+ <para>Again, this equation assumes that L is the direction <emphasis>from</emphasis> the

+ <para>From here, the Phong term is computed by taking the dot product of the reflection

+ direction and the view direction, clamping it to 0, 1. The next line, where we use

+ the angle of incidence, is very important. What this line does is prevent us from

+ having a specular term when the surface normal is oriented away from the light. If

+ this line were not here, it would be possible to have specular highlights appear to

+ shine <emphasis>through</emphasis> a surface. Which is not particularly

+ <para>The GLSL standard function <function>pow</function> is next used to raise the

+ Phong term to the power. This function seems generally useful, but it has a large

+ number of limitations. The <function>pow</function> function computes <inlineequation>

+ <mathphrase>X<superscript>Y</superscript></mathphrase>

+ </inlineequation>, where X is the first parameter and Y is the second.</para>

+ <para>This function only works for values of X that are greater than or equal to 0; it

+ returns undefined values (ie: anything) otherwise. Clamping the Phong term ensures

+ this. Also, if X is exactly 0.0, then Y must be strictly greater than zero;

+ undefined values are returned otherwise. These limitations exist to make computing

+ the power function much faster.</para>

+ <para>And for Phong specular computations, the limitations almost never come into play.

+ The cosine of the angle is clamped, and the specular exponent is not allowed to be

+ <para>Notice that the specular term is added into the diffuse and ambient terms. This

+ has meaning for the intensity issue we have seen before. If the diffuse and specular

+ colors are too large, and the light attenuation is quite small, then the resulting

+ values from the lighting equations can be larger than 1.0 in magnitude. Since OpenGL

+ automatically clamps the colors to 1.0, this can cause unpleasant effects, where

+ there appears to be a very bright, white area on a surface.</para>

+ <title>Visual Specular</title>

+ <para>Having even a weak specular term can make a significant, if subtle, difference. In

+ our case, the specular color of the material is a fairly weak (0.25, 0.25, 0.25).

+ But even with a rough specular highlight, the surface looks more physically

+ <para>In particular, it is interesting to note what happens when you use a very dark

+ diffuse color. You can activate this by pressing the <keycap>G</keycap> key.</para>

+ <!--TODO: Show dark diffuse color.-->

+ <para>If there was no specular term at all, you would a virtually scene. The specular

+ highlight, even with the fairly weak specular reflection of 0.25, is strong enough

+ to give some definition to the object when seen from various angles. This more

+ accurately shows what a black plastic object might look like.</para>

+ <para>One thing you may notice is that, if you bring the light close to the surface, the

+ specular area tends to have very sharp edges.</para>

+ <!--TODO: Show a picture of the clipping.-->

+ <para>This is part of the nature of specular reflections. If the light is almost

+ perpendicular to the surface, the specular reflection will shine brightest when the

+ light is almost eclipsed by the surface. This creates a strong discontinuity at the

+ point where the light is no longer in view.</para>

+ <para>You generally see this most with rough surfaces (small exponents). With smoother

+ surfaces, this is rarely seen. But this is not the only visual oddity with Phong and

+ having small exponents.</para>

+ <para>If you drop the exponent down to the minimum value the code will allow, you will

+ see something like this:</para>

+ <!--TODO: show a picture of the Phong distortion.-->

+ <para>This ring area shows one of the main limitations of the Phong model. When trying

+ to depict a surface that is rough but still has specular highlights, the Phong model

+ starts to break down. It will not allow any specular contribution from areas outside

+ of a certain region.</para>

+ <para>This region comes from the angle between the reflection direction and the view

+ direction. This area is the region where the reflection direction and view direction

+ are more than 90 degrees apart.</para>

+ <para>Under the microfacet model, there is still some chance that some microfacets are

+ oriented towards the camera, even if reflection direction is pointed sharply away.

+ Thus, there should be at least some specular contribution from those areas. The

+ Phong model cannot allow this, due to how it is computed.</para>

+ <para>What all this tells us is that Phong works best with larger exponents. Small

+ exponents show its problems and limitations.</para>

+ <title>Blinn-Phong Model</title>

+ <para>The problem with Phong, with regard to the reflection and view directions being

+ greater than 90 degrees, can be solved by changing the computation. This modified model

+ is called the <glossterm>Blinn-Phong specular model</glossterm> or just the

+ <glossterm>Blinn specular model.</glossterm></para>

+ <para>It is no more physically correct than the Phong model. But it does tend to account for

+ more than Phong.</para>

+ <para>The main problem with Phong is that the angle between the view direction and the

+ reflection direction has to be less than 90 degrees in order for the specular term to be

+ non-zero. So cases like this:</para>

+ <!--TODO: Show the Phong problem in 2D-->

+ <para>These are not modeled correctly. These could have microfacets that are oriented

+ towards the camera, but Phong cannot properly render this. The problem is that the dot

+ product between the view direction and reflection direction can be negative, which does

+ not lead to a reasonable result when passed through the rest of the equation.</para>

+ <para>The Blinn model uses a different set of vectors for its computations, one that are

+ less than 90 degrees in all valid cases. The Blinn model requires computing the

+ <glossterm>half-angle vector</glossterm>. The half-angle vector is the direction

+ halfway between the view direction and the light position.</para>

+ <!--TODO: Show a 2D representation of the half-angle vector.-->

+ <!--TODO: Equation for the half-angle vector.-->

+ <para>When the view direction is perfectly aligned with the reflected direction, the

+ half-angle vector is perfectly aligned with the surface normal. To describe the

+ half-angle vector another way, it is the direction the surface normal would need to be

+ oriented in in order for the viewer to see a specular reflection from the light

+ <!--TODO: Show the halfangle vector for a view direction equal to the reflection direction.-->

+ <para>So instead of comparing the reflection vector to the view direction, the Blinn model

+ compares the half-angle vector to the surface normal. It then raises this value to a

+ power representing the shininess of the surface.</para>

+ <!--TODO: Equation of the Blinn term: cos(H, N) ^ s-->

+ <para>The angle between the half-angle vector and the normal is always less than 90 degrees.

+ So the Blinn specular model produces similar results to the Phong model, but without

+ some of Phong's problems. This is demonstrated in the <phrase role="propername">Blinn vs

+ Phong Lighting</phrase> tutorial.</para>

+ <!--TODO: Show an image of Blinn from the tutorial.-->

+ <para>The controls are similar to the last tutorial. Pressing the <keycap>H</keycap> key

+ will switch between Blinn and Phong specular. Pressing <keycombo>

+ </keycombo> will switch between diffuse+specular and specular only. Because the specular

+ exponents have different meanings between the two lighting models, each model has a

+ separate exponent. The keys for changing the exponent values will only change the value

+ for the lighting model currently being viewed.</para>

+ <para>The real work here is, as before, in the shader computations. Here is the main code

+ for computing the diffuse + Blinn illumination.</para>

+ <title>Blinn-Phong Lighting Shader</title>

+ <programlisting language="glsl">vec3 lightDir = vec3(0.0);

+ float atten = CalcAttenuation(cameraSpacePosition, lightDir);

+ vec4 attenIntensity = atten * lightIntensity;

+ vec3 surfaceNormal = normalize(vertexNormal);

+ float cosAngIncidence = dot(surfaceNormal, lightDir);

+ cosAngIncidence = clamp(cosAngIncidence, 0, 1);

+ vec3 viewDirection = normalize(-cameraSpacePosition);

+ vec3 halfAngle = normalize(lightDir + viewDirection);

+ float blinnTerm = dot(surfaceNormal, halfAngle);

+ blinnTerm = clamp(blinnTerm, 0, 1);

+ blinnTerm = cosAngIncidence != 0.0 ? blinnTerm : 0.0;

+ blinnTerm = pow(blinnTerm, shininessFactor);

+ outputColor = (diffuseColor * attenIntensity * cosAngIncidence) +

+ (specularColor * attenIntensity * blinnTerm) +

+ (diffuseColor * ambientIntensity);</programlisting>

+ <para>The half-angle vector is computed by normalizing the sum of the light direction and

+ view direction vectors. As before, we take the dot product between that and the surface

+ normal, clamp, then raise the result to a power.</para>

+ <para>Blinn specular solves the Phong problem with the reflection direction.</para>

+ <!--TODO: Picture comparing Phong and Blinn with same light positions and low shininess.-->

+ <para>The Blinn specular exponent does not mean quite the same thing as the Phong exponent.

+ In general, to produce a highlight the same size as a Phong one, you will need a larger

+ Blinn exponent. Play around with the different exponents, to get a feel for what Blinn

+ and Phong can and cannot achieve.</para>

+ <title>Gaussian</title>

+ <para>Phong and Blinn are nice toy heuristics that take relatively little computational

+ power. But if you're truly serious about computing specular highlights, you need a model

+ that actually <emphasis>models</emphasis> microfacets.</para>

+ <para>Real microfacet models are primarily based on the answer to the question <quote>What

+ proportion of the microfacets of this surface are oriented in such a way as to

+ specularly reflect light towards the viewer?</quote> The greater the proportion of

+ properly oriented microfacets, the stronger the reflected light. This question is

+ ultimately one of statistics.</para>

+ <para>Thus it makes sense to model this as a probability distribution. We know that the

+ average microfacet orientation is the surface normal. So it's just a matter of

+ developing a probability distribution function that says what portion of the surface's

+ microfacets are oriented to provide specular reflections given the light direction and

+ the view direction.</para>

+ <para>In statistics, the very first place you go for modelling anything with a probability

+ distribution is to the <glossterm>normal distribtuion</glossterm> or <glossterm>Gaussian

+ distribution.</glossterm> It may not be the correct distribution that physically

+ models what the microfacet distribution of a surface looks like, but it's usually a good

+ <para>The Gaussian distribution is the classic <quote>bell-shaped curve</quote>

+ distribution. The mathematical function for computing the probability density of the

+ Gaussian distribution at a particular point X is:</para>

+ <!--TODO: Equation for Gaussian distribution.-->

+ <!--TODO: Picture of Gaussian curve.-->

+ <para>This represents the percentage of the items in the distribution that satisfy the

+ property that the X in the distribution is trying to model. The <literal>e</literal> in

+ this equation is a common mathematical constant, equivalent to ~2.718.The value of

+ <varname>μ</varname> is the average. So the absolute value of X is not important;

+ what matters is how far X is from the average.</para>

+ <para>The value <varname>σ<superscript>2</superscript></varname> is the variance of the

+ Gaussian distribution. Without getting too technical, the larger this value becomes, the

+ flatter and wider the distribution is. The variance specifies how far from the average

+ you can get to achieve a certain probability density. The area of the distribution that

+ is positive and negative <varname>σ</varname> away from the average takes up ~68% of the

+ possible values. The area that is 2<varname>σ</varname> away represents ~95% of the

+ possible values.</para>

+ <para>We know what the average is for us: the surface normal. We can incorporate what we

+ learned from Blinn, by measuring the distance from perfect reflection by comparing the

+ surface normal to the half-angle vector. Thus, the X values represents the angle between

+ the surface normal and half-angle vector. The value <varname>μ</varname>, the average,

+ <para>The equation we will be using for modelling the microfacet distribution with a

+ Gaussian distribution is a slightly simplified form of the Gaussian distribution

+ <!--TODO: Equation for Guassian lighting distribution.-->

+ <para>This replaces our Phong and Blinn terms in our specular lighting equation and gives us

+ the <glossterm>Gaussian specular model</glossterm>. The value <varname>m</varname>

+ ranges from (0, 1], with larger values representing an increasingly rougher surface.

+ Technically, you can use values larger than 1, but the results begin looking

+ increasingly less useful. A value of 1 is plenty rough enough for specular reflection;

+ properly modelling extremely rough surfaces requires additional computations besides

+ determining the distribution of microfacets.</para>

+ <para>The <phrase>Gaussian Specular Lighting</phrase> tutorial shows an implementation of

+ Gaussian specular. It allows a comparison between Phong, Blinn, and Gaussian. It

+ controls the same as the previous tutorial, with the <keycap>H</keycap> key switching

+ between the three specular computations, and the <keycombo>

+ </keycombo> switching between diffuse+specular and specular only.</para>

+ <para>Here is the fragment shader for doing Gaussian lighting.</para>

+ <title>Gaussian Lighting Shader</title>

+ <programlisting language="glsl">vec3 lightDir = vec3(0.0);

+float atten = CalcAttenuation(cameraSpacePosition, lightDir);

+vec4 attenIntensity = atten * lightIntensity;

+vec3 surfaceNormal = normalize(vertexNormal);

+float cosAngIncidence = dot(surfaceNormal, lightDir);

+cosAngIncidence = clamp(cosAngIncidence, 0, 1);

+vec3 viewDirection = normalize(-cameraSpacePosition);

+vec3 halfAngle = normalize(lightDir + viewDirection);

+float angleNormalHalf = acos(dot(halfAngle, surfaceNormal));

+float exponent = angleNormalHalf / shininessFactor;

+exponent = -(exponent * exponent);

+float gaussianTerm = exp(exponent);

+gaussianTerm = cosAngIncidence != 0.0 ? gaussianTerm : 0.0;

+outputColor = (diffuseColor * attenIntensity * cosAngIncidence) +

+ (specularColor * attenIntensity * gaussianTerm) +

+ (diffuseColor * ambientIntensity);</programlisting>

+ <para>Computing the angle between the half-angle vector and the surface normal requires the

+ use of the <function>acos</function> function. We use the dot-product to compute the

+ cosine of the angle, so we need a function to undo the cosine operation. The

+ <glossterm>arc cosine</glossterm> or <glossterm>inverse cosine</glossterm> function

+ takes the result of a cosine and returns the angle that produced that value.</para>

+ <para>To do the exponentiation, we use the <function>exp</function> function. This function

+ raises the constant <literal>e</literal> to the power of the argument. Everything else

+ proceeds as expected.</para>

+ <title>What Gaussian Offers</title>

+ <para>If you play around with the controls, you can see how much the Gaussian

+ distribution offers over Phong and Blinn. For example, set the Gaussian smoothness

+ <!--TODO: Show a picture of a Gaussian highlight with smoothness at 0.05-->

+ <para>It requires very large exponents, well in excess of 100, to match the small size

+ and focus of that specular highlight with Phong or Blinn. It takes even larger

+ exponents to match the Gaussian value of 0.02.</para>

+ <para>Otherwise the differences between Gaussian and Blinn are fairly subtle. For rough

+ surfaces, there is little substantive difference. But Gaussian tends to have a

+ sharper, more distinct highlight for shiny surfaces.</para>

+ <title>On Performance</title>

+ <para>The three specular highlight models seen here are obviously more computationally

+ expensive than diffuse lighting. But which is ultimately more expensive than the

+ <para>The difference between Phong and Blinn is that Phong must compute the reflection

+ vector, while Blinn computes the half-angle vector. The equation for computing the

+ reflection vector is:</para>

+ <!--TODO: Show the reflection vector equation again-->

+ <para>This involves a vector dot product, a scalar multiply, a vector-scalar multiply, and a

+ vector addition (subtraction). Computing the half-angle vector requires doing a vector

+ addition and performing a normalize operation. Normalizing a vector requires a vector

+ dot product (dotting the vector with itself), taking the square-root of that value, and

+ then a vector-scalar divide by that value.</para>

+ <para>Time once was that it was easy to know what was faster. The presence of a square-root

+ operation alone would have condemned Blinn as the slower method. On modern 3D graphics

+ hardware however, taking the reciprocal square-root (1 / √X) is generally about as fast

+ as doing a vector multiply. This puts Blinn as approximately equal in performance to

+ Phong; on some hardware, it may even be faster. In general, the performance difference

+ between the two will be negligable.</para>

+ <para>Gaussian is a different story. It would be reasonable to expect the

+ <function>pow</function> function, taking <inlineequation>

+ <mathphrase>x<superscript>y</superscript></mathphrase>

+ </inlineequation> for arbitrary values, to be slower than executing

+ <function>exp</function>, <inlineequation>

+ <mathphrase>e<superscript>x</superscript></mathphrase>

+ </inlineequation>. They might have the same performance, but if one is going to be

+ faster, it is more likely to be <function>exp</function> than <function>pow</function>.

+ However, Gaussian also uses the inverse cosine; that pretty much negates any possibility

+ of performance parity. The inverse cosine computation is certainly not built into the

+ hardware, and thus must be computed using the shader logic. And while this is likely

+ true of exponentiation and power functions, Gaussian has to do <emphasis>two</emphasis>

+ of these operations, compared to just one for Phong or Blinn.</para>

+ <para>One might consider using Gouraud shading with specular reflections as a method of

+ optimization. This is not for the best. Specular highlights do not interpolate linearly

+ at all, so unless the mesh is finely divided, it will generally look awful.</para>

<?dbhtml filename="Tut10 In Review.html" ?>

<para>In this tutorial, you have learned the following:</para>

+ <para>Specular lighting represents direct, mirror-like reflections from a surface.

+ Specular highlights are mirror-like reflections directly from a light source.

+ Adding weak specular highlights to even rough surfaces can increase visual

+ <para>The microfacet model of specular reflection means that, for a given surface

+ area, there are many mirror-like surfaces. Each microfacet reflects perfectly in

+ its direction. The average of the microfacets </para>

+ <para>The Phong and Blinn models of specular reflection use a power function based

+ on how close the viewer is to perfect reflection to approximate a microfacet

+ <para>A Gaussian statistical distribution can be used to more accurately model the

+ distributions of microfacets on a surface.</para>

<para>Try doing these things with the given programs.</para>

+ <para>Change the shaders to use the diffuse color as the specular color. You may

+ need to drop the specular color somewhat to keep from over-brightening the

+ scene. How this all looks will be particularly evident with the colored

+ <title>Further Research</title>

+ <para>As you might guess, this is far from the end on specular reflections and specular

+ highlights. Accurately modelling specular reflection is very difficult; doing so

+ while maintaining high performance is even moreso.</para>

+ <para>If you are interested in more accurate models of specular highlights, there is the

+ Beckmann distribution. This is a particular statistical distribution of microfacets

+ that is more physically based than a Gaussian distribution. It may be a bit more

+ computationally expensive than Gaussian (due to being able to avoid the

+ <function>acos</function>). The two do have a roughness factor that has the same

+ <para>If you want to go even farther, investigate the <quote>Cook-Torrance</quote> model

+ of specular reflection. It incorporates several terms. It uses a statistical

+ distribution to determine the number of microfacets oriented in a direction. This

+ distribution can be Gaussian, Beckmann, or some other distribution. It modifies this

+ result based on a geometric component that models microfacet self-shadowing and the

+ possibility for multiple interreflections among a microfaceted surface. And it adds

+ a term to compensate for the Fresnel effect: an effect where specular reflection

+ from a surface is more intense when viewed edge-on than directly top-down.</para>

<title>GLSL Functions of Note</title>

+ <funcdef>vec <function>reflect</function></funcdef>

+ <paramdef>vec <parameter>I</parameter></paramdef>

+ <paramdef>vec <parameter>N</parameter></paramdef>

+ <para>Computes the vector that would be reflected across the normal <varname>N</varname>

+ from an incident vector <varname>I</varname>. The vector result will be normalized

+ if the input vectors are normalized. Note that <varname>I</varname> vector is the

+ vector <emphasis>towards</emphasis> the surface.</para>

+ <funcdef>vec <function>pow</function></funcdef>

+ <paramdef>vec <parameter>X</parameter></paramdef>

+ <paramdef>vec <parameter>Y</parameter></paramdef>

+ <para>Raises <varname>X</varname> to the power of <varname>Y</varname>, component-wise.

+ If a component of <varname>X</varname> is less than 0, then the resulting value is

+ undefined. If <varname>X</varname> is exactly zero, and <varname>Y</varname> is less

+ than or equal to 0, then the resulting value is undefined.</para>

+ <funcdef>vec <function>acos</function></funcdef>

+ <paramdef>vec <parameter>X</parameter></paramdef>

+ <para>Returns the inverse cosine of <varname>X</varname>, component-wise. This returns

+ the angle in radians, which is on the range [0, π]. If any component of

+ <varname>X</varname> is outside of the [-1, 1] range, then that component of the

+ result will be undefined. This is because the cosine of a value is always on [-1,

+ 1], so the inverse-cosine function cannot take values outside of this range.</para>

+ <funcdef>vec <function>exp</function></funcdef>

+ <paramdef>vec <parameter>exponent</parameter></paramdef>

+ <para>Returns the value of <inlineequation>

+ <mathphrase>e<superscript>exponent</superscript></mathphrase>

+ </inlineequation>, component-wise.</para>

+ <glossterm>specular reflection</glossterm>

+ <para>A mirror-like reflection of light from a surface. Specular reflections

+ reflect light; thus, the color the viewer sees is strongly based on the view

+ angle relative to the light. Specular reflections often do not affect the

+ color of the incoming light.</para>

+ <glossterm>specular highlights</glossterm>

+ <para>Mirror-like reflections directly from light sources. Since light sources

+ are brighter than light reflected by other objects, modelling only specular

+ highlights can provide useful realism without having to model reflections

+ from light produced by other objects in the scene.</para>

+ <glossterm>angle of view, viewing angle</glossterm>

+ <para>The angle between the surface normal and the direction to the

+ <glossterm>microfacet model</glossterm>

+ <para>Describes a surface as a number of flat planes called microfacets. Each

+ microfacet reflects light using a simple lighting model. The light from a

+ portion of the surface is simply the aggregate of the light from all of the

+ microfacets of the surface. The statistical distribution of microfacet

+ directions on a surface becomes an integral part of the lighting equation.

+ The normal of a surface at a point is the average normal of the microfacets

+ of that part of the surface.</para>

+ <para>The microfacet model can be used to model the reflectance characteristics

+ of rough surfaces.</para>

+ <glossterm>Phong specular model</glossterm>

+ <para>A simple model for creating specular highlights. It uses a power function

+ to determine the distribution of microfacets of the surface. The base of the

+ power function is the cosine of the angle between the view direction and the

+ direction of perfect reflection along the surface normal. The exponent is an

+ arbitrary value on the range (0, ∞); large values describe increasingly

+ shiny surfaces, while small values are for rough surfaces.</para>

+ <glossterm>half-angle vector</glossterm>

+ <para>The vector halfway between the direction towards the light and the view

+ direction. When the half-angle vector is oriented exactly with the surface

+ normal, then the view direction is oriented along the reflection

+ <glossterm>Blinn-Phong specular model</glossterm>

+ <para>A simple model for creating specular highlights. Like standard Phong, it

+ uses a power function to model the distribution of microfacets. The base of

+ the power function is the cosine of the angle between the half-angle vector

+ and the surface normal. The exponent is an arbitrary value on the range (0,

+ ∞); large values describe increasingly shiny surfaces, while small values

+ are for rough surfaces.</para>

+ <glossterm>Gaussian distribution, normal distribution</glossterm>

+ <para>A common statistical distribution. It defines the familiar

+ <quote>bell-shaped curve,</quote> with the average value at the highest

+ point of the distribution.</para>

+ <glossterm>Gaussian specular model</glossterm>

+ <para>A model for creating specular highlights. It uses the Gaussian

+ distribution to model the distribution of microfacets on a surface. It uses

+ a value to control the distribution; this value ranges on (0, 1], where

+ small numbers are smooth surfaces and large numbers are rough

+ <glossterm>inverse cosine, arc cosine</glossterm>

+ <para>Performs the opposite of the cosine function. The cosine function takes

+ angles and returns a value on the range (-1, 1). The inverse cosine takes

+ values on the range (-1, 1) and returns an angle in radians.</para>