|
396 | 396 | #include <iostream> |
397 | 397 | #include "ray.h" |
398 | 398 |
|
399 | | - vec3 color(const ray& r, hitable *world, int depth) { |
| 399 | + vec3 color(const ray& r, hittable *world, int depth) { |
400 | 400 | vec3 unit_direction = unit_vector(r.direction()); |
401 | 401 | float t = 0.5*(unit_direction.y() + 1.0); |
402 | 402 | return (1.0-t)*vec3(1.0, 1.0, 1.0) + t*vec3(0.5, 0.7, 1.0); |
|
601 | 601 | solution is the make an “abstract class” for anything a ray might hit and make both a sphere and a |
602 | 602 | list of spheres just something you can hit. What that class should be called is something of a |
603 | 603 | quandary -- calling it an “object” would be good if not for “object oriented” programming. “Surface” |
604 | | -is often used, with the weakness being maybe we will want volumes. “Hitable” emphasizes the member |
605 | | -function that unites them. I don’t love any of these but I will go with “hitable”. |
| 604 | +is often used, with the weakness being maybe we will want volumes. “hittable” emphasizes the member |
| 605 | +function that unites them. I don’t love any of these but I will go with “hittable”. |
606 | 606 |
|
607 | 607 | <div class='together'> |
608 | | -This `hitable` abstract class will have a hit function that takes in a ray. Most ray tracers have |
| 608 | +This `hittable` abstract class will have a hit function that takes in a ray. Most ray tracers have |
609 | 609 | found it convenient to add a valid interval for hits $t_{min}$ to $t_{max}$, so the hit only |
610 | 610 | “counts” if $t_{min} < t < t_{max}$. For the initial rays this is positive $t$, but as we will see, |
611 | 611 | it can help some details in the code to have an interval $t_{min}$ to $t_{max}$. One design question |
|
615 | 615 | we’ll want motion blur at some point, so I’ll add a time input variable. Here’s the abstract class: |
616 | 616 |
|
617 | 617 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
618 | | - #ifndef HITABLEH |
619 | | - #define HITABLEH |
| 618 | + #ifndef HITTABLEH |
| 619 | + #define HITTABLEH |
620 | 620 |
|
621 | 621 | #include "ray.h" |
622 | 622 |
|
|
627 | 627 | vec3 normal; |
628 | 628 | }; |
629 | 629 |
|
630 | | - class hitable { |
| 630 | + class hittable { |
631 | 631 | public: |
632 | 632 | virtual bool hit( |
633 | 633 | const ray& r, float t_min, float t_max, hit_record& rec) const = 0; |
|
644 | 644 | #ifndef SPHEREH |
645 | 645 | #define SPHEREH |
646 | 646 |
|
647 | | - #include "hitable.h" |
| 647 | + #include "hittable.h" |
648 | 648 |
|
649 | | - class sphere: public hitable { |
| 649 | + class sphere: public hittable { |
650 | 650 | public: |
651 | 651 | sphere() {} |
652 | 652 | sphere(vec3 cen, float r) : center(cen), radius(r) {}; |
|
690 | 690 | And a list of objects: |
691 | 691 |
|
692 | 692 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
693 | | - #ifndef HITABLELISTH |
694 | | - #define HITABLELISTH |
| 693 | + #ifndef HITTABLELISTH |
| 694 | + #define HITTABLELISTH |
695 | 695 |
|
696 | | - #include "hitable.h" |
| 696 | + #include "hittable.h" |
697 | 697 |
|
698 | | - class hitable_list: public hitable { |
| 698 | + class hittable_list: public hittable { |
699 | 699 | public: |
700 | | - hitable_list() {} |
701 | | - hitable_list(hitable **l, int n) {list = l; list_size = n; } |
| 700 | + hittable_list() {} |
| 701 | + hittable_list(hittable **l, int n) {list = l; list_size = n; } |
702 | 702 | virtual bool hit( |
703 | 703 | const ray& r, float tmin, float tmax, hit_record& rec) const; |
704 | | - hitable **list; |
| 704 | + hittable **list; |
705 | 705 | int list_size; |
706 | 706 | }; |
707 | 707 |
|
708 | | - bool hitable_list::hit( |
| 708 | + bool hittable_list::hit( |
709 | 709 | const ray& r, float t_min, float t_max, hit_record& rec) const { |
710 | 710 |
|
711 | 711 | hit_record temp_rec; |
|
731 | 731 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
732 | 732 | #include <iostream> |
733 | 733 | #include "sphere.h" |
734 | | - #include "hitable_list.h" |
| 734 | + #include "hittable_list.h" |
735 | 735 | #include "float.h" |
736 | 736 |
|
737 | | - vec3 color(const ray& r, hitable *world) { |
| 737 | + vec3 color(const ray& r, hittable *world) { |
738 | 738 | hit_record rec; |
739 | 739 | if (world->hit(r, 0.0, MAXFLOAT, rec)) { |
740 | 740 | return 0.5*vec3(rec.normal.x()+1, rec.normal.y()+1, rec.normal.z()+1); |
|
754 | 754 | vec3 horizontal(4.0, 0.0, 0.0); |
755 | 755 | vec3 vertical(0.0, 2.0, 0.0); |
756 | 756 | vec3 origin(0.0, 0.0, 0.0); |
757 | | - hitable *list[2]; |
| 757 | + hittable *list[2]; |
758 | 758 | list[0] = new sphere(vec3(0,0,-1), 0.5); |
759 | 759 | list[1] = new sphere(vec3(0,-100.5,-1), 100); |
760 | | - hitable *world = new hitable_list(list,2); |
| 760 | + hittable *world = new hittable_list(list,2); |
761 | 761 | for (int j = ny-1; j >= 0; j--) { |
762 | 762 | for (int i = 0; i < nx; i++) { |
763 | 763 | float u = float(i) / float(nx); |
|
892 | 892 | int ny = 100; |
893 | 893 | int ns = 100; |
894 | 894 | std::cout << "P3\n" << nx << " " << ny << "\n255\n"; |
895 | | - hitable *list[2]; |
| 895 | + hittable *list[2]; |
896 | 896 | list[0] = new sphere(vec3(0,0,-1), 0.5); |
897 | 897 | list[1] = new sphere(vec3(0,-100.5,-1), 100); |
898 | | - hitable *world = new hitable_list(list,2); |
| 898 | + hittable *world = new hittable_list(list,2); |
899 | 899 | camera cam; |
900 | 900 | for (int j = ny-1; j >= 0; j--) { |
901 | 901 | for (int i = 0; i < nx; i++) { |
|
982 | 982 | Then update the `color()` function to use the new random direction generator: |
983 | 983 |
|
984 | 984 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
985 | | - vec3 color(const ray& r, hitable *world, int depth) { |
| 985 | + vec3 color(const ray& r, hittable *world, int depth) { |
986 | 986 | hit_record rec; |
987 | 987 | if (world->hit(r, 0.0, MAXFLOAT, rec)) { |
988 | 988 | vec3 target = rec.p + rec.normal + random_in_unit_sphere(); |
|
1072 | 1072 |
|
1073 | 1073 | <div class='together'> |
1074 | 1074 | The `hit_record` is to avoid a bunch of arguments so we can stuff whatever info we want in there. |
1075 | | -You can use arguments instead; it’s a matter of taste. Hitables and materials need to know each |
| 1075 | +You can use arguments instead; it’s a matter of taste. Hittables and materials need to know each |
1076 | 1076 | other so there is some circularity of the references. In C++ you just need to alert the compiler |
1077 | | -that the pointer is to a class, which the “class material” in the hitable class below does: |
| 1077 | +that the pointer is to a class, which the “class material” in the hittable class below does: |
1078 | 1078 |
|
1079 | 1079 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1080 | | - #ifndef HITABLEH |
1081 | | - #define HITABLEH |
| 1080 | + #ifndef HITTABLEH |
| 1081 | + #define HITTABLEH |
1082 | 1082 | #include "ray.h" |
1083 | 1083 |
|
1084 | 1084 | class material; |
|
1091 | 1091 | material *mat_ptr; |
1092 | 1092 | }; |
1093 | 1093 |
|
1094 | | - class hitable { |
| 1094 | + class hittable { |
1095 | 1095 | public: |
1096 | 1096 | virtual bool hit( |
1097 | 1097 | const ray& r, float t_min, float t_max, hit_record& rec) const = 0; |
|
1113 | 1113 | within `hit_record`. See the lines below marked with **`/* NEW */`**. |
1114 | 1114 |
|
1115 | 1115 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1116 | | - class sphere: public hitable { |
| 1116 | + class sphere: public hittable { |
1117 | 1117 | public: |
1118 | 1118 | sphere() {} |
1119 | 1119 | sphere(vec3 cen, float r, material *m) |
|
1223 | 1223 | We need to modify the color function to use this: |
1224 | 1224 |
|
1225 | 1225 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1226 | | - vec3 color(const ray& r, hitable *world, int depth) { |
| 1226 | + vec3 color(const ray& r, hittable *world, int depth) { |
1227 | 1227 | hit_record rec; |
1228 | 1228 | if (world->hit(r, 0.001, MAXFLOAT, rec)) { |
1229 | 1229 | ray scattered; |
|
1254 | 1254 | int ny = 100; |
1255 | 1255 | int ns = 100; |
1256 | 1256 | std::cout << "P3\n" << nx << " " << ny << "\n255\n"; |
1257 | | - hitable *list[4]; |
| 1257 | + hittable *list[4]; |
1258 | 1258 | list[0] = new sphere(vec3(0,0,-1), 0.5, new lambertian(vec3(0.1, 0.2, 0.5))); |
1259 | 1259 | list[1] = new sphere(vec3(0,-100.5,-1), 100, new lambertian(vec3(0.8, 0.8, 0.0))); |
1260 | 1260 | list[2] = new sphere(vec3(1,0,-1), 0.5, new metal(vec3(0.8, 0.6, 0.2), 0.0)); |
1261 | 1261 | list[3] = new sphere(vec3(-1,0,-1), 0.5, new metal(vec3(0.8, 0.8, 0.8))); |
1262 | | - hitable *world = new hitable_list(list,4); |
| 1262 | + hittable *world = new hittable_list(list,4); |
1263 | 1263 | camera cam; |
1264 | 1264 | for (int j = ny-1; j >= 0; j--) { |
1265 | 1265 | for (int i = 0; i < nx; i++) { |
|
1598 | 1598 | float R = cos(M_PI/4); |
1599 | 1599 | list[0] = new sphere(vec3(-R,0,-1), R, new lambertian(vec3(0, 0, 1))); |
1600 | 1600 | list[1] = new sphere(vec3( R,0,-1), R, new lambertian(vec3(1, 0, 0))); |
1601 | | - hitable *world = new hitable_list(list,2); |
| 1601 | + hittable *world = new hittable_list(list,2); |
1602 | 1602 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
1603 | 1603 |
|
1604 | 1604 | gives: |
|
1800 | 1800 | First let’s make the image on the cover of this book -- lots of random spheres: |
1801 | 1801 |
|
1802 | 1802 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1803 | | - hitable *random_scene() { |
| 1803 | + hittable *random_scene() { |
1804 | 1804 | int n = 500; |
1805 | | - hitable **list = new hitable*[n+1]; |
| 1805 | + hittable **list = new hittable*[n+1]; |
1806 | 1806 | list[0] = new sphere(vec3(0,-1000,0), 1000, new lambertian(vec3(0.5, 0.5, 0.5))); |
1807 | 1807 | int i = 1; |
1808 | 1808 | for (int a = -11; a < 11; a++) { |
|
1836 | 1836 | list[i++] = new sphere(vec3(-4, 1, 0), 1.0, new lambertian(vec3(0.4, 0.2, 0.1))); |
1837 | 1837 | list[i++] = new sphere(vec3(4, 1, 0), 1.0, new metal(vec3(0.7, 0.6, 0.5), 0.0)); |
1838 | 1838 |
|
1839 | | - return new hitable_list(list,i); |
| 1839 | + return new hittable_list(list,i); |
1840 | 1840 | } |
1841 | 1841 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
1842 | 1842 | </div> |
|
1872 | 1872 | blog. |
1873 | 1873 |
|
1874 | 1874 | 6. Volumes and media. Cool stuff and will challenge your software architecture. I favor making |
1875 | | - volumes have the hitable interface and probabilistically have intersections based on density. |
| 1875 | + volumes have the hittable interface and probabilistically have intersections based on density. |
1876 | 1876 | Your rendering code doesn’t even have to know it has volumes with that method. |
1877 | 1877 |
|
1878 | 1878 | 7. Parallelism. Run $N$ copies of your code on $N$ cores with different random seeds. Average the |
|
0 commit comments