Graphics Reference
In-Depth Information
on the surface of the glass sphere, but that there was no sign of any transmitted
light. There are many possible problems. Maybe the surface element's method for
returning all BSDF impulses is failing to return the transmissive ray. Maybe every
transmitted ray is somehow suffering total internal reflection. Maybe the number
of bounces is being truncated at two, and since light would have to bounce off the
back wall, then through two air-glass interfaces, and to the eye, we're never seeing
it. How should you debug?
First, it's very useful to be able to trace a single ray, using the pixel coordinates
as arguments, as in pathTrace(int x, int y) . You can identify a single pixel
in which the sphere is visible, add code to path-trace that one pixel, and use a
debugger to stop in that code at the first intersection. You check the number of
impulses returned, and find that there are two. One has a positive z -component
(it's a reflection back somewhat toward the eye), and the other has a negative
z -component (it's transmission into the sphere). (Here you can see the advantage
of having a view that looks along the z -axis, at least in your test program.)
Second, continuing your debugging, following that second impulse, you find
that it does, in fact, intersect the green glass sphere a second time. Multiple scat-
tering seems to be working fine. But the second intersection is surprisingly near
the first one—all three coordinates are almost the same. If you chose, as your ( x , y )
pixel, one that shows a point near the center of the sphere's image in the picture,
then you'd expect the first and second intersections to be on the front and then the
back of the sphere, nearly a diameter apart. What's wrong?
Once again, the problem has to do with bumping. It's true that the transmitted
ray needs to be bumped in the direction of the surface normal, but it needs its
starting point to be bumped into the sphere rather than out of it. To determine
which way a ray should be bumped, we need to know which side of the surface it's
on. That gets tested with a dot product between the ray direction and the surface
normal. If your scattering code says
1
2
Ray r(surfel.geometric.location, impulse.w);
r = r.bumpedRay(0.0001f, surfel.geometric.normal);
then every recursive ray will be bumped toward the exterior of the sphere. Instead,
you need to write:
1
2
3
4
Ray r(surfel.geometric.location, impulse.w);
r = r.bumpedRay(0.0001f *
sign(surfel.geometric.normal.dot(r.direction())),
surfel.geometric.normal);
In general, debugging by following rays is quite difficult. It helps to have
scenes in which things are simple. A scene with one plane, at z =
20, and one
sphere, of radius 10, centered at the origin, is easy to work with: Whenever you
have a ray-scene intersection, it's obvious which surface you're on, and if your
intersection point doesn't have z =
20, it's easy to mentally add up x 2 + y 2 + z 2
to see whether it's approximately 10. It's even better to have scenes so simple that
you know the exact answer you expect to get at any point. That's why, for instance,
our fourth scene consists of an area light that's completely absorptive, and a mirror
(we added the frame to the mirror to make the scene a little easier to understand
visually, but removed it during debugging). An eye ray is going to hit the light (for
which the computed radiance back along the ray will be the emitted radiance of
the light) or miss the scene completely, or hit the mirror, from which it will reflect
 
 
Search WWH ::




Custom Search