Graphics Reference
In-Depth Information
In our implementation, the line-of-sight visibility test is performed by the
visible function, which is supposed to return true if and only if there is an
unoccluded line of sight. While working on the shading routine we temporarily
implemented visible to always return true , which means that our images con-
tain no shadows. We now revisit the visible function in order to implement
shadows.
We already have a powerful tool for evaluating line of sight: the intersect
function. The light source is not visible from P if there is some intersection with
another triangle. So we can test visibility simply by iterating over the scene again,
this time using the shadow ray from P to the light instead of from the camera to
P . Of course, we could also test rays from the light to P .
Listing 15.20 shows the implementation of visible . The structure is very
similar to that of sampleRayTriangle . It has three major differences in the
details. First, instead of shading the intersection, if we find any intersection we
immediately return false for the visibility test. Second, instead of casting rays
an infinite distance, we terminate when they have passed the light source. That is
because we don't care about triangles past the light—they could not possibly cast
shadows on P . Third and finally, we don't really start our shadow ray cast at P .
Instead, we offset it slightly along the ray direction. This prevents the ray from
reintersecting the surface containing P as soon as it is cast.
Listing 15.20: Line-of-sight visibility test, to be applied
to shadow determination.
1
bool visible( const Vector3 &P, const Vector3 & direction, float
distance, const Scene & scene){
static const float rayBumpEpsilon = 1e-4;
const Ray shadowRay(P + direction * rayBumpEpsilon, direction);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
distance -= rayBumpEpsilon;
// Test each potential shadow caster to see if it lies between P and the light
float ignore[3];
for ( unsigned int s = 0; s < scene.triangleArray.size(); ++s) {
if (intersect(shadowRay, scene.triangleArray[s], ignore) < distance) {
// This triangle is closer than the light
return false ;
}
}
return true ;
}
Our single-triangle scene is insufficient for testing shadows. We require one
object to cast shadows and another to receive them. A simple extension is to add
a quadrilateral “ground plane” onto which the green triangle will cast its shadow.
Listing 15.21 gives code to create this scene. Note that this code also adds another
triangle with the same vertices as the green one but the opposite winding order.
Because our triangles are single-sided, the green triangle would not cast a shadow.
We need to add the back of that surface, which will occlude the rays cast upward
toward the light from the ground.
Figure 15.9: The green trian-
gle scene extended with a two-
triangle gray ground “plane.” A
back surface has also been added
to the green triangle.
Inline Exercise 15.7: Walk through the intersection code to verify the claim
that without the second “side,” the green triangle would cast no shadow.
 
Search WWH ::




Custom Search