Graphics Reference
In-Depth Information
A natural scheme for visualizing a direction is to interpret the
(
x
,
y
,
z
)
fields as
(
r
,
g
,
b
)
color triplets. The conversion of ray direction to pixel color is of course a
gross violation of units, but it is a really useful debugging technique and we aren't
expecting anything principled here anyway.
Because each ordinate is on the interval
[
−
1, 1
]
, we rescale them to the range
[
0, 1
]
by
r
=(
x
+
1
)
2. Our image display routines also apply an exposure func-
tion, so we need to scale the resultant intensity down by a constant on the order of
the inverse of the exposure value. Temporarily inserting the following line:
/
image.set(x, y, Color3(R.direction() + Vector3(1, 1, 1)) / 5);
into
rayTrace
in place of the
sampleRayTriangle
call should yield an image
like that shown in Figure 15.4. (The factor of 1
5 scales the debugging values to a
reasonable range for our output, which was originally calibrated for radiance; we
found a usable constant for this particular example by trial and error.) We expect
the
x
-coordinate of the ray, which here is visualized as the color red, to increase
from a minimum on the left to a maximum on the right. Likewise, the (3D)
y
-
coordinate, which is visualized as green, should increase from a minimum at the
bottom of the image to a maximum at the top. If your result varies from this,
examine the pattern you observe and consider what kind of error could produce it.
We will revisit visualization as a debugging technique later in this chapter, when
testing the more complex intersection routine.
/
Figure 15.4: Visualization of eye-
ray directions.
Listing 15.15 shows the code for sampling a triangle with a ray. This code doesn't
perform any of the heavy lifting itself. It just computes the values needed for
intersect
and
shade
.
Listing 15.15: Sampling the intersection and shading of one triangle
with one ray.
1
bool
sampleRayTriangle(
const
Scene
& scene,
int
x,
int
y,
const
Ray
&R,
const
Triangle
&T,
Radiance3
& radiance, float& distance) {
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
float
weight[3];
const float
d = intersect(R, T, weight);
if
(d >= distance) {
return false
;
}
// This intersection is closer than the previous one
distance = d;
// Intersection point
const
Point3
& P = R.origin() + R.direction()
*
d;
// Find the interpolated vertex normal at the intersection
const
Vector3
& n = (T.normal(0)
*
weight[0] +
T.normal(1)
*
weight[1] +
T.normal(2)
*
weight[2]).direction();
const
Vector3
& w_o = -R.direction();