Skip to content

Commit b363815

Browse files
committed
Merge branch 'dev-patch' into dev-minor
2 parents e0a3bd5 + 730c56c commit b363815

File tree

3 files changed

+126
-129
lines changed

3 files changed

+126
-129
lines changed

books/RayTracingInOneWeekend.html

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
====================================================================================================
1818

1919
I’ve taught many graphics classes over the years. Often I do them in ray tracing, because you are
20-
forced to write all the code but you can still get cool images with no API. I decided to adapt my
20+
forced to write all the code, but you can still get cool images with no API. I decided to adapt my
2121
course notes into a how-to, to get you to a cool program as quickly as possible. It will not be a
2222
full-featured ray tracer, but it does have the indirect lighting which has made ray tracing a staple
2323
in movies. Follow these steps, and the architecture of the ray tracer you produce will be good for
@@ -66,7 +66,7 @@
6666
The PPM Image Format
6767
---------------------
6868
Whenever you start a renderer, you need a way to see an image. The most straightforward way is to
69-
write it to a file. The catch is, there are so many formats and many of those are complex. I always
69+
write it to a file. The catch is, there are so many formats. Many of those are complex. I always
7070
start with a plain text ppm file. Here’s a nice description from Wikipedia:
7171

7272
![](../images/img.ppm-example.jpg)
@@ -390,13 +390,13 @@
390390
The ray Class
391391
--------------
392392
<div class='together'>
393-
The one thing that all ray tracers have is a ray class, and a computation of what color is seen
394-
along a ray. Let’s think of a ray as a function $\mathbf{P}(t) = \mathbf{A} + t \mathbf{b}$. Here
393+
The one thing that all ray tracers have is a ray class and a computation of what color is seen along
394+
a ray. Let’s think of a ray as a function $\mathbf{P}(t) = \mathbf{A} + t \mathbf{b}$. Here
395395
$\mathbf{P}$ is a 3D position along a line in 3D. $\mathbf{A}$ is the ray origin and $\mathbf{b}$ is
396396
the ray direction. The ray parameter $t$ is a real number (`double` in the code). Plug in a
397-
different $t$ and $\mathbf{P}(t)$ moves the point along the ray. Add in negative $t$ and you can go
398-
anywhere on the 3D line. For positive $t$, you get only the parts in front of $\mathbf{A}$, and this
399-
is what is often called a half-line or ray.
397+
different $t$ and $\mathbf{P}(t)$ moves the point along the ray. Add in negative $t$ values and you
398+
can go anywhere on the 3D line. For positive $t$, you get only the parts in front of $\mathbf{A}$,
399+
and this is what is often called a half-line or ray.
400400

401401
![Figure [lerp]: Linear interpolation](../images/fig.lerp.jpg)
402402

@@ -449,7 +449,7 @@
449449
often, so I’ll stick with a 200×100 image. I’ll put the “eye” (or camera center if you think of a
450450
camera) at $(0,0,0)$. I will have the y-axis go up, and the x-axis to the right. In order to respect
451451
the convention of a right handed coordinate system, into the screen is the negative z-axis. I will
452-
traverse the screen from the lower left hand corner and use two offset vectors along the screen
452+
traverse the screen from the lower left hand corner, and use two offset vectors along the screen
453453
sides to move the ray endpoint across the screen. Note that I do not make the ray direction a unit
454454
length vector because I think not doing that makes for simpler and slightly faster code.
455455

@@ -578,8 +578,8 @@
578578
</div>
579579

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

584584
$$ t^2 \mathbf{b} \cdot \mathbf{b}
585585
+ 2t \mathbf{b} \cdot (\mathbf{A}-\mathbf{C})
@@ -770,11 +770,11 @@
770770
An Abstraction for Hittable Objects
771771
------------------------------------
772772
Now, how about several spheres? While it is tempting to have an array of spheres, a very clean
773-
solution is to make an “abstract class” for anything a ray might hit and make both a sphere and a
773+
solution is the make an “abstract class” for anything a ray might hit, and make both a sphere and a
774774
list of spheres just something you can hit. What that class should be called is something of a
775775
quandary -- calling it an “object” would be good if not for “object oriented” programming. “Surface”
776776
is often used, with the weakness being maybe we will want volumes. “hittable” emphasizes the member
777-
function that unites them. I don’t love any of these but I will go with “hittable”.
777+
function that unites them. I don’t love any of these, but I will go with “hittable”.
778778

779779
<div class='together'>
780780
This `hittable` abstract class will have a hit function that takes in a ray. Most ray tracers have
@@ -924,11 +924,12 @@
924924
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
925925
[Listing [normals-point-against]: <kbd>[sphere.h]</kbd> Remembering the side of the surface]
926926

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

933934
We add the `front_face` bool to the `hit_record` struct. We'll also add a function to solve this
934935
calculation for us.
@@ -1245,11 +1246,10 @@
12451246

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

12541254
Some Random Number Utilities
12551255
-----------------------------
@@ -1461,7 +1461,7 @@
14611461
Lambertian.)
14621462

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

14671467
<div class='together'>
@@ -1982,7 +1982,7 @@
19821982
---------------------------------------
19831983
<div class='together'>
19841984
For the Lambertian (diffuse) case we already have, it can either scatter always and attenuate by its
1985-
reflectance $R$, or it can scatter with no attenuation but absorb the fraction $1-R$ of the rays. Or
1985+
reflectance $R$, or it can scatter with no attenuation but absorb the fraction $1-R$ of the rays, or
19861986
it could be a mixture of those strategies. For Lambertian materials we get this simple class:
19871987

