Skip to content

Commit 3aa101c

Browse files
committed
Revisions from PR commentary
1 parent 7e94361 commit 3aa101c

File tree

3 files changed

+89
-87
lines changed

3 files changed

+89
-87
lines changed

books/RayTracingInOneWeekend.html

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
don’t need to. However, I suggest you do, because it’s fast, portable, and most production movie and
3434
video game renderers are written in C++. Note that I avoid most “modern features” of C++, but
3535
inheritance and operator overloading are too useful for ray tracers to pass on. I do not provide the
36-
code online, but the code is real, and I show all of it except for a few straightforward operators
37-
in the `vec3` class. I am a big believer in typing in code to learn it, but when code is available I
36+
code online, but the code is real and I show all of it except for a few straightforward operators in
37+
the `vec3` class. I am a big believer in typing in code to learn it, but when code is available I
3838
use it, so I only practice what I preach when the code is not available. So don’t ask!
3939

4040
I have left that last part in because it is funny what a 180 I have done. Several readers ended up
@@ -64,7 +64,7 @@
6464
====================================================================================================
6565

6666
Whenever you start a renderer, you need a way to see an image. The most straightforward way is to
67-
write it to a file. The catch is, there are so many formats, and many of those are complex. I always
67+
write it to a file. The catch is, there are so many formats. Many of those are complex. I always
6868
start with a plain text ppm file. Here’s a nice description from Wikipedia:
6969

7070
![](../images/img.ppm-example.jpg)
@@ -140,7 +140,7 @@
140140

141141
<div class='together'>
142142
Hooray! This is the graphics “hello world”. If your image doesn’t look like that, open the output
143-
file in a text editor, and see what it looks like. It should start something like this:
143+
file in a text editor and see what it looks like. It should start something like this:
144144

145145
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
146146
P3
@@ -171,7 +171,7 @@
171171
loop or other problem.
172172

173173
<div class='together'>
174-
Our program outputs the image to the standard output stream (`std::cout`), so leave that alone, and
174+
Our program outputs the image to the standard output stream (`std::cout`), so leave that alone and
175175
instead write to the error output stream (`std::cerr`):
176176

177177
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
@@ -355,9 +355,9 @@
355355
====================================================================================================
356356

357357
<div class='together'>
358-
The one thing that all ray tracers have is a ray class, and a computation of what color is seen
359-
along a ray. Let’s think of a ray as a function $\mathbf{p}(t) = \mathbf{a} + t \vec{\mathbf{b}}$.
360-
Here $\mathbf{p}$ is a 3D position along a line in 3D. $\mathbf{a}$ is the ray origin, and
358+
The one thing that all ray tracers have is a ray class and a computation of what color is seen along
359+
a ray. Let’s think of a ray as a function $\mathbf{p}(t) = \mathbf{a} + t \vec{\mathbf{b}}$. Here
360+
$\mathbf{p}$ is a 3D position along a line in 3D. $\mathbf{a}$ is the ray origin, and
361361
$\vec{\mathbf{b}}$ is the ray direction. The ray parameter $t$ is a real number (`double` in the
362362
code). Plug in a different $t$ and $p(t)$ moves the point along the ray. Add in negative $t$ and you
363363
can go anywhere on the 3D line. For positive $t$, you get only the parts in front of $\mathbf{a}$,
@@ -401,7 +401,7 @@
401401
</div>
402402

403403
Now we are ready to turn the corner and make a ray tracer. At the core, the ray tracer sends rays
404-
through pixels, and computes the color seen in the direction of those rays. The involved steps are
404+
through pixels and computes the color seen in the direction of those rays. The involved steps are
405405
(1) calculate the ray from the eye to the pixel, (2) determine which objects the ray intersects, and
406406
(3) compute a color for that intersection point. When first developing a ray tracer, I always do a
407407
simple camera for getting the code up and running. I also make a simple `color(ray)` function that
@@ -535,8 +535,8 @@
535535
</div>
536536

537537
<div class='together'>
538-
The rules of vector algebra are all that we would want here, and if we expand that equation, and
539-
move all the terms to the left hand side we get:
538+
The rules of vector algebra are all that we would want here. If we expand that equation and move all
539+
the terms to the left hand side we get:
540540

