i
i
i
i
i
i
i
i
4.8. Ideal Specular Reflection 87
Figure 4.18. By testing
in the interval starting at ,
we avoid numerical impre-
cision causing the ray to hit
the surface p is on.
function raycolor( ray e + td, real t
0
, real t
1
)
hit-record rec, srec
if (scene→hit(e + td, t
0
, t
1
,rec)) then
p = e +(rec.t) d
color c = rec.k
a
I
a
if (not scene→hit(p + sl, , ∞,srec)) then
vector3 h = normalized(normalized(l)+normalized(−d))
c = c + rec.k
d
I max(0, rec.n ·l)+(rec.k
s
) I (rec.n · h)
rec.p
return c
else
return background-color
Note that the ambient color is added whether p is in shadow or not. If there are
multiple light sources, we can send a shadow ray before evaluating the shading
model for each light. The code above assumes that d and l are not necessarily unit
vectors. This is crucial for d, in particular, if we wish to cleanly add instancing
later (see Section 13.2).
4.8 Ideal Specular Reflection
Figure 4.19. When look-
ing into a perfect mirror, the
viewer looking in direction d
will see whatever the viewer
“below” the surface would
see in direction r.
It is straightforward to add ideal specular reflection, or mirror reflection,toaray-
tracing program. The key observation is shown in Figure 4.19 where a viewer
looking from direction e sees what is in direction r as seen from the surface. The
vector r is found using a variant of the Phong lighting reflection Equation (10.6).
There are sign changes because the vector d points toward the surface in this case,
so,
r = d − 2(d · n)n, (4.5)
In the real world, some energy is lost when the light reflects from the surface, and
this loss can be different for different colors. For example, gold reflects yellow
more efficiently than blue, so it shifts the colors of the objects it reflects. This can
be implemented by adding a recursive call in raycolor:
Figure 4.20. Asimple
scene rendered with diffuse
and Blinn-Phong shading,
shadows from three light
sources, and specular re-
flection from the floor.
color c = c + k
m
raycolor(p + sr, , ∞)
where k
m
(for “mirror reflection”) is the specular RGB color. We need to make
sure we test for s ∈ [, ∞) for the same reason as we did with shadow rays; we
don’t want the reflection ray to hit the object that generates it.
The problem with the recursive call above is that it may never terminate. For
example, if a ray starts inside a room, it will bounce forever. This can be fixed by