19881988
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
@@ -2212,7 +2212,7 @@
22122212

22132213
Clear materials such as water, glass, and diamonds are dielectrics. When a light ray hits them, it
22142214
splits into a reflected ray and a refracted (transmitted) ray. We’ll handle that by randomly
2215-
choosing between reflection or refraction and only generating one scattered ray per interaction.
2215+
choosing between reflection or refraction, and only generating one scattered ray per interaction.
22162216

22172217

22182218
Refraction
@@ -2340,7 +2340,7 @@
23402340
Total Internal Reflection
23412341
--------------------------
23422342
That definitely doesn't look right. One troublesome practical issue is that when the ray is in the
2343-
material with the higher refractive index, there is no real solution to Snell’s law and thus there
2343+
material with the higher refractive index, there is no real solution to Snell’s law, and thus there
23442344
is no refraction possible. If we refer back to Snell's law and the derivation of $\sin\theta'$:
23452345

23462346
$$ \sin\theta' = \frac{\eta}{\eta'} \cdot \sin\theta $$
@@ -2354,8 +2354,8 @@
23542354
$$ \frac{1.5}{1.0} \cdot \sin\theta > 1.0 $$,
23552355

23562356
<div class="together">
2357-
the equality between the two sides of the equation is broken and a solution cannot exist. If a
2358-
solution does not exist the glass cannot refract and must reflect the ray:
2357+
The equality between the two sides of the equation is broken, and a solution cannot exist. If a
2358+
solution does not exist, the glass cannot refract, and therefore must reflect the ray:
23592359

23602360
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
23612361
if(etai_over_etat * sin_theta > 1.0) {
@@ -2528,8 +2528,8 @@
25282528
-------------------------------
25292529
<div class='together'>
25302530
An interesting and easy trick with dielectric spheres is to note that if you use a negative radius,
2531-
the geometry is unaffected but the surface normal points inward, so it can be used as a bubble
2532-
to make a hollow glass sphere:
2531+
the geometry is unaffected, but the surface normal points inward. This can be used as a bubble to
2532+
make a hollow glass sphere:
25332533

25342534
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
25352535
world.add(make_shared<sphere>(point3(0,0,-1), 0.5, make_shared<lambertian>(color(.1, .2, .5))));
@@ -2763,9 +2763,9 @@
27632763
--------------------------
27642764
<div class="together">
27652765
A real camera has a complicated compound lens. For our code we could simulate the order: sensor,
2766-
then lens, then aperture, and figure out where to send the rays and flip the image once computed
2767-
(the image is projected upside down on the film). Graphics people usually use a thin lens
2768-
approximation:
2766+
then lens, then aperture. Then we could figure out where to send the rays, and flip the image after
2767+
it's computed (the image is projected upside down on the film). Graphics people, however, usually
2768+
use a thin lens approximation:
27692769

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

@@ -2963,8 +2963,8 @@
29632963
</div>
29642964

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

@@ -2973,28 +2973,28 @@
29732973
-----------
29742974
You now have a cool ray tracer! What next?
29752975

2976-
1. Lights. You can do this explicitly, by sending shadow rays to lights, or it can be done
2976+
1. Lights -- You can do this explicitly, by sending shadow rays to lights, or it can be done
29772977
implicitly by making some objects emit light, biasing scattered rays toward them, and then
29782978
downweighting those rays to cancel out the bias. Both work. I am in the minority in favoring
29792979
the latter approach.
29802980

2981-
2. Triangles. Most cool models are in triangle form. The model I/O is the worst and almost
2981+
2. Triangles -- Most cool models are in triangle form. The model I/O is the worst and almost
29822982
everybody tries to get somebody else’s code to do this.
29832983

2984-
3. Surface textures. This lets you paste images on like wall paper. Pretty easy and a good thing
2984+
3. Surface Textures -- This lets you paste images on like wall paper. Pretty easy and a good thing
29852985
to do.
29862986

2987-
4. Solid textures. Ken Perlin has his code online. Andrew Kensler has some very cool info at his
2987+
4. Solid textures -- Ken Perlin has his code online. Andrew Kensler has some very cool info at his
29882988
blog.
29892989

2990-
5. Volumes and media. Cool stuff and will challenge your software architecture. I favor making
2990+
5. Volumes and Media -- Cool stuff and will challenge your software architecture. I favor making
29912991
volumes have the hittable interface and probabilistically have intersections based on density.
29922992
Your rendering code doesn’t even have to know it has volumes with that method.
29932993

2994-
6. Parallelism. Run $N$ copies of your code on $N$ cores with different random seeds. Average the
2995-
$N$ runs. This averaging can also be done hierarchically where $N/2$ pairs can be averaged to
2996-
get $N/4$ images, and pairs of those can be averaged. That method of parallelism should extend
2997-
well into the thousands of cores with very little coding.
2994+
6. Parallelism -- Run $N$ copies of your code on $N$ cores with different random seeds. Average
2995+
the $N$ runs. This averaging can also be done hierarchically where $N/2$ pairs can be averaged
2996+
to get $N/4$ images, and pairs of those can be averaged. That method of parallelism should
2997+
extend well into the thousands of cores with very little coding.
29982998

29992999
Have fun, and please send me your cool images!
30003000

0 commit comments

Comments
 (0)