541541
$$ t^2 \vec{\mathbf{b}}\cdot\vec{\mathbf{b}}
542542
+ 2t \vec{\mathbf{b}} \cdot \vec{(\mathbf{a}-\mathbf{c})}
@@ -864,11 +864,12 @@
864864
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
865865
[Listing [normals-point-against]: <kbd>[sphere.h]</kbd> Remembering the side of the surface]
866866

867-
The decision whether to have normals always point out or to always point against the ray is based on
868-
whether you want to determine the side of the surface at the time of geometry or at the time of
869-
coloring. In this book we have more material types than we have geometry types, so we'll go for
870-
less work, and put the determination at geometry time. This is simply a matter of preference, and
871-
you'll see both implementations in the literature.
867+
We can set things up so that normals always point “outward” from the surface, or always point
868+
against the incident ray. This decision is determined by whether you want to determine the side of
869+
the surface at the time of geometry intersection or at the time of coloring. In this book we have
870+
more material types than we have geometry types, so we'll go for less work and put the determination
871+
at geometry time. This is simply a matter of preference, and you'll see both implementations in the
872+
literature.
872873

873874
We add the `front_face` bool to the `hit_record` struct. I know that we’ll also want motion blur at
874875
some point, so I’ll also add a time input variable.
@@ -1029,7 +1030,7 @@
10291030

10301031
We'll use shared pointers in our code, because it allows multiple geometries to share a common
10311032
instance (for example, a bunch of spheres that all use the same texture map material), and because
1032-
it makes memory management automatic, and easier to reason about.
1033+
it makes memory management automatic and easier to reason about.
10331034

10341035
`std::shared_ptr` is included with the `<memory>` header.
10351036

@@ -1178,10 +1179,10 @@
11781179

11791180
When a real camera takes a picture, there are usually no jaggies along edges because the edge pixels
11801181
are a blend of some foreground and some background. We can get the same effect by averaging a bunch
1181-
of samples inside each pixel. We will not bother with stratification, which is controversial, but is
1182+
of samples inside each pixel. We will not bother with stratification. This is controversial, but is
11821183
usual for my programs. For some ray tracers it is critical, but the kind of general one we are
1183-
writing doesn’t benefit very much from it, and it makes the code uglier. We abstract the camera
1184-
class a bit so we can make a cooler camera later.
1184+
writing doesn’t benefit very much from it and it makes the code uglier. We abstract the camera class
1185+
a bit so we can make a cooler camera later.
11851186

11861187
One thing we need is a random number generator that returns real random numbers. We need a function
11871188
that returns a canonical random number which by convention returns random real in the range
@@ -1384,7 +1385,7 @@
13841385
ideal diffuse surfaces. (I used to do it as a lazy hack that approximates mathematically ideal
13851386
Lambertian.)
13861387

