(point3( 1.0, 0.0, -1.0), 0.5, material_right));
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
@@ -3277,17 +3277,18 @@
-Now we'll update the scene to change the left and center spheres to glass:
+Now we'll update the scene to illustrate refraction by changing the left sphere to glass, which has
+an index of refraction of approximately 1.5.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
auto material_ground = make_shared(color(0.8, 0.8, 0.0));
+ auto material_center = make_shared(color(0.1, 0.2, 0.5));
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
- auto material_center = make_shared(1.5);
auto material_left = make_shared(1.5);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
auto material_right = make_shared(color(0.8, 0.6, 0.2), 1.0);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- [Listing [two-glass]: [main.cc] Changing left and center spheres to glass]
+ [Listing [two-glass]: [main.cc] Changing the left sphere to glass]
@@ -3302,9 +3303,10 @@
Total Internal Reflection
--------------------------
-That definitely doesn't look right. One troublesome practical issue is that when the ray is in the
-material with the higher refractive index, there is no real solution to Snell’s law, and thus there
-is no refraction possible. If we refer back to Snell's law and the derivation of $\sin\theta'$:
+One troublesome practical issue with refraction is that there are ray angles for which no solution
+is possible using Snell's law. When a ray enters a medium of lower index of refraction at a
+sufficiently glancing angle, it can refract with an angle greater than 90°. If we refer back to
+Snell's law and the derivation of $\sin\theta'$:
$$ \sin\theta' = \frac{\eta}{\eta'} \cdot \sin\theta $$
@@ -3334,8 +3336,10 @@
Here all the light is reflected, and because in practice that is usually inside solid objects, it is
-called “total internal reflection”. This is why sometimes the water-air boundary acts as a perfect
-mirror when you are submerged.
+called _total internal reflection_. This is why sometimes the water-to-air boundary acts as a
+perfect mirror when you are submerged -- if you're under water looking up, you can see things above
+the water, but when you are close to the surface and looking sideways, the water surface looks like
+a mirror.
We can solve for `sin_theta` using the trigonometric qualities:
@@ -3400,25 +3404,42 @@
-
-Attenuation is always 1 -- the glass surface absorbs nothing. If we try that out with these
-parameters:
+Attenuation is always 1 -- the glass surface absorbs nothing.
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ Highlight
+If we render the prior scene with the new `dielectric::scatter()` function, we see … no change. Huh?
+
+Well, it turns out that given a sphere of material with an index of refraction greater than air,
+there's no incident angle that will yield total internal reflection -- neither at the ray-sphere
+entrance point nor at the ray exit. This is due to the geometry of spheres, as a grazing incoming
+ray will always be bent to a smaller angle, and then bent back to the original angle on exit.
+
+So how can we illustrate total internal reflection? Well, if the sphere has an index of refraction
+_less_ than the medium it's in, then we can hit it with shallow grazing angles, getting total
+_external_ reflection. That should be good enough to observe the effect.
+
+We'll model a world filled with water (index of refraction approximately 1.33), and change the
+sphere material to air (index of refraction 1.00) -- an air bubble! To do this, change the left
+sphere material's index of refraction to
+
+ $$\frac{\text{index of refraction of air}}{\text{index of refraction of water}}$$
+
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
auto material_ground = make_shared(color(0.8, 0.8, 0.0));
auto material_center = make_shared(color(0.1, 0.2, 0.5));
- auto material_left = make_shared(1.5);
- auto material_right = make_shared(color(0.8, 0.6, 0.2), 0.0);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
+ auto material_left = make_shared(1.00 / 1.33);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
+ auto material_right = make_shared(color(0.8, 0.6, 0.2), 1.0);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- [Listing [scene-dielectric]: [main.cc] Scene with dielectric and shiny sphere]
-
-
+ [Listing [two-glass]: [main.cc] Left sphere is an air bubble in water]
-We get:
+This change yields the following render:
+
+ 
- 
+Here you can see that more-or-less direct rays refract, while glancing rays reflect.
@@ -3509,7 +3530,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
...
world.add(make_shared(point3( 0.0, -100.5, -1.0), 100.0, material_ground));
- world.add(make_shared(point3( 0.0, 0.0, -1.0), 0.5, material_center));
+ world.add(make_shared(point3( 0.0, 0.0, -1.2), 0.5, material_center));
world.add(make_shared(point3(-1.0, 0.0, -1.0), 0.5, material_left));
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
world.add(make_shared(point3(-1.0, 0.0, -1.0), -0.4, material_left));
@@ -3776,7 +3797,7 @@
auto material_right = make_shared(color(0.8, 0.6, 0.2), 0.0);
world.add(make_shared(point3( 0.0, -100.5, -1.0), 100.0, material_ground));
- world.add(make_shared(point3( 0.0, 0.0, -1.0), 0.5, material_center));
+ world.add(make_shared(point3( 0.0, 0.0, -1.2), 0.5, material_center));
world.add(make_shared(point3(-1.0, 0.0, -1.0), 0.5, material_left));
world.add(make_shared(point3(-1.0, 0.0, -1.0), -0.4, material_left));
world.add(make_shared(point3( 1.0, 0.0, -1.0), 0.5, material_right));
diff --git a/images/img-1.16-glass-always-refract.png b/images/img-1.16-glass-always-refract.png
index df89a382..61e7b4be 100644
Binary files a/images/img-1.16-glass-always-refract.png and b/images/img-1.16-glass-always-refract.png differ
diff --git a/images/img-1.17-air-bubble-total-reflection.png b/images/img-1.17-air-bubble-total-reflection.png
new file mode 100644
index 00000000..b9e84bf5
Binary files /dev/null and b/images/img-1.17-air-bubble-total-reflection.png differ
diff --git a/images/img-1.17-glass-sometimes-refract.png b/images/img-1.17-glass-sometimes-refract.png
deleted file mode 100644
index 70f9ff4a..00000000
Binary files a/images/img-1.17-glass-sometimes-refract.png and /dev/null differ