Graphics Reference
In-Depth Information
Figure 15.3. The figure is a top view of the scene in which
x
increases to the right
and
z
increases downward. The near plane appears as a horizontal line, and the
start
point is on that plane, along the line from the camera at the origin to the
center of a specific pixel.
To implement this function we needed to parameterize the camera by either the
image plane depth or the desired field of view. Field of view is a more intuitive way
to specify a camera, so we previously chose that parameterization when building
the scene representation.
Listing 15.14: Computing the ray through the center of pixel
(
x
,
y
)
on a
width
×
height
image.
1
2
3
4
5
6
7
8
9
10
11
12
13
Ray
computeEyeRay(
float
x,
float
y,
int
width,
int
height,
const
Camera
& camera) {
const float
aspect = float(height) / width;
// Compute the side of a square at z = -1 based on our
// horizontal left-edge-to-right-edge field of view
const float
s = -2.0f
*
tan(camera.fieldOfViewX
*
0.5f);
const
Vector3
& start =
Vector3
( (x / width - 0.5f)
*
s,
-(y / height - 0.5f)
*
s
*
aspect, 1.0f)
*
camera.zNear;
return
Ray
(start, start.direction());
}
We choose to place the ray origin on the near (sometimes called hither) clip-
ping plane, at
z
=
camera.zNear
. We could start rays at the origin instead of the
near plane, but starting at the near plane will make it easier for results to line up
precisely with our rasterizer later.
The ray direction is the direction from the center of projection (which is
at the origin,
(
0, 0, 0
)
)totheray
start
point, so we simply normalize
start
point.
width
Start
z
5
zNear
Inline Exercise 15.6:
By the rules of Chapter 7, we should compute the ray
direction as
(start - Vector3(0,0,0)).direction()
. That makes the
camera position explicit, so we are less likely to introduce a bug if we later
change the camera. This arises simply from strongly typing the code to match
the underlying mathematical types. On the other hand, our code is going to be
full of lines like this, and consistently applying correct typing might lead to
more harm from obscuring the algorithm than benefit from occasionally find-
ing an error. It is a matter of personal taste and experience (we can somewhat
reconcile our typing with the math by claiming that
P.direction()
on a
point
P
returns the direction to the point, rather than “normalizing” the point).
Rewrite
computeEyeRay
using the distinct
Point
and
Vector
abstrac-
tions from Chapter 7 to get a feel for how this affects the presentation and
correctness. If this inspires you, it's quite reasonable to restructure all the code
in this chapter that way, and doing so is a valuable exercise.
Field of
view
Camera
x
(0,0,0)
z
Figure 15.3: The ray through a
pixel center in terms of the image
resolution and the camera's hori-
zontal field of view.
Note that the
y
-coordinate of the
start
is negated. This is because
y
is in 2D
screen space, with a “
y
=
down” convention, and the ray is in a 3D coordinate
system with a “
y
=
up” convention.