diff --git a/CMakeLists.txt b/CMakeLists.txt
index 97377a8d..e4264c2c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,9 +15,13 @@ project ( RTWeekend
set ( CMAKE_CXX_STANDARD 11 )
# Source
-set ( SOURCE_ONE_WEEKEND
+set ( COMMON_ALL
src/common/rtweekend.h
src/common/vec3.h
+)
+
+set ( SOURCE_ONE_WEEKEND
+ ${COMMON_ALL}
src/InOneWeekend/camera.h
src/InOneWeekend/hittable.h
src/InOneWeekend/hittable_list.h
@@ -28,9 +32,8 @@ set ( SOURCE_ONE_WEEKEND
)
set ( SOURCE_NEXT_WEEK
- src/common/rtweekend.h
+ ${COMMON_ALL}
src/common/rtw_stb_image.h
- src/common/vec3.h
src/common/external/stb_image.h
src/TheNextWeek/aabb.h
src/TheNextWeek/aarect.h
@@ -51,13 +54,13 @@ set ( SOURCE_NEXT_WEEK
)
set ( SOURCE_REST_OF_YOUR_LIFE
- src/common/rtweekend.h
+ ${COMMON_ALL}
src/common/rtw_stb_image.h
- src/common/vec3.h
src/common/external/stb_image.h
src/TheRestOfYourLife/aabb.h
src/TheRestOfYourLife/aarect.h
src/TheRestOfYourLife/box.h
+ src/TheRestOfYourLife/bucamera.h
src/TheRestOfYourLife/bvh.h
src/TheRestOfYourLife/camera.h
src/TheRestOfYourLife/constant_medium.h
@@ -75,12 +78,23 @@ set ( SOURCE_REST_OF_YOUR_LIFE
src/TheRestOfYourLife/main.cc
)
-set ( COMMON_DIR src )
-
+# Executables
add_executable(inOneWeekend ${SOURCE_ONE_WEEKEND})
add_executable(theNextWeek ${SOURCE_NEXT_WEEK})
add_executable(theRestOfYourLife ${SOURCE_REST_OF_YOUR_LIFE})
+add_executable(cos_cubed src/TheRestOfYourLife/cos_cubed.cc ${COMMON_ALL})
+add_executable(cos_density src/TheRestOfYourLife/cos_density.cc ${COMMON_ALL})
+add_executable(integrate_x_sq src/TheRestOfYourLife/integrate_x_sq.cc ${COMMON_ALL})
+add_executable(pi src/TheRestOfYourLife/pi.cc ${COMMON_ALL})
+add_executable(sphere_importance src/TheRestOfYourLife/sphere_importance.cc ${COMMON_ALL})
+add_executable(sphere_plot src/TheRestOfYourLife/sphere_plot.cc ${COMMON_ALL})
-target_include_directories(inOneWeekend PRIVATE ${COMMON_DIR})
-target_include_directories(theNextWeek PRIVATE ${COMMON_DIR})
-target_include_directories(theRestOfYourLife PRIVATE ${COMMON_DIR})
+target_include_directories(inOneWeekend PRIVATE src)
+target_include_directories(theNextWeek PRIVATE src)
+target_include_directories(theRestOfYourLife PRIVATE src)
+target_include_directories(cos_cubed PRIVATE src)
+target_include_directories(cos_density PRIVATE src)
+target_include_directories(integrate_x_sq PRIVATE src)
+target_include_directories(pi PRIVATE src)
+target_include_directories(sphere_importance PRIVATE src)
+target_include_directories(sphere_plot PRIVATE src)
diff --git a/books/RayTracingInOneWeekend.html b/books/RayTracingInOneWeekend.html
index fddde399..ff6f0b04 100644
--- a/books/RayTracingInOneWeekend.html
+++ b/books/RayTracingInOneWeekend.html
@@ -88,6 +88,7 @@
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [main-initial]: [main.cc] Creating your first image]
There are some things to note in that code:
@@ -137,6 +138,7 @@
14 253 51
15 253 51
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [first-img]: First image output]
If it doesn’t, then you probably just have some newlines or something similar that is confusing the
@@ -212,6 +214,7 @@
double e[3];
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [vec3-class]: [vec3.h] `vec3` class]
We use `double` here, but some ray tracers use `float`. Either one is fine -- follow your own
@@ -264,6 +267,7 @@
return v / v.length();
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [vec3-utility]: [vec3.h] vec3 utility functions]
Now we can change our main to use this:
@@ -289,6 +293,7 @@
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [main-gradient]: [main.cc] Creating a color gradient image]
@@ -315,13 +320,12 @@
#include "common/vec3.h"
- class ray
- {
+ class ray {
public:
ray() {}
ray(const vec3& a, const vec3& b) { A = a; B = b; }
- vec3 origin() const { return A; }
- vec3 direction() const { return B; }
+ vec3 origin() const { return A; }
+ vec3 direction() const { return B; }
vec3 point_at_parameter(double t) const { return A + t*B; }
vec3 A;
@@ -330,6 +334,7 @@
#endif
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [ray-initial]:
@@ -496,6 +502,7 @@
return (1.0-t)*vec3(1.0, 1.0, 1.0) + t*vec3(0.5, 0.7, 1.0);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [main-red-sphere]: [main.cc] Rendering a red sphere]
@@ -569,6 +576,7 @@
return (1.0-t)*vec3(1.0, 1.0, 1.0) + t*vec3(0.5, 0.7, 1.0);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [render-surface-normal]: [main.cc] Rendering surface normals on a sphere]
@@ -586,6 +594,7 @@
auto c = dot(oc, oc) - radius*radius;
auto discriminant = b*b - 4*a*c;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [ray-sphere-before]: [main.cc] Ray-sphere intersection code (before)]
First, recall that a vector dotted with itself is equal to the squared length of that vector.
@@ -616,6 +625,7 @@
return (-half_b - sqrt(discriminant) ) / a;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [ray-sphere-after]: [main.cc] Ray-sphere intersection code (after)]
Now, how about several spheres? While it is tempting to have an array of spheres, a very clean
@@ -647,7 +657,7 @@
vec3 normal;
};
- class hittable {
+ class hittable {
public:
virtual bool hit(
const ray& r, double t_min, double t_max, hit_record& rec) const = 0;
@@ -655,6 +665,7 @@
#endif
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [hittable-initial]: [hittable.h] The hittable class]
@@ -667,10 +678,10 @@
#include "common/vec3.h"
#include "hittable.h"
- class sphere: public hittable {
+ class sphere: public hittable {
public:
sphere() {}
- sphere(vec3 cen, double r) : center(cen), radius(r) {};
+ sphere(vec3 cen, double r) : center(cen), radius(r) {};
virtual bool hit(
const ray& r, double tmin, double tmax, hit_record& rec) const;
vec3 center;
@@ -707,6 +718,7 @@
#endif
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [sphere-initial]: [sphere.h] The sphere class]
@@ -747,6 +759,7 @@
#endif
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [hittable-list-initial]:
@@ -851,6 +864,7 @@
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [main-with-rtweekend-h]: [main.cc] desc]
@@ -890,7 +904,7 @@
return rand() / (RAND_MAX + 1.0);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
+ [Listing [random-double]: [rtweekend.h] random_double() function]
@@ -910,6 +924,7 @@
return rand_generator();
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [random-double-alt]: [file] random_double(), alternate implemenation]
@@ -951,6 +966,7 @@
};
#endif
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [camera-initial]: [camera.h] The camera class]
To handle the multi-sampled color computation, we update the `vec3::write_color()` function. Rather
@@ -966,6 +982,7 @@
return x;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [clamp]: (256.0 * clamp(b, 0.0, 0.999999)) << '\n';
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [write-color-clamped]: [vec3.h] The write_color() function]
Main is also changed:
@@ -1018,6 +1036,7 @@
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [main-multi-sample]: [main.cc] Rendering with multi-sampled pixels]
@@ -1079,6 +1098,7 @@
return vec3(r * cos(a), r * sin(a), z);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [random-unit-vec]: [material.h] The random_unit_vector() function]
@@ -1100,6 +1120,7 @@
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [ray-color-random-unit]: [main.cc] ray_color() using a random ray direction]
@@ -1136,6 +1157,7 @@
<< static_cast(256.0 * clamp(b, 0.0, 0.999999)) << '\n';
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [write-color-gamma]: [vec3.h] write_color(), with gamma correction]
@@ -1154,6 +1176,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
if (world->hit(r, 0.001, infinity, rec)) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [reflect-tolerance]: [main.cc] Calculating reflected ray origins with tolerance]
This gets rid of the shadow acne problem. Yes it is really called that.
@@ -1176,13 +1199,14 @@
This suggests the abstract class:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- class material {
+ class material {
public:
virtual bool scatter(
const ray& r_in, const hit_record& rec, vec3& attenuation,
ray& scattered) const = 0;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [material-initial]: [material.h] The material class]
@@ -1198,13 +1222,17 @@
#include "common/rtweekend.h"
#include "ray.h"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
class material;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
struct hit_record {
double t;
vec3 p;
vec3 normal;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
material *mat_ptr;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
};
class hittable {
@@ -1215,6 +1243,7 @@
#endif
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [hit-with-material]: [hittable.h] Hit record with added material pointer]
What we have set up here is that material will tell us how rays interact with the surface.
@@ -1229,11 +1258,11 @@
within `hit_record`. See the highlighted lines below:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- class sphere: public hittable {
+ class sphere: public hittable {
public:
sphere() {}
sphere(vec3 cen, double r, material *m)
- : center(cen), radius(r), mat_ptr(m) {};
+ : center(cen), radius(r), mat_ptr(m) {};
virtual bool hit(
const ray& r, double tmin, double tmax, hit_record& rec) const;
vec3 center;
@@ -1276,6 +1305,7 @@
return false;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [sphere-material]: [sphere.h] Ray-sphere intersection with added material information]
@@ -1299,6 +1329,7 @@
vec3 albedo;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [lambertian-initial]: [material.h] The lambertian material class]
Note we could just as well only scatter with some probability $p$ and have attenuation be
@@ -1323,6 +1354,7 @@
return v - 2*dot(v,n)*n;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [vec3-reflect]: [material.h] vec3 reflection function]
@@ -1342,6 +1374,7 @@
vec3 albedo;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [metal-material]: [material.h] Metal material with reflectance function]
@@ -1369,6 +1402,7 @@
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [ray-color-scatter]: [main.cc] Ray color with scattered reflectance]
@@ -1407,6 +1441,7 @@
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [scene-with-metal]: [main.cc] Scene with metal spheres]
@@ -1464,6 +1499,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [metal-fuzz]: [main.cc] Metal spheres with fuzziness]
In order to generate a random point inside a unit sphere (`random_in_unit_sphere()`), we used one of
the easiest algorithms: a rejection method. First, pick a random point in the unit cube where x, y,
@@ -1532,6 +1568,7 @@
return false;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [refract]: [material.h] Refraction function]
@@ -1572,6 +1609,7 @@
double ref_idx;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [dielectric]: [material.h] Dielectric material class]
Attenuation is always 1 -- the glass surface absorbs nothing. The `attenuation = vec3(1.0, 1.0,
@@ -1588,6 +1626,7 @@
list[2] = new sphere(vec3(1,0,-1), 0.5, new metal(vec3(0.8, 0.6, 0.2), 0.0));
list[3] = new sphere(vec3(-1,0,-1), 0.5, new dielectric(1.5));
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [scene-dielectric]: [main.cc] Scene with dielectric sphere]
We get:
@@ -1613,6 +1652,7 @@
return r0 + (1-r0)*pow((1 - cosine),5);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [schlick]: [material.h] Schlick approximation]
@@ -1675,6 +1715,7 @@
double ref_idx;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [glass]: [material.h] Full glass material]
@@ -1689,6 +1730,7 @@
list[3] = new sphere(vec3(-1,0,-1), 0.5, new dielectric(1.5));
list[4] = new sphere(vec3(-1,0,-1), -0.45, new dielectric(1.5));
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [scene-hollow-glass]: [main.cc] Scene with hollow glass sphere]
@@ -1721,14 +1763,9 @@
This implies $h = \tan(\frac{\theta}{2})$. Our camera now becomes:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- #ifndef CAMERA_H
- #define CAMERA_H
-
- #include "common/rtweekend.h"
- #include "ray.h"
-
class camera {
public:
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
camera(
double vfov, // vfov is top to bottom in degrees
double aspect
@@ -1741,6 +1778,7 @@
vertical = vec3(0.0, 2*half_height, 0.0);
origin = vec3(0.0, 0.0, 0.0);
}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
ray get_ray(double u, double v) {
return ray(origin,
@@ -1752,8 +1790,8 @@
vec3 horizontal;
vec3 vertical;
};
- #endif
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [camera-fov]: [camera.h] Camera with adjustable field-of-view (fov)]
@@ -1765,6 +1803,7 @@
list[1] = new sphere(vec3( R,0,-1), R, new lambertian(vec3(1, 0, 0)));
hittable *world = new hittable_list(list,2);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [scene-wide-angle]:
[main.cc] Scene with wide-angle camera]
gives:
@@ -1796,22 +1835,16 @@
camera horizontally level until you decide to experiment with crazy camera angles.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- #ifndef CAMERA_H
- #define CAMERA_H
-
- #include "common/rtweekend.h"
- #include "ray.h"
-
class camera {
public:
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
camera(
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
vec3 lookfrom, vec3 lookat, vec3 vup,
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
double vfov, // vfov is top to bottom in degrees
double aspect
) {
vec3 u, v, w;
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
auto theta = degrees_to_radians(vfov);
auto half_height = tan(theta/2);
auto half_width = aspect * half_height;
@@ -1836,8 +1869,8 @@
vec3 horizontal;
vec3 vertical;
};
- #endif
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [camera-orient]:
[camera.h] Positionable and orientable camera]
This allows us to change the viewpoint:
@@ -1845,6 +1878,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
camera cam(vec3(-2,2,1), vec3(0,0,-1), vec3(0,1,0), 90, double(nx)/ny);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [scene-free-view]: [main.cc] Scene with alternate viewpoint]
to get:
@@ -1893,12 +1927,6 @@
point:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- #ifndef CAMERA_H
- #define CAMERA_H
-
- #include "common/rtweekend.h"
- #include "ray.h"
-
vec3 random_in_unit_disk() {
vec3 p;
do {
@@ -1909,10 +1937,10 @@
class camera {
public:
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
camera(
vec3 lookfrom, vec3 lookat, vec3 vup,
double vfov, // vfov is top to bottom in degrees
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
double aspect, double aperture, double focus_dist
) {
lens_radius = aperture / 2;
@@ -1953,8 +1981,8 @@
double lens_radius;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
};
- #endif
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [camera-dof]: [camera.h] Camera with adjustable depth-of-field (dof)]
@@ -1968,6 +1996,7 @@
camera cam(lookfrom, lookat, vec3(0,1,0), 20, double(nx)/ny, aperture, dist_to_focus);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [scene-camera-dof]: [main.cc] Scene camera with depth-of-field]
We get:
@@ -2023,6 +2052,7 @@
return new hittable_list(list,i);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [scene-final]: [main.cc] Final scene]
diff --git a/books/RayTracingTheNextWeek.html b/books/RayTracingTheNextWeek.html
index 34115769..07655de0 100644
--- a/books/RayTracingTheNextWeek.html
+++ b/books/RayTracingTheNextWeek.html
@@ -62,8 +62,7 @@
For this we will first need to have a ray store the time it exists at:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- class ray
- {
+ class ray {
public:
ray() {}
ray(const vec3& a, const vec3& b, double ti = 0.0) {
@@ -82,6 +81,7 @@
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [time-ray]: [ray.h] Ray with time information]
Now we need to modify the camera to generate rays at a random time between `time1` and `time2`.
@@ -143,6 +143,7 @@
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [time-camera]:
[camera.h] Camera with time information]
We also need a moving object. I’ll create a sphere class that has its center move linearly from
`center0` at `time0` to `center1` at `time1`. Outside that time interval it continues on, so those
@@ -170,6 +171,7 @@
return center0 + ((time - time0) / (time1 - time0))*(center1 - center0);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [moving-sphere]:
[moving_sphere.h] A moving sphere]
An alternative to making a new moving sphere class is to just make them all move and have the
@@ -215,6 +217,7 @@
return false;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [moving-sphere-hit]: [moving-sphere.h] Moving sphere hit function]
@@ -239,6 +242,7 @@
vec3 albedo;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [lambertian-animate]: [material.h] Lambertian matrial for moving objects]
@@ -295,10 +299,12 @@
return new hittable_list(list,i);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [scene-spheres-moving]:
+ [main.cc] Last book's final scene, but with moving spheres]
-And with these viewing parameters gives:
+And with these viewing parameters:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
vec3 lookfrom(13,2,3);
@@ -311,6 +317,9 @@
dist_to_focus, 0.0, 1.0
);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [scene-spheres-moving-camera]: [main.cc] Viewing parameters]
+
+gives the following result:

@@ -547,6 +556,7 @@
vec3 _max;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [aabb]: [aabb.h] Axis-aligned bounding box class]
@@ -571,6 +581,7 @@
return true;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [aabb-hit]: [aabb.h] Axis-aligned bounding box hit function]
@@ -588,6 +599,7 @@
virtual bool bounding_box(double t0, double t1, aabb& box) const = 0;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [hittable-bbox]: [hittable.h] Hittable class with bounding-box]
@@ -600,6 +612,7 @@
return true;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [sphere-bbox]: [sphere.h] Sphere with bounding box]
@@ -616,6 +629,7 @@
return true;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [moving-sphere-bbox]: [moving_sphere.h] Moving sphere with bounding box]
@@ -641,6 +655,7 @@
return true;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [hit-list-bbox]: [hittable_list.h] Hittable list with bounding box]
@@ -658,6 +673,7 @@
return aabb(small,big);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [surrounding-box]: [aabb.h] Surrounding bounding box]
@@ -687,6 +703,7 @@
return true;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [bvh]: [bvh.h] Bounding volume hierarchy]
Note that the children pointers are to generic hittables. They can be other `bvh_nodes`, or
@@ -723,6 +740,7 @@
else return false;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [bvh-hit]:
[bvh.h] Bounding volume hierarchy hit function]
@@ -785,6 +803,7 @@
box = surrounding_box(box_left, box_right);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [bvh-node]: [bvh.h] Bounding volume hierarchy node]
The check for whether there is a bounding box at all is in case you sent in something like an
@@ -810,6 +829,7 @@
return 1;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [bvh-x-comp]: [bvh.h] BVH comparison function, X-axis]
@@ -838,6 +858,7 @@
vec3 color;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [texture]: [texture.h] A texture class]
Now we can make textured materials by replacing the vec3 color with a texture pointer:
@@ -845,20 +866,27 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
class lambertian : public material {
public:
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
lambertian(texture *a) : albedo(a) {}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
virtual bool scatter(
const ray& r_in, const hit_record& rec, vec3& attenuation, ray& scattered
) const {
vec3 target = rec.p + rec.normal + random_unit_vector();
scattered = ray(rec.p, target - rec.p);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
attenuation = albedo->value(0, 0, rec.p);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
return true;
}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
texture *albedo;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [lambertian-textured]: [material.h] Lambertian material with texture]
@@ -867,12 +895,14 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
new lambertian(vec3(0.5, 0.5, 0.5)))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [lam-solid]: [main.cc] Lambertian material with solid color]
now you should replace the `vec3(...)` with `new constant_texture(vec3(...))`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
new lambertian(new constant_texture(vec3(0.5, 0.5, 0.5))))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [lam-textured]: [main.cc] Lambertian material with texture]
@@ -896,6 +926,7 @@
texture *even;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [checker-texture]: [texture.h] Checkered texture]
Those checker odd/even pointers can be to a constant texture or to some other procedural texture.
@@ -911,6 +942,7 @@
);
list[0] = new sphere(vec3(0,-1000,0), 1000, new lambertian(checker));
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [checker-example]: [main.cc] Checkered texture in use]
We get:
@@ -934,6 +966,7 @@
return new hittable_list(list,2);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [scene-two-checker]: [main.cc] Scene with two checkered spheres]
With camera:
@@ -946,6 +979,7 @@
camera cam(lookfrom, lookat, vec3(0,1,0), 20, double(nx)/ny, aperture, dist_to_focus,
0.0, 1.0);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [scene-two-checker-view]: [main.cc] Viewing parameters]
We get:
@@ -1035,6 +1069,7 @@
int *perlin::perm_y = perlin_generate_perm();
int *perlin::perm_z = perlin_generate_perm();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [perlin]: [perlin.h] A Perlin texture class and functions]
@@ -1051,6 +1086,7 @@
perlin noise;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [noise-texture]: [texture.h] Noise texture]
@@ -1065,6 +1101,7 @@
return new hittable_list(list, 2);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [scene-perlin]: [main.cc] Scene with two Perlin-textured spheres]
@@ -1078,6 +1115,7 @@
camera cam(lookfrom, lookat, vec3(0,1,0), 20, double(nx)/ny,
aperture, dist_to_focus, 0.0, 1.0);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [scene-perlin-view]: [main.cc] Viewing parameters]
@@ -1128,6 +1166,7 @@
static int *perm_z;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [perlin-trilinear]: [perlin.h] Perlin with trilienear interpolation]
@@ -1161,6 +1200,7 @@
int k = floor(p.z());
...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [perlin-smoothed]: [perlin.h] Perlin smoothed]
@@ -1189,6 +1229,7 @@
double scale;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [perlin-smoothed-2]: [perlin.h] Perlin smoothed, higher frequency]
which gives:
@@ -1208,6 +1249,7 @@
int *perlin::perm_y = perlin_generate_perm();
int *perlin::perm_z = perlin_generate_perm();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [perlin-randunit]: [perlin.h] Perlin with random unit translations]
@@ -1226,6 +1268,7 @@
return p;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [perlin-gen-2]: [perlin.h] New perlin_generate()]
@@ -1258,6 +1301,7 @@
static int *perm_z;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [perlin-2]: [perlin.h] The perlin class so far]
@@ -1280,6 +1324,7 @@
return accum;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [perlin-interp]: [perlin.h] Perlin interpolation function so far]
@@ -1306,6 +1351,7 @@
return fabs(accum);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [perlin-turb]: [perlin.h] Turbulence function]
Here `fabs()` is the `math.h` absolute value function.
@@ -1340,6 +1386,7 @@
double scale;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [noise-tex-2]: [texture.h] Noise texture with turbulence]
Which yields:
@@ -1411,6 +1458,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
get_sphere_uv((rec.p-center)/radius, rec.u, rec.v);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [get-sphere-uv-call]: [sphere.h] Sphere UV coordinates from hit]
@@ -1424,6 +1472,7 @@
v = (theta + pi/2) / pi;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [get-sphere-uv]: [sphere.h] get_sphere_uv function]
Now we also need to create a texture class that holds an image. I am going to use my favorite image
@@ -1454,6 +1503,7 @@
return vec3(r, g, b);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [img-texture]: [surface_texture.h] Image texture class]
The representation of a packed array in that order is pretty standard. Thankfully, the `stb_image`
@@ -1462,6 +1512,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
#include "common/rtw_stb_image.h"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [incl-stb-img]: Including the STB image package]
@@ -1477,6 +1528,7 @@
unsigned char *tex_data = stbi_load("earthmap.jpg", &nx, &ny, &nn, 0);
material *mat = new lambertian(new image_texture(tex_data, nx, ny));
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [stbi-load-use]: [main.cc] Using stbi_load() to load an image]
We start to see some of the power of all colors being textures -- we can assign any kind of texture
@@ -1497,8 +1549,8 @@
First, let’s make a light emitting material. We need to add an emitted function (we could also add
-it to hit_record instead -- that’s a matter of design taste). Like the background, it just tells the
-ray what color it is and performs no reflection. It’s very simple:
+it to `hit_record instead` -- that’s a matter of design taste). Like the background, it just tells
+the ray what color it is and performs no reflection. It’s very simple:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
class diffuse_light : public material {
@@ -1512,6 +1564,7 @@
texture *emit;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [diffuse-light]: [material.h] A diffuse light class]
@@ -1523,11 +1576,14 @@
public:
virtual bool scatter(const ray& r_in, const hit_record& rec,
vec3& attenuation, ray& scattered) const = 0;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
virtual vec3 emitted(double u, double v, const vec3& p) const {
return vec3(0,0,0);
}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [matl-emit]: [material.h] New emitted function in class material]
@@ -1539,6 +1595,7 @@
if (world->hit(r, 0.001, infinity, rec)) {
ray scattered;
vec3 attenuation;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
vec3 emitted = rec.mat_ptr->emitted(rec.u, rec.v, rec.p);
if (depth < 50 && rec.mat_ptr->scatter(r, rec, attenuation, scattered))
return emitted + attenuation * ray_color(scattered, world, depth+1);
@@ -1547,8 +1604,10 @@
}
else
return vec3(0,0,0);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [ray-color-emitted]: [main.cc] ray_color function for emitting materials]
Now, let’s make some rectangles. Rectangles are often convenient for modelling man-made
@@ -1601,6 +1660,7 @@
double x0, x1, y0, y1, k;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [xy-rect]: [aarect.h] XY-plane rectangle objects]
@@ -1624,6 +1684,7 @@
return true;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [xy-rect-hit]: [aarect.h] Hit function for XY rectangle objects]
@@ -1642,6 +1703,7 @@
return new hittable_list(list,4);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [rect-light]: [main.cc] A simple rectangle light]
@@ -1698,6 +1760,7 @@
double y0, y1, z0, z1, k;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [xz-yz-rects]: [aarect.h] XZ and YZ rectangle objects]
@@ -1738,6 +1801,7 @@
return true;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [xz-yz]: [aarect.h] XZ and YZ rectangle object hit functions]
@@ -1761,6 +1825,7 @@
return new hittable_list(list,i);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [cornell-box-empty]: [main.cc] Cornell box scene, empty]
@@ -1776,6 +1841,7 @@
camera cam(lookfrom, lookat, vec3(0,1,0), vfov, double(nx)/ny,
aperture, dist_to_focus, 0.0, 1.0);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [cornell-box-view]: [main.cc] Viewing parameters]
@@ -1813,6 +1879,7 @@
hittable *ptr;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [flip-normals]: [hittable.h] Flip-normals function]
@@ -1827,16 +1894,23 @@
material *green = new lambertian(new constant_texture(vec3(0.12, 0.45, 0.15)));
material *light = new diffuse_light(new constant_texture(vec3(15, 15, 15)));
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
list[i++] = new flip_normals(new yz_rect(0, 555, 0, 555, 555, green));
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
list[i++] = new yz_rect(0, 555, 0, 555, 0, red);
list[i++] = new xz_rect(213, 343, 227, 332, 554, light);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
list[i++] = new flip_normals(new xz_rect(0, 555, 0, 555, 555, white));
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
list[i++] = new xz_rect(0, 555, 0, 555, 0, white);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
list[i++] = new flip_normals(new xy_rect(0, 555, 0, 555, 555, white));
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
return new hittable_list(list,i);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [cornell-box-flipped]: [main.cc] Empty Cornell box with flipped rectangles]
@@ -1888,6 +1962,7 @@
return list_ptr->hit(r, t0, t1, rec);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [box-class]:
[box.h] A box object]
Now we can add two blocks (but not rotated)
@@ -1896,6 +1971,7 @@
list[i++] = new box(vec3(130, 0, 65), vec3(295, 165, 230), white);
list[i++] = new box(vec3(265, 0, 295), vec3(430, 330, 460), white);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [add-boxes]: [main.cc] Adding box objects]
@@ -1954,6 +2030,7 @@
return false;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [translate-class]:
[hittable.h] Hittable translation class]
@@ -2016,6 +2093,7 @@
aabb bbox;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [rot-y]: [hittable.h] Hittable rotate-Y class]
@@ -2038,8 +2116,7 @@
auto newx = cos_theta*x + sin_theta*z;
auto newz = -sin_theta*x + cos_theta*z;
vec3 tester(newx, y, newz);
- for (int c = 0; c < 3; c++)
- {
+ for (int c = 0; c < 3; c++) {
if (tester[c] > max[c])
max[c] = tester[c];
if (tester[c] < min[c])
@@ -2051,6 +2128,7 @@
bbox = aabb(min, max);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [rot-y-rot]: [hittable.h] Rotate-Y rotate method]
@@ -2080,6 +2158,7 @@
return false;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [rot-y-hit]: [hittable.h] Hittable Y-rotate hit function]
@@ -2095,6 +2174,7 @@
vec3(265,0,295)
);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [scene-rot-y]: [main.cc] Cornell scene with Y-rotated boxes]
@@ -2153,6 +2233,7 @@
material *phase_function;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [const-med-class]: [constant_medium.h] Constant medium class]
@@ -2175,6 +2256,7 @@
texture *albedo;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [isotropic-class]: [material.h] The isotropic class]
@@ -2230,6 +2312,7 @@
return false;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [const-med-hit]: [constant_medium.h] Constant medium hit method]
The reason we have to be so careful about the logic around the boundary is we need to make sure this
@@ -2271,6 +2354,7 @@
return new hittable_list(list,i);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [cornell-smoke]: [main.cc] Cornell box, with smoke]
@@ -2345,6 +2429,7 @@
return new hittable_list(list,l);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [scene-final]:
[main.cc] Final scene]
Running it with 10,000 rays per pixel yields:
diff --git a/books/RayTracingTheRestOfYourLife.html b/books/RayTracingTheRestOfYourLife.html
index 2694149e..fd9c65fe 100644
--- a/books/RayTracingTheRestOfYourLife.html
+++ b/books/RayTracingTheRestOfYourLife.html
@@ -87,9 +87,10 @@
if(x*x + y*y < 1)
inside_circle++;
}
- std::cout << "Estimate of Pi = " << 4*double(inside_circle) / N << "\n";
+ std::cout << "Estimate of Pi = " << 4*double(inside_circle) / N << '\n';
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [estpi-1]: [pi.cc] Estimating π]
This gives me the answer `Estimate of Pi = 3.196`
@@ -122,6 +123,7 @@
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [estpi-2]:
[pi.cc] Estimating π, v2]
@@ -159,12 +161,16 @@
inside_circle_stratified++;
}
}
- std::cout << "Regular Estimate of Pi = " <<
- 4*double(inside_circle) / (sqrt_N*sqrt_N) << "\n";
- std::cout << "Stratified Estimate of Pi = " <<
- 4*double(inside_circle_stratified) / (sqrt_N*sqrt_N) << "\n";
+
+ auto N = static_cast(sqrt_N) * sqrt_N;
+ std::cout
+ << "Regular Estimate of Pi = "
+ << 4*double(inside_circle) / (sqrt_N*sqrt_N) << '\n'
+ << "Stratified Estimate of Pi = "
+ << 4*double(inside_circle_stratified) / (sqrt_N*sqrt_N) << '\n';
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [estpi-3]: [pi.cc] Estimating π, v3]
I get:
@@ -207,6 +213,12 @@
This suggests a MC approach:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
+ #include "common/rtweekend.h"
+
+ #include
+ #include
+ #include
+
int main() {
int inside_circle = 0;
int inside_circle_stratified = 0;
@@ -219,6 +231,7 @@
std::cout << "I =" << 2*sum/N << "\n";
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [integ-xsq-1]: [integrate_x_sq.cc] Integrating $x^2$]
This, as expected, produces approximately the exact answer we get with algebra, $I = 8/3$. But we
@@ -381,29 +394,27 @@
down-weight. The _pdf_ is a perfect measure of how much or little sampling is being done. So the
weighting function should be proportional to $1/pdf$ . In fact it is exactly $1/pdf$ :
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- #include "common/rtweekend.h"
-
- #include
- #include
- #include
-
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
inline double pdf(double x) {
return 0.5*x;
}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
int main() {
int inside_circle = 0;
int inside_circle_stratified = 0;
int N = 1000000;
- double sum;
+ auto sum = 0.0;
for (int i = 0; i < N; i++) {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
auto x = sqrt(4*random_double());
sum += x*x / pdf(x);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
}
- std::cout << "I =" << sum/N << "\n";
+ std::cout << "I = " << sum/N << '\n';
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [integ-xsq-2]: [integrate_x_sq.cc] Integrating $x^2$ with _pdf_]
Since we are sampling more where the integrand is big, we might expect less noise and thus faster
@@ -414,30 +425,27 @@
If we take that same code with uniform samples so the pdf = $1/2$ over the range [0,2] we can use
the machinery to get `x = 2*random_double()` and the code is:
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- #include "common/rtweekend.h"
- #include "random.h"
-
- #include
- #include
- #include
-
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
inline double pdf(double x) {
return 0.5;
}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
int main() {
int inside_circle = 0;
int inside_circle_stratified = 0;
int N = 1000000;
- double sum;
+ auto sum = 0.0;
for (int i = 0; i < N; i++) {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
auto x = 2*random_double();
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
sum += x*x / pdf(x);
}
- std::cout << "I =" << sum/N << "\n";
+ std::cout << "I = " << sum/N << '\n';
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [integ-xsq-3]: [integrate_x_sq.cc] Integrating $x^2$, v3]
@@ -461,29 +469,29 @@
integrating $p$ analytically), but it’s a good exercise to make sure our code works. For just 1
sample we get:
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- #include "common/rtweekend.h"
-
- #include
- #include
- #include
-
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
inline double pdf(double x) {
return 3*x*x/8;
}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
int main() {
int inside_circle = 0;
int inside_circle_stratified = 0;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
int N = 1;
- double sum;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
+ auto sum = 0.0;
for (int i = 0; i < N; i++) {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
auto x = pow(8*random_double(), 1./3.);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
sum += x*x / pdf(x);
}
- std::cout << "I =" << sum/N << "\n";
+ std::cout << "I = " << sum/N << '\n';
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [integ-xsq-4]: [integrate_x_sq.cc] Integrating $x^2$, final version]
Which always returns the exact answer.
@@ -504,7 +512,7 @@
====================================================================================================
In our ray tracer we pick random directions, and directions can be represented as points on the
-unit-sphere. The same methodology as before applies. But now we need to have a pdf defined over 2D.
+unit sphere. The same methodology as before applies, but now we need to have a pdf defined over 2D.
Suppose we have this integral over all directions:
$$ \int cos^2(\theta) $$
@@ -520,11 +528,12 @@
vec3 random_in_unit_sphere() {
vec3 p;
do {
- p = 2.0*vec3(random_double(),random_double(),random_double()) - vec3(1,1,1);
- } while (dot(p,p) >= 1.0);
+ p = 2*vec3(random_double(),random_double(),random_double()) - vec3(1,1,1);
+ } while (p.squared_length() >= 1);
return p;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [rand-unit-sphere]: [pdf.h] Random point in unit sphere]
@@ -533,12 +542,16 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
vec3 random_on_unit_sphere() {
vec3 p;
+ double len_squared;
do {
- p = 2.0*vec3(random_double(),random_double(),random_double()) - vec3(1,1,1);
- } while (dot(p,p) >= 1.0);
- return unit_vector(p);
+ p = 2*vec3(random_double(),random_double(),random_double()) - vec3(1,1,1);
+ len_squared = p.squared_length();
+ } while (len_squared >= 1);
+ return p / sqrt(len_squared);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [rand-on-sphere]: [sphere_importance.cc]
+ Random point on the surface of the unit sphere, importance sampled]
@@ -553,15 +566,17 @@
int main() {
int N = 1000000;
- double sum;
+ auto sum = 0.0;
for (int i = 0; i < N; i++) {
- vec3 d = random_on_unit_sphere();
- auto cosine_squared = d.z()*d.z();
- sum += cosine_squared / pdf(d);
+ vec3 d = random_on_unit_sphere();
+ auto cosine_squared = d.z()*d.z();
+ sum += cosine_squared / pdf(d);
}
- std::cout << "I =" << sum/N << "\n";
+ std::cout << "I = " << sum/N << '\n';
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [main-sphereimp]: [sphere_importance.cc]
+ Generating importance-sampled points on the unit sphere]
The analytic answer (if you remember enough advanced calc, check me!) is $\frac{4}{3} \pi$, and the
@@ -702,12 +717,13 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
void cornell_box(hittable **scene, camera **cam, double aspect) {
- int i = 0;
- hittable **list = new hittable*[8];
material *red = new lambertian( new constant_texture(vec3(0.65, 0.05, 0.05)) );
material *white = new lambertian( new constant_texture(vec3(0.73, 0.73, 0.73)) );
material *green = new lambertian( new constant_texture(vec3(0.12, 0.45, 0.15)) );
material *light = new diffuse_light( new constant_texture(vec3(15, 15, 15)) );
+
+ hittable **list = new hittable*[8];
+ int i = 0;
list[i++] = new flip_normals(new yz_rect(0, 555, 0, 555, 555, green));
list[i++] = new yz_rect(0, 555, 0, 555, 0, red);
list[i++] = new xz_rect(213, 343, 227, 332, 554, light);
@@ -719,6 +735,7 @@
list[i++] = new translate(new rotate_y(
new box(vec3(0, 0, 0), vec3(165, 330, 165), white), 15), vec3(265,0,295));
*scene = new hittable_list(list,i);
+
vec3 lookfrom(278, 278, -800);
vec3 lookat(278, 278, 0);
auto dist_to_focus = 10.0;
@@ -728,10 +745,11 @@
vfov, aspect, aperture, dist_to_focus, 0.0, 1.0);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [cornell-box]: [main.cc] Cornell box, refactored]
-At 500x500 my code produces this image in 10min on 1 core of my Macbook:
+At 500×500 my code produces this image in 10min on 1 core of my Macbook:

@@ -744,10 +762,10 @@
let’s sample like we do now: $p(direction) = \cos(\theta) / \pi$.
-We modify the base-class _material_ to enable this importance sampling:
+We modify the base-class `material` to enable this importance sampling:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- class material {
+ class material {
public:
virtual bool scatter(
@@ -768,6 +786,8 @@
}
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [class-material]: [material.h]
+ The material class, adding importance sampling]
@@ -798,6 +818,8 @@
texture *albedo;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [class-lambertian-impsample]: [material.h]
+ Lambertian material, modified for importance sampling]
@@ -824,6 +846,8 @@
return vec3(0,0,0);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [ray-color-impsample]: [main.cc]
+ The ray_color function, modified for importance sampling]
You should get exactly the same picture.
@@ -845,6 +869,7 @@
return true;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [scatter-mod]:
[material.h] Modified scatter function]
@@ -945,11 +970,11 @@
auto x = cos(2*pi*r1)*2*sqrt(r2*(1-r2));
auto y = sin(2*pi*r1)*2*sqrt(r2*(1-r2));
auto z = 1 - 2*r2;
-
- std::cout << x << " " << y << " " << z << "\n";
+ std::cout << x << " " << y << " " << z << '\n';
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [rand-unit-sphere-plot]: [sphere_plot.cc] Random points on the unit sphere]
@@ -993,10 +1018,11 @@
auto z = 1 - r2;
sum += z*z*z / (1.0/(2.0*pi));
}
- std::cout << "PI/2 = " << pi/2 << "\n";
- std::cout << "Estimate = " << sum/N << "\n";
+ std::cout << "PI/2 = " << pi/2 << '\n';
+ std::cout << "Estimate = " << sum/N << '\n';
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [cos-cubed]: [cos_cubed.cc] Integration using $cos^3(x)$]
@@ -1019,6 +1045,11 @@
Let’s also start generating them as random vectors:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
+ #include "common/rtweekend.h"
+
+ #include
+ #include
+
inline vec3 random_cosine_direction() {
auto r1 = random_double();
auto r2 = random_double();
@@ -1036,10 +1067,11 @@
vec3 v = random_cosine_direction();
sum += v.z()*v.z()*v.z() / (v.z()/(pi));
}
- std::cout << "PI/2 = " << pi/2 << "\n";
- std::cout << "Estimate = " << sum/N << "\n";
+ std::cout << "PI/2 = " << pi/2 << '\n';
+ std::cout << "Estimate = " << sum/N << '\n';
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [cos-density]: [cos_density.cc] Integration with cosine density function]
We can generate other densities later as we need them. In the next chapter we’ll get them aligned to
@@ -1126,14 +1158,13 @@
utility functions:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- class onb
- {
+ class onb {
public:
onb() {}
inline vec3 operator[](int i) const { return axis[i]; }
- vec3 u() const { return axis[0]; }
- vec3 v() const { return axis[1]; }
- vec3 w() const { return axis[2]; }
+ vec3 u() const { return axis[0]; }
+ vec3 v() const { return axis[1]; }
+ vec3 w() const { return axis[2]; }
vec3 local(double a, double b, double c) const { return a*u() + b*v() + c*w(); }
vec3 local(const vec3& a) const { return a.x()*u() + a.y()*v() + a.z()*w(); }
void build_from_w(const vec3&);
@@ -1152,6 +1183,7 @@
axis[0] = cross(w(), v());
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [class-onb]: [onb.h] Ortho-normal basis class]
@@ -1170,6 +1202,7 @@
return true;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [scatter-onb]: [material.h] Scatter function, with ortho-normal basis]
@@ -1262,6 +1295,7 @@
return vec3(0,0,0);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [ray-color-lights]: [main.cc] Ray color with light sampling]
@@ -1287,6 +1321,7 @@
return vec3(0,0,0);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [emitted-directional]: [material.h] Material emission, directional]
@@ -1343,12 +1378,13 @@
minimal interface works, and for the _pdf_ this implies:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- class pdf {
+ class pdf {
public:
virtual double value(const vec3& direction) const = 0;
virtual vec3 generate() const = 0;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [class-pdf]: [pdf.h] The PDF class]
We’ll see if that works by fleshing out the subclasses. For sampling the light, we will need
@@ -1370,12 +1406,13 @@
else
return 0;
}
- virtual vec3 generate() const {
+ virtual vec3 generate() const {
return uvw.local(random_cosine_direction());
}
onb uvw;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [class-cos-pdf]: [pdf.h] The cosine_pdf class]
@@ -1409,6 +1446,7 @@
return vec3(0,0,0);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [ray-color-cos-pdf]: [main.cc] The ray_color function, using cosine pdf]
This yields an apparently matching result so all we’ve done so far is refactor where `pdf` is
@@ -1436,6 +1474,7 @@
hittable *ptr;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [class-hittable-pdf]: [pdf.h] The hittable_pdf class]
@@ -1444,22 +1483,25 @@
class:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- class hittable {
+ class hittable {
public:
- virtual bool hit(const ray& r, double t_min, double t_max,
- hit_record& rec) const = 0;
+ virtual bool hit(
+ const ray& r, double t_min, double t_max, hit_record& rec) const = 0;
virtual bool bounding_box(double t0, double t1, aabb& box) const = 0;
- virtual double pdf_value(const vec3& o, const vec3& v) const {return 0.0;}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
+ virtual double pdf_value(const vec3& o, const vec3& v) const {return 0.0;}
virtual vec3 random(const vec3& o) const {return vec3(1, 0, 0);}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [hittable-plus2]: [hittable.h] The hittable class, with two new methods]
And we change `xz_rect` to implement those functions:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- class xz_rect: public hittable {
+ class xz_rect: public hittable {
public:
xz_rect() {}
xz_rect(
@@ -1493,6 +1535,7 @@
double x0, x1, z0, z1, k;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [xz-rect-pdf]: [aarect.h] XZ rect with pdf]
@@ -1526,6 +1569,7 @@
return vec3(0,0,0);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [ray-color-hittable-pdf]: [main.cc] ray_color function with hittable pdf]
@@ -1555,6 +1599,7 @@
pdf *p[2];
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [class-mixturepdf]: [pdf.h] The mixture_pdf class]
@@ -1590,6 +1635,7 @@
return vec3(0,0,0);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [ray-color-mixture]: [main.cc] The ray_color function, using mixture pdf]
@@ -1673,19 +1719,21 @@
We can redesign `material` and stuff all the new arguments into a `struct` like we did for
`hittable`:
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- struct scatter_record
- {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
+ struct scatter_record {
ray specular_ray;
bool is_specular;
vec3 attenuation;
pdf *pdf_ptr;
};
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- class material {
+ class material {
public:
virtual bool scatter(
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
const ray& r_in, const hit_record& hrec, scatter_record& srec
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
) const {
return false;
}
@@ -1697,12 +1745,15 @@
}
virtual vec3 emitted(
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
const ray& r_in, const hit_record& rec, double u, double v, const vec3& p
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
) const {
return vec3(0,0,0);
}
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [material-refactor]: [material.h] Refactoring the material class]
@@ -1725,8 +1776,8 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
- bool scatter(const ray& r_in, const hit_record& hrec,
- scatter_record& srec) const {
+ bool scatter(const ray& r_in, const hit_record& hrec, scatter_record& srec
+ ) const {
srec.is_specular = false;
srec.attenuation = albedo->value(hrec.u, hrec.v, hrec.p);
srec.pdf_ptr = new cosine_pdf(hrec.normal);
@@ -1737,6 +1788,7 @@
texture *albedo;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [lambertian-scatter]: [material.h] New lambertian scatter() method]
@@ -1767,6 +1819,7 @@
return vec3(0,0,0);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [ray-color-scatter]: [main.cc] Ray color with scatter]
@@ -1793,6 +1846,7 @@
double fuzz;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [metal-scatter]: [material.h] The metal class scatter method]
Note that if fuzziness is high, this surface isn’t ideally specular, but the implicit sampling works
@@ -1833,6 +1887,8 @@
return vec3(0,0,0);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [ray-color-implicit]: [main.cc]
+ Ray color function with implicitly-sampled rays]
@@ -1871,6 +1927,7 @@
vfov, aspect, aperture, dist_to_focus, 0.0, 1.0);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [scene-cornell-al]: [main.cc] Cornell box scene with aluminum material]
@@ -1968,6 +2025,7 @@
return uvw.local(random_to_sphere(radius, distance_squared));
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [sphere-pdf]: [sphere.h] Sphere with pdf]
@@ -1984,6 +2042,7 @@
return vec3(x, y, z);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [rand-to-sphere]: [pdf.h] The random_to_sphere utility function]
@@ -2004,6 +2063,7 @@
col += ray_color(r, world, glass_sphere, 0);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [sampling-sphere]: [main.cc] Sampling just the sphere]
@@ -2035,6 +2095,7 @@
return list[ index ]->random(o);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [density-mixture]: [hittable_list.h] Creating a mixture of densities]
@@ -2048,6 +2109,7 @@
a[1] = glass_sphere;
hittable_list hlist(a,2);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [scene-density-mixture]: [main.cc] Updating the scene]
@@ -2100,6 +2162,7 @@
<< static_cast(255.999 * clamp(b, 0.0, 1.0)) << '\n';
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [write-color-nan]: [common/vec3.h] NaN-tolerant write_color function]
diff --git a/src/TheRestOfYourLife/bucamera.h b/src/TheRestOfYourLife/bucamera.h
new file mode 100644
index 00000000..0763377c
--- /dev/null
+++ b/src/TheRestOfYourLife/bucamera.h
@@ -0,0 +1,49 @@
+#ifndef CAMERAH
+#define CAMERAH
+//==================================================================================================
+// Written in 2016 by Peter Shirley
+//
+// To the extent possible under law, the author(s) have dedicated all copyright and related and
+// neighboring rights to this software to the public domain worldwide. This software is distributed
+// without any warranty.
+//
+// You should have received a copy (see file COPYING.txt) of the CC0 Public Domain Dedication along
+// with this software. If not, see .
+//==================================================================================================
+
+#include "ray.h"
+
+
+class camera {
+ public:
+ camera() {
+ lower_left_corner = vec3(-2.0, -1.0, -1.0);
+ horizontal = vec3(4.0, 0.0, 0.0);
+ vertical = vec3(0.0, 2.0, 0.0);
+ /*
+ lower_left_corner = vec3(-.1, -0.05, -1.0);
+ horizontal = vec3(0.2, 0.0, 0.0);
+ vertical = vec3(0.0, 0.1, 0.0);
+ */
+ origin = vec3(0.0, 0.0, 0.0);
+ }
+
+ camera(vec3 lookfrom, vec3 lookat, vec3 view_up, float aspect, float vfov, float aperture, float distance_to_focus) {
+ origin = lookfrom;
+ w = unit_vector(lookfrom - lookat;
+ u = unit_vector(cross(vup, w));
+ v = cross(w, u);
+ ZZ
+ }
+ ray get_ray(float s, float t) { return ray(origin, lower_left_corner + s*horizontal + t*vertical - origin); }
+
+ vec3 origin;
+ vec3 lower_left_corner;
+ vec3 horizontal;
+ vec3 vertical;
+ vec3 u, v, w;
+ float radius;
+};
+
+#endif
+
diff --git a/src/TheRestOfYourLife/cos_cubed.cc b/src/TheRestOfYourLife/cos_cubed.cc
new file mode 100644
index 00000000..fb34605d
--- /dev/null
+++ b/src/TheRestOfYourLife/cos_cubed.cc
@@ -0,0 +1,31 @@
+//==================================================================================================
+// Originally written in 2016 by Peter Shirley
+//
+// To the extent possible under law, the author(s) have dedicated all copyright and related and
+// neighboring rights to this software to the public domain worldwide. This software is distributed
+// without any warranty.
+//
+// You should have received a copy (see file COPYING.txt) of the CC0 Public Domain Dedication along
+// with this software. If not, see .
+//==================================================================================================
+
+#include "common/rtweekend.h"
+
+#include
+#include
+
+
+int main() {
+ int N = 1000000;
+ auto sum = 0.0;
+ for (int i = 0; i < N; i++) {
+ auto r1 = random_double();
+ auto r2 = random_double();
+ auto x = cos(2*pi*r1)*2*sqrt(r2*(1-r2));
+ auto y = sin(2*pi*r1)*2*sqrt(r2*(1-r2));
+ auto z = 1 - r2;
+ sum += z*z*z / (1.0/(2.0*pi));
+ }
+ std::cout << "PI/2 = " << pi/2 << '\n';
+ std::cout << "Estimate = " << sum/N << '\n';
+}
diff --git a/src/TheRestOfYourLife/cos_density.cc b/src/TheRestOfYourLife/cos_density.cc
new file mode 100644
index 00000000..eb8f92d7
--- /dev/null
+++ b/src/TheRestOfYourLife/cos_density.cc
@@ -0,0 +1,38 @@
+//==================================================================================================
+// Written in 2016 by Peter Shirley
+//
+// To the extent possible under law, the author(s) have dedicated all copyright and related and
+// neighboring rights to this software to the public domain worldwide. This software is distributed
+// without any warranty.
+//
+// You should have received a copy (see file COPYING.txt) of the CC0 Public Domain Dedication along
+// with this software. If not, see .
+//==================================================================================================
+
+#include "common/rtweekend.h"
+
+#include
+#include
+
+
+inline vec3 random_cosine_direction() {
+ auto r1 = random_double();
+ auto r2 = random_double();
+ auto z = sqrt(1-r2);
+ auto phi = 2*pi*r1;
+ auto x = cos(phi)*sqrt(r2);
+ auto y = sin(phi)*sqrt(r2);
+ return vec3(x, y, z);
+}
+
+
+int main() {
+ int N = 1000000;
+ auto sum = 0.0;
+ for (int i = 0; i < N; i++) {
+ vec3 v = random_cosine_direction();
+ sum += v.z()*v.z()*v.z() / (v.z()/(pi));
+ }
+ std::cout << "PI/2 = " << pi/2 << '\n';
+ std::cout << "Estimate = " << sum/N << '\n';
+}
diff --git a/src/TheRestOfYourLife/hittable.h b/src/TheRestOfYourLife/hittable.h
index ea8786f7..e3e2ffe1 100644
--- a/src/TheRestOfYourLife/hittable.h
+++ b/src/TheRestOfYourLife/hittable.h
@@ -38,12 +38,12 @@ struct hit_record
material *mat_ptr;
};
-class hittable {
+class hittable {
public:
virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const = 0;
virtual bool bounding_box(double t0, double t1, aabb& box) const = 0;
- virtual double pdf_value(const vec3& o, const vec3& v) const {return 0.0;}
- virtual vec3 random(const vec3& o) const {return vec3(1, 0, 0);}
+ virtual double pdf_value(const vec3& o, const vec3& v) const { return 0.0; }
+ virtual vec3 random(const vec3& o) const { return vec3(1,0,0); }
};
class flip_normals : public hittable {
@@ -120,8 +120,7 @@ rotate_y::rotate_y(hittable *p, double angle) : ptr(p) {
auto newx = cos_theta*x + sin_theta*z;
auto newz = -sin_theta*x + cos_theta*z;
vec3 tester(newx, y, newz);
- for ( int c = 0; c < 3; c++ )
- {
+ for ( int c = 0; c < 3; c++ ) {
if ( tester[c] > max[c] )
max[c] = tester[c];
if ( tester[c] < min[c] )
diff --git a/src/TheRestOfYourLife/integrate_x_sq.cc b/src/TheRestOfYourLife/integrate_x_sq.cc
new file mode 100644
index 00000000..ab08b48c
--- /dev/null
+++ b/src/TheRestOfYourLife/integrate_x_sq.cc
@@ -0,0 +1,33 @@
+//==================================================================================================
+// Originally written in 2016 by Peter Shirley
+//
+// To the extent possible under law, the author(s) have dedicated all copyright and related and
+// neighboring rights to this software to the public domain worldwide. This software is distributed
+// without any warranty.
+//
+// You should have received a copy (see file COPYING.txt) of the CC0 Public Domain Dedication along
+// with this software. If not, see .
+//==================================================================================================
+
+#include "common/rtweekend.h"
+
+#include
+#include
+#include
+
+
+inline double pdf(double x) {
+ return 3*x*x/8;
+}
+
+int main() {
+ int inside_circle = 0;
+ int inside_circle_stratified = 0;
+ int N = 1;
+ auto sum = 0.0;
+ for (int i = 0; i < N; i++) {
+ auto x = pow(8*random_double(), 1./3.);
+ sum += x*x / pdf(x);
+ }
+ std::cout << "I = " << sum/N << "\n";
+}
diff --git a/src/TheRestOfYourLife/main.cc b/src/TheRestOfYourLife/main.cc
index 6f5e6010..9b0859b5 100644
--- a/src/TheRestOfYourLife/main.cc
+++ b/src/TheRestOfYourLife/main.cc
@@ -57,12 +57,13 @@ vec3 ray_color(const ray& r, hittable *world, hittable *light_shape, int depth)
}
void cornell_box(hittable **scene, camera **cam, double aspect) {
- int i = 0;
- hittable **list = new hittable*[8];
material *red = new lambertian( new constant_texture(vec3(0.65, 0.05, 0.05)) );
material *white = new lambertian( new constant_texture(vec3(0.73, 0.73, 0.73)) );
material *green = new lambertian( new constant_texture(vec3(0.12, 0.45, 0.15)) );
material *light = new diffuse_light( new constant_texture(vec3(15, 15, 15)) );
+
+ hittable **list = new hittable*[8];
+ int i = 0;
list[i++] = new flip_normals(new yz_rect(0, 555, 0, 555, 555, green));
list[i++] = new yz_rect(0, 555, 0, 555, 0, red);
list[i++] = new flip_normals(new xz_rect(213, 343, 227, 332, 554, light));
@@ -74,6 +75,7 @@ void cornell_box(hittable **scene, camera **cam, double aspect) {
list[i++] = new translate(new rotate_y(
new box(vec3(0, 0, 0), vec3(165, 330, 165), white), 15), vec3(265,0,295));
*scene = new hittable_list(list,i);
+
vec3 lookfrom(278, 278, -800);
vec3 lookat(278, 278, 0);
auto dist_to_focus = 10.0;
diff --git a/src/TheRestOfYourLife/pdf.h b/src/TheRestOfYourLife/pdf.h
index ad442933..5a2d7527 100644
--- a/src/TheRestOfYourLife/pdf.h
+++ b/src/TheRestOfYourLife/pdf.h
@@ -35,17 +35,14 @@ inline vec3 random_to_sphere(double radius, double distance_squared) {
return vec3(x, y, z);
}
-
vec3 random_in_unit_sphere() {
vec3 p;
do {
- p = 2.0*vec3(random_double(),random_double(),random_double()) - vec3(1,1,1);
- } while (dot(p,p) >= 1.0);
+ p = 2*vec3(random_double(),random_double(),random_double()) - vec3(1,1,1);
+ } while (p.squared_length() >= 1);
return p;
}
-
-
class pdf {
public:
virtual double value(const vec3& direction) const = 0;
@@ -53,7 +50,6 @@ class pdf {
virtual ~pdf() {}
};
-
class cosine_pdf : public pdf {
public:
cosine_pdf(const vec3& w) { uvw.build_from_w(w); }
diff --git a/src/TheRestOfYourLife/pi.cc b/src/TheRestOfYourLife/pi.cc
new file mode 100644
index 00000000..3c368d08
--- /dev/null
+++ b/src/TheRestOfYourLife/pi.cc
@@ -0,0 +1,42 @@
+//==================================================================================================
+// Originally written in 2016 by Peter Shirley
+//
+// To the extent possible under law, the author(s) have dedicated all copyright and related and
+// neighboring rights to this software to the public domain worldwide. This software is distributed
+// without any warranty.
+//
+// You should have received a copy (see file COPYING.txt) of the CC0 Public Domain Dedication along
+// with this software. If not, see .
+//==================================================================================================
+
+#include "common/rtweekend.h"
+
+#include
+#include
+#include
+
+
+int main() {
+ int inside_circle = 0;
+ int inside_circle_stratified = 0;
+ int sqrt_N = 10000;
+ for (int i = 0; i < sqrt_N; i++) {
+ for (int j = 0; j < sqrt_N; j++) {
+ auto x = 2*random_double() - 1;
+ auto y = 2*random_double() - 1;
+ if (x*x + y*y < 1)
+ inside_circle++;
+ x = 2*((i + random_double()) / sqrt_N) - 1;
+ y = 2*((j + random_double()) / sqrt_N) - 1;
+ if (x*x + y*y < 1)
+ inside_circle_stratified++;
+ }
+ }
+
+ auto N = static_cast(sqrt_N) * sqrt_N;
+ std::cout
+ << "Regular Estimate of Pi = "
+ << 4*double(inside_circle) / N << '\n'
+ << "Stratified Estimate of Pi = "
+ << 4*double(inside_circle_stratified) / N << '\n';
+}
diff --git a/src/TheRestOfYourLife/sphere_importance.cc b/src/TheRestOfYourLife/sphere_importance.cc
new file mode 100644
index 00000000..f6d552f8
--- /dev/null
+++ b/src/TheRestOfYourLife/sphere_importance.cc
@@ -0,0 +1,42 @@
+//==================================================================================================
+// Originally written in 2016 by Peter Shirley
+//
+// To the extent possible under law, the author(s) have dedicated all copyright and related and
+// neighboring rights to this software to the public domain worldwide. This software is distributed
+// without any warranty.
+//
+// You should have received a copy (see file COPYING.txt) of the CC0 Public Domain Dedication along
+// with this software. If not, see .
+//==================================================================================================
+
+#include "common/rtweekend.h"
+
+#include
+#include
+#include
+
+
+vec3 random_on_unit_sphere() {
+ vec3 p;
+ double len_squared;
+ do {
+ p = 2*vec3(random_double(), random_double(), random_double()) - vec3(1,1,1);
+ len_squared = p.squared_length();
+ } while (len_squared >= 1);
+ return p / sqrt(len_squared);
+}
+
+inline double pdf(const vec3& p) {
+ return 1.0 / (4.0*pi);
+}
+
+int main() {
+ int N = 1000000;
+ auto sum = 0.0;
+ for (int i = 0; i < N; i++) {
+ vec3 d = random_on_unit_sphere();
+ auto cosine_squared = d.z()*d.z();
+ sum += cosine_squared / pdf(d);
+ }
+ std::cout << "I = " << sum/N << '\n';
+}
diff --git a/src/TheRestOfYourLife/sphere_plot.cc b/src/TheRestOfYourLife/sphere_plot.cc
new file mode 100644
index 00000000..d01f47f7
--- /dev/null
+++ b/src/TheRestOfYourLife/sphere_plot.cc
@@ -0,0 +1,27 @@
+//==================================================================================================
+// Originally written in 2016 by Peter Shirley
+//
+// To the extent possible under law, the author(s) have dedicated all copyright and related and
+// neighboring rights to this software to the public domain worldwide. This software is distributed
+// without any warranty.
+//
+// You should have received a copy (see file COPYING.txt) of the CC0 Public Domain Dedication along
+// with this software. If not, see .
+//==================================================================================================
+
+#include "common/rtweekend.h"
+
+#include
+#include
+
+
+int main() {
+ for (int i = 0; i < 2000; i++) {
+ auto r1 = random_double();
+ auto r2 = random_double();
+ auto x = cos(2*pi*r1)*2*sqrt(r2*(1-r2));
+ auto y = sin(2*pi*r1)*2*sqrt(r2*(1-r2));
+ auto z = 1 - 2*r2;
+ std::cout << x << " " << y << " " << z << '\n';
+ }
+}
diff --git a/style/book.css b/style/book.css
index e5028d31..3a60951d 100644
--- a/style/book.css
+++ b/style/book.css
@@ -131,6 +131,14 @@ body {
color: #a0a0a0;
}
+.md div.listingcaption {
+ margin-left: 3ex;
+}
+
+.md div.listingcaption kbd {
+ font-style: normal;
+}
+
/* -------------------------------------------------------------------------------------------------
** Images & Figures
** -----------------------------------------------------------------------------------------------*/
@@ -195,4 +203,9 @@ body {
.md pre.listing.tilde code {
font-size: 65%;
}
+
+ .md div.listingcaption.tilde {
+ margin-left: 5ex;
+ }
+
}