1387-
(Reader Vassillen Chizhov proved that the lazy hack is indeed just a lazy hack, and is inaccurate.
1388+
(Reader Vassillen Chizhov proved that the lazy hack is indeed just a lazy hack and is inaccurate.
13881389
The correct representation of ideal Lambertian isn't much more work, and is presented at the end of
13891390
the chapter.)
13901391

@@ -1404,7 +1405,7 @@
14041405
<div class='together'>
14051406
We need a way to pick a random point in a unit radius sphere. We’ll use what is usually the easiest
14061407
algorithm: a rejection method. First, pick a random point in the unit cube where x, y, and z all
1407-
range from -1 to +1. Reject this point, and try again if the point is outside the sphere.
1408+
range from -1 to +1. Reject this point and try again if the point is outside the sphere.
14081409

14091410
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
14101411
class vec3 {
@@ -2030,7 +2031,7 @@
20302031
</div>
20312032

20322033
<div class='together'>
2033-
We can also randomize the reflected direction by using a small sphere, and choosing a new endpoint
2034+
We can also randomize the reflected direction by using a small sphere and choosing a new endpoint
20342035
for the ray:
20352036

20362037
![Figure [reflect-fuzzy]: Generating fuzzed reflection rays](../images/fig.reflect-fuzzy.jpg)
@@ -2107,7 +2108,7 @@
21072108

21082109
Is that right? Glass balls look odd in real life. But no, it isn’t right. The world should be
21092110
flipped upside down and no weird black stuff. I just printed out the ray straight through the middle
2110-
of the image, and it was clearly wrong. That often does the job.
2111+
of the image and it was clearly wrong. That often does the job.
21112112

21122113
<div class='together'>
21132114
The refraction is described by Snell’s law:
@@ -2222,7 +2223,7 @@
22222223
$$ \frac{1.5}{1.0} \cdot \sin\theta > 1.0 $$
22232224

22242225
The equality between the two sides of the equation is broken, and a solution cannot exist. If a
2225-
solution does not exist the glass cannot refract, and must reflect the ray:
2226+
solution does not exist, the glass cannot refract, and therefore must reflect the ray:
22262227

22272228
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
22282229
if(etai_over_etat * sin_theta > 1.0) {
@@ -2386,8 +2387,8 @@
23862387

23872388
<div class='together'>
23882389
An interesting and easy trick with dielectric spheres is to note that if you use a negative radius,
2389-
the geometry is unaffected, but the surface normal points inward, so it can be used as a bubble
2390-
to make a hollow glass sphere:
2390+
the geometry is unaffected, but the surface normal points inward. This can be used as a bubble to
2391+
make a hollow glass sphere:
23912392

23922393
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
23932394
world.add(make_shared<sphere>(vec3(0,0,-1), 0.5, make_shared<lambertian>(vec3(0.1, 0.2, 0.5))));
@@ -2507,7 +2508,7 @@
25072508

25082509
Remember that `vup`, `v`, and `w` are all in the same plane. Note that, like before when our fixed
25092510
camera faced -Z, our arbitrary view camera faces -w. And keep in mind that we can -- but we don’t
2510-
have to -- use world up (0,1,0) to specify vup. This is convenient, and will naturally keep your
2511+
have to -- use world up (0,1,0) to specify vup. This is convenient and will naturally keep your
25112512
camera horizontally level until you decide to experiment with crazy camera angles.
25122513

25132514
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
@@ -2606,9 +2607,9 @@
26062607

26072608
<div class="together">
26082609
A real camera has a complicated compound lens. For our code we could simulate the order: sensor,
2609-
then lens, then aperture. Then we could figure out where to send the rays, and flip the image once
2610-
computed (the image is projected upside down on the film). Graphics people usually use a thin lens
2611-
approximation:
2610+
then lens, then aperture. Then we could figure out where to send the rays, and flip the image after
2611+
it's computed (the image is projected upside down on the film). Graphics people, however, usually
2612+
use a thin lens approximation:
26122613

26132614
![Figure [cam-lens]: Camera lens model](../images/fig.cam-lens.jpg)
26142615

@@ -2803,8 +2804,8 @@
28032804
</div>
28042805

28052806
An interesting thing you might note is the glass balls don’t really have shadows which makes them
2806-
look like they are floating. This is not a bug (you don’t see glass balls much in real life, where
2807-
they also look a bit strange, and indeed seem to float on cloudy days). A point on the big sphere
2807+
look like they are floating. This is not a bug -- you don’t see glass balls much in real life, where
2808+
they also look a bit strange, and indeed seem to float on cloudy days. A point on the big sphere
28082809
under a glass ball still has lots of light hitting it because the sky is re-ordered rather than
28092810
blocked.
28102811

books/RayTracingTheNextWeek.html

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@
5151
average answer with a ray that is at exactly a single time. This is fundamentally why random ray
5252
tracing tends to be simple.
5353

54-
The basic idea is to generate rays at random times while the shutter is open, and intersect the
55-
model at that one time. The way it is usually done is to have the camera move and the objects move,
56-
but have each ray exist at exactly one time. This way the “engine” of the ray tracer can just make
57-
sure the objects are where they need to be for the ray, and the intersection guts don’t change much.
54+
The basic idea is to generate rays at random times while the shutter is open and intersect the model
55+
at that one time. The way it is usually done is to have the camera move and the objects move, but
56+
have each ray exist at exactly one time. This way the “engine” of the ray tracer can just make sure
57+
the objects are where they need to be for the ray, and the intersection guts don’t change much.
5858

5959
<div class='together'>
6060
For this we will first need to have a ray store the time it exists at:
@@ -188,10 +188,10 @@
188188
[Listing [moving-sphere]: <kbd>[moving_sphere.h]</kbd> A moving sphere]
189189

190190
<div class='together'>
191-
An alternative to making a new moving sphere class is to just make them all move, and have the
192-
stationary ones have the same begin and end point. I’m on the fence about that trade-off between
193-
fewer classes and more efficient stationary spheres, so let your design taste guide you. The
194-
intersection code barely needs a change: `center` just needs to become a function `center(time)`:
191+
An alternative to making a new moving sphere class is to just make them all move, while stationary
192+
spheres have the same begin and end position. I’m on the fence about that trade-off between fewer
193+
classes and more efficient stationary spheres, so let your design taste guide you. The intersection
194+
code barely needs a change: `center` just needs to become a function `center(time)`:
195195

196196
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
197197
bool moving_sphere::hit(
@@ -266,9 +266,9 @@
266266

267267
<div class='together'>
268268
The code below takes the example diffuse spheres from the scene at the end of the last book, and
269-
makes them move during the image render. (Think of a camera with shutter opening at time 0, and then
270-
closing again at time 1.) Each sphere moves from its center $\mathbf{C}$ at time $t=0$ to
271-
$\mathbf{C} + (0, r/2, 0)$ at time $t=1$, where $r$ is a random number in $[0,1)$:
269+
makes them move during the image render. (Think of a camera with shutter opening at time 0 and
270+
closing at time 1.) Each sphere moves from its center $\mathbf{C}$ at time $t=0$ to $\mathbf{C} +
271+
(0, r/2, 0)$ at time $t=1$, where $r$ is a random number in $[0,1)$:
272272

273273
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
274274
hittable_list random_scene() {
@@ -356,8 +356,8 @@
356356
it a logarithmic search in the spirit of binary search. Because we are sending millions to billions
357357
of rays on the same model, we can do an analog of sorting the model, and then each ray intersection
358358
can be a sublinear search. The two most common families of sorting are to 1) divide the space, and
359-
2) divide the objects. The latter is usually much easier to code up, and just as fast to run for
360-
most models.
359+
2) divide the objects. The latter is usually much easier to code up and just as fast to run for most
360+
models.
361361

362362
<div class='together'>
363363
The key idea of a bounding volume over a set of primitives is to find a volume that fully encloses
@@ -541,7 +541,7 @@
541541
If there are any `NaN`s running around there, the compare will return false so we need to be sure
542542
our bounding boxes have a little padding if we care about grazing cases (and we probably should
543543
because in a ray tracer all cases come up eventually). With all three dimensions in a loop, and
544-
passing in the interval $t_{min}$, $t_{max}$ we get:
544+
passing in the interval $[t_{min}$, $t_{max}]$, we get:
545545

546546
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
547547
#include "rtweekend.h"
@@ -580,9 +580,9 @@
580580
`NaN`s and other exceptions.
581581

582582
<div class='together'>
583-
In reviewing this intersection method, Andrew Kensler at Pixar tried some experiments, and has
584-
proposed this version of the code which works extremely well on many compilers, and I have adopted
585-
it as my go-to method:
583+
In reviewing this intersection method, Andrew Kensler at Pixar tried some experiments and proposed
584+
the following version of the code. It works extremely well on many compilers, and I have adopted it
585+
as my go-to method:
586586

587587
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
588588
inline bool aabb::hit(const ray& r, double tmin, double tmax) const {
@@ -607,8 +607,8 @@
607607
We now need to add a function to compute the bounding boxes of all the hittables. Then we will make
608608
a hierarchy of boxes over all the primitives, and the individual primitives--like spheres--will live
609609
at the leaves. That function returns a bool because not all primitives have bounding boxes (_e.g._,
610-
infinite planes). In addition, objects move so it takes `time1` and `time2` for the interval of the
611-
frame, and the bounding box will bound the object moving through that interval.
610+
infinite planes). In addition, moving objects will have a bounding box that encloses the object for
611+
the entire time interval [`time1`,`time2`].
612612

613613
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
614614
class hittable {
@@ -2114,7 +2114,7 @@
21142114
</div>
21152115

21162116
<div class='together'>
2117-
This is very noisy because the light is small, but we have a problem: some of the walls are facing
2117+
This is very noisy because the light is small. But we have a problem: some of the walls are facing
21182118
the wrong way. We haven't specified that a diffuse material should behave differently on different
21192119
faces of the object, but what if the Cornell box had a different pattern on the inside and outside
21202120
walls? The rectangle objects are described such that their front faces are always in the

0 commit comments

Comments
 (0)