Graphics Reference
In-Depth Information
To specify the vertical field of view instead of the horizontal one, replace
fieldOfViewX with fieldOfViewY and insert the line s /= aspect .
15.4.1.1 Camera Design Notes
The C++ language offers both functions and methods as procedural abstractions.
We have presented computeEyeRay as a function that takes a Camera parameter
to distinguish the “support code” Camera class from the ray-tracer-specific code
that you are adding. As you move forward through the topic, consider refactoring
the support code to integrate auxiliary functions like this directly into the appro-
priate classes. (If you are using an existing 3D library as support code, it is likely
that the provided camera class already contains such a method. In that case, it is
worth implementing the method once as a function here so that you have the expe-
rience of walking through and debugging the routine. You can later discard your
version in favor of a canonical one once you've reaped the educational value.)
A software engineering tip: Although we have chosen to forgo small optimiza-
tions, it is still important to be careful to use references (e.g., Image& ) to avoid
excess copying of arguments and intermediate results. There are two related rea-
sons for this, and neither is about the performance of this program.
The first reason is that we want to be in the habit of avoiding excessive copy-
ing. A Vector3 occupies 12 bytes of memory, but a full-screen Image is a few
megabytes. If we're conscientious about never copying data unless we want copy
semantics, then we won't later accidentally copy an Image or other large struc-
ture. Memory allocation and copy operations can be surprisingly slow and will
bloat the memory footprint of our program. The time cost of copying data isn't
just a constant overhead factor on performance. Copying the image once per pixel,
in the inner loop, would change the ray caster's asymptotic run time from O( n ) in
the number of pixels to O( n 2 ) .
The second reason is that experienced programmers rely on a set of idioms
that are chosen to avoid bugs. Any deviation from those attracts attention, because
it is a potential bug. One such convention in C++ is to pass each value as a const
reference unless otherwise required, for the long-term performance reasons just
described. So code that doesn't do so takes longer for an experienced programmer
to review because of the need to check that there isn't an error or performance
implication whenever an idiom is not followed. If you are an experienced C++
programmer, then such idioms help you to read the code. If you are not, then either
ignore all the ampersands and treat this as pseudocode, or use it as an opportunity
to become a better C++ programmer.
15.4.1.2 Testing the Eye-Ray Computation
We need to test computeEyeRay before continuing. One way to do this is to write
a unit test that computes the eye rays for specific pixels and then compares them
to manually computed results. That is always a good testing strategy. In addition
to that, we can visualize the eye rays. Visualization is a good way to quickly see
the result of many computations. It allows us to more intuitively check results, and
to identify patterns of errors if they do not match what we expected.
In this section, we'll visualize the directions of the rays. The same process can
be applied to the origins. The directions are the more common location for an error
and conveniently have a bounded range, which make them both more important
and easier to visualize.
 
Search WWH ::




Custom Search