### Recent Announcements for Project 4

• Diffuse Lighting Fix

If you perform diffuse lighting on a red sphere, the hemisphere where the
light is shining should appear to be a more well-lit red, instead of white
(specular highlights are white).  If diffuse lighting is not looking
correct, try adding the color of the material as a multiplicative factor
to the diffuse calculation.  You can do this by changing:

Color = summation( Kd * Ci * (Li dot N) )

...to:

Color = summation( Kd * Cm * Ci * (Li dot N) )

Kd is the diffuse coefficient, Cm is the color of the material, Ci is the
color of the light i , Li is the unit light vector to light i, and N is
the unit normal.
•
• Shadow Ray Floating Point Errors

One issue with computing shadow rays is that you may get a false
intersection hit when you test a shadow ray.  When you generate a shadow
ray coming from, say, the surface of a sphere, and you test if the ray
intersects an object, floating point error may result in your code
computing an intersection for the very sphere you started at.

You'll notice this error if see surfaces that should be well-lit, but they
are peppered with black dots of shadow.  The floating point error in the
shadow test causes some of the shadow rays to intersect with the sphere
itself even though they shouldn't, which then creates these black dots.

To fix this error, the most robust solution is to actually move the shadow
ray out a little from the point of intersection along the direction of the
ray, to get out of the range of floating point imprecision.  For instance,

r(t) = P0 + t * dir

...you can transform it to:
r'(t) = P1 + t * dir
...where...
P1 = P0 + EPSILON * dir
EPSILON = a very small, positive float, like 0.001, (a global constant)

This floating point error applies not only to shadow rays, but also to
reflection and refraction rays, which will need to be similarly
moved by EPSILON along their directions.
•
• Ray Data Structure

Clearing up a point of confusion, the two fields of a ray struct in the
starter code are (point start, point end), which is really a point
followed by a direction.  In other words,

point start - a POINT, it is the point that the way starts at, w = 1.0
point end - a VECTOR, it is the direction that the ray is pointing in, w = 0.0
•
• Correction to raytrace.pdf

In the pseudocode in raytrace.pdf (linked from the Project 4 website), the
4th line on the second page reads:

spec := Ks[j] * intensity(flec) * (r.V)^ns[j];

There are a few things wrong with this line.  First, to clarify what (r.V)
is, 'r' should be the unit vector Ri, the reflection of Li (the light
vector for light i) about the normal.  'V' is correct, meaning it is the
unit viewer vector.  Also, since Ri exists for each light, we need to sum
it over all lights.

Finally, the multiplcation sign between intensity(flec) and [the dot
product with a power] should instead be an add sign.  Since one of these
terms calculatates global reflection color while the other term calculates
local specular highlights and they are independent, we need an add rather
than a multiply.

So, the corrected line should read:

spec := Ks[j] * ( intensity(flec) + summation_i { (Ri.V)^ns[j] } );

Also note that instead of (Ri.V), you can use the half vector dotted with
the normal, (Hi.N).  To get the right effects, you may also want to break
the specular coefficient Ks[j] down into two nonequal coefficients, one
multiplying the global reflection ray intensity only and the other
multiplying the sum of the specular highlights only.