|
398 | 398 | #include <iostream> |
399 | 399 | #include "ray.h" |
400 | 400 |
|
401 | | - vec3 color(const ray& r, hitable *world, int depth) { |
| 401 | + vec3 color(const ray& r, hittable *world, int depth) { |
402 | 402 | vec3 unit_direction = unit_vector(r.direction()); |
403 | 403 | float t = 0.5*(unit_direction.y() + 1.0); |
404 | 404 | return (1.0-t)*vec3(1.0, 1.0, 1.0) + t*vec3(0.5, 0.7, 1.0); |
|
617 | 617 | solution is the make an “abstract class” for anything a ray might hit and make both a sphere and a |
618 | 618 | list of spheres just something you can hit. What that class should be called is something of a |
619 | 619 | quandary -- calling it an “object” would be good if not for “object oriented” programming. “Surface” |
620 | | -is often used, with the weakness being maybe we will want volumes. “Hitable” emphasizes the member |
621 | | -function that unites them. I don’t love any of these but I will go with “hitable”. |
| 620 | +is often used, with the weakness being maybe we will want volumes. “hittable” emphasizes the member |
| 621 | +function that unites them. I don’t love any of these but I will go with “hittable”. |
622 | 622 |
|
623 | 623 | <div class='together'> |
624 | | -This `hitable` abstract class will have a hit function that takes in a ray. Most ray tracers have |
| 624 | +This `hittable` abstract class will have a hit function that takes in a ray. Most ray tracers have |
625 | 625 | found it convenient to add a valid interval for hits $t_{min}$ to $t_{max}$, so the hit only |
626 | 626 | “counts” if $t_{min} < t < t_{max}$. For the initial rays this is positive $t$, but as we will see, |
627 | 627 | it can help some details in the code to have an interval $t_{min}$ to $t_{max}$. One design question |
|
631 | 631 | we’ll want motion blur at some point, so I’ll add a time input variable. Here’s the abstract class: |
632 | 632 |
|
633 | 633 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
634 | | - #ifndef HITABLEH |
635 | | - #define HITABLEH |
| 634 | + #ifndef HITTABLEH |
| 635 | + #define HITTABLEH |
636 | 636 |
|
637 | 637 | #include "ray.h" |
638 | 638 |
|
|
643 | 643 | vec3 normal; |
644 | 644 | }; |
645 | 645 |
|
646 | | - class hitable { |
| 646 | + class hittable { |
647 | 647 | public: |
648 | 648 | virtual bool hit( |
649 | 649 | const ray& r, float t_min, float t_max, hit_record& rec) const = 0; |
|
660 | 660 | #ifndef SPHEREH |
661 | 661 | #define SPHEREH |
662 | 662 |
|
663 | | - #include "hitable.h" |
| 663 | + #include "hittable.h" |
664 | 664 |
|
665 | | - class sphere: public hitable { |
| 665 | + class sphere: public hittable { |
666 | 666 | public: |
667 | 667 | sphere() {} |
668 | 668 | sphere(vec3 cen, float r) : center(cen), radius(r) {}; |
|
706 | 706 | And a list of objects: |
707 | 707 |
|
708 | 708 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
709 | | - #ifndef HITABLELISTH |
710 | | - #define HITABLELISTH |
| 709 | + #ifndef HITTABLELISTH |
| 710 | + #define HITTABLELISTH |
711 | 711 |
|
712 | | - #include "hitable.h" |
| 712 | + #include "hittable.h" |
713 | 713 |
|
714 | | - class hitable_list: public hitable { |
| 714 | + class hittable_list: public hittable { |
715 | 715 | public: |
716 | | - hitable_list() {} |
717 | | - hitable_list(hitable **l, int n) {list = l; list_size = n; } |
| 716 | + hittable_list() {} |
| 717 | + hittable_list(hittable **l, int n) {list = l; list_size = n; } |
718 | 718 | virtual bool hit( |
719 | 719 | const ray& r, float tmin, float tmax, hit_record& rec) const; |
720 | | - hitable **list; |
| 720 | + hittable **list; |
721 | 721 | int list_size; |
722 | 722 | }; |
723 | 723 |
|
724 | | - bool hitable_list::hit( |
| 724 | + bool hittable_list::hit( |
725 | 725 | const ray& r, float t_min, float t_max, hit_record& rec) const { |
726 | 726 |
|
727 | 727 | hit_record temp_rec; |
|
747 | 747 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
748 | 748 | #include <iostream> |
749 | 749 | #include "sphere.h" |
750 | | - #include "hitable_list.h" |
| 750 | + #include "hittable_list.h" |
751 | 751 | #include "float.h" |
752 | 752 |
|
753 | 753 |
|
754 | 754 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
755 | | - vec3 color(const ray& r, hitable *world) { |
| 755 | + vec3 color(const ray& r, hittable *world) { |
756 | 756 | hit_record rec; |
757 | 757 | if (world->hit(r, 0.0, MAXFLOAT, rec)) { |
758 | 758 | return 0.5*vec3(rec.normal.x()+1, rec.normal.y()+1, rec.normal.z()+1); |
|
778 | 778 |
|
779 | 779 |
|
780 | 780 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
781 | | - hitable *list[2]; |
| 781 | + hittable *list[2]; |
782 | 782 | list[0] = new sphere(vec3(0,0,-1), 0.5); |
783 | 783 | list[1] = new sphere(vec3(0,-100.5,-1), 100); |
784 | | - hitable *world = new hitable_list(list,2); |
| 784 | + hittable *world = new hittable_list(list,2); |
785 | 785 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
786 | 786 |
|
787 | 787 | for (int j = ny-1; j >= 0; j--) { |
|
925 | 925 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
926 | 926 | std::cout << "P3\n" << nx << " " << ny << "\n255\n"; |
927 | 927 |
|
928 | | - hitable *list[2]; |
| 928 | + hittable *list[2]; |
929 | 929 | list[0] = new sphere(vec3(0,0,-1), 0.5); |
930 | 930 | list[1] = new sphere(vec3(0,-100.5,-1), 100); |
931 | | - hitable *world = new hitable_list(list,2); |
| 931 | + hittable *world = new hittable_list(list,2); |
932 | 932 |
|
933 | 933 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
934 | 934 | camera cam; |
|
1022 | 1022 | Then update the `color()` function to use the new random direction generator: |
1023 | 1023 |
|
1024 | 1024 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1025 | | - vec3 color(const ray& r, hitable *world, int depth) { |
| 1025 | + vec3 color(const ray& r, hittable *world, int depth) { |
1026 | 1026 | hit_record rec; |
1027 | 1027 | if (world->hit(r, 0.0, MAXFLOAT, rec)) { |
1028 | 1028 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
|
1114 | 1114 |
|
1115 | 1115 | <div class='together'> |
1116 | 1116 | The `hit_record` is to avoid a bunch of arguments so we can stuff whatever info we want in there. |
1117 | | -You can use arguments instead; it’s a matter of taste. Hitables and materials need to know each |
| 1117 | +You can use arguments instead; it’s a matter of taste. Hittables and materials need to know each |
1118 | 1118 | other so there is some circularity of the references. In C++ you just need to alert the compiler |
1119 | | -that the pointer is to a class, which the “class material” in the hitable class below does: |
| 1119 | +that the pointer is to a class, which the “class material” in the hittable class below does: |
1120 | 1120 |
|
1121 | 1121 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1122 | | - #ifndef HITABLEH |
1123 | | - #define HITABLEH |
| 1122 | + #ifndef HITTABLEH |
| 1123 | + #define HITTABLEH |
1124 | 1124 | #include "ray.h" |
1125 | 1125 |
|
1126 | 1126 | class material; |
|
1133 | 1133 | material *mat_ptr; |
1134 | 1134 | }; |
1135 | 1135 |
|
1136 | | - class hitable { |
| 1136 | + class hittable { |
1137 | 1137 | public: |
1138 | 1138 | virtual bool hit( |
1139 | 1139 | const ray& r, float t_min, float t_max, hit_record& rec) const = 0; |
|
1155 | 1155 | within `hit_record`. See the lines below marked with **`/* NEW */`**. |
1156 | 1156 |
|
1157 | 1157 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1158 | | - class sphere: public hitable { |
| 1158 | + class sphere: public hittable { |
1159 | 1159 | public: |
1160 | 1160 | sphere() {} |
1161 | 1161 | sphere(vec3 cen, float r, material *m) |
|
1265 | 1265 | We need to modify the color function to use this: |
1266 | 1266 |
|
1267 | 1267 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1268 | | - vec3 color(const ray& r, hitable *world, int depth) { |
| 1268 | + vec3 color(const ray& r, hittable *world, int depth) { |
1269 | 1269 | hit_record rec; |
1270 | 1270 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
1271 | 1271 | if (world->hit(r, 0.001, MAXFLOAT, rec)) { |
|
1301 | 1301 |
|
1302 | 1302 |
|
1303 | 1303 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
1304 | | - hitable *list[4]; |
| 1304 | + hittable *list[4]; |
1305 | 1305 | list[0] = new sphere(vec3(0,0,-1), 0.5, new lambertian(vec3(0.1, 0.2, 0.5))); |
1306 | 1306 | list[1] = new sphere(vec3(0,-100.5,-1), 100, new lambertian(vec3(0.8, 0.8, 0.0))); |
1307 | 1307 | list[2] = new sphere(vec3(1,0,-1), 0.5, new metal(vec3(0.8, 0.6, 0.2), 0.0)); |
1308 | 1308 | list[3] = new sphere(vec3(-1,0,-1), 0.5, new metal(vec3(0.8, 0.8, 0.8))); |
1309 | | - hitable *world = new hitable_list(list,4); |
| 1309 | + hittable *world = new hittable_list(list,4); |
1310 | 1310 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1311 | 1311 |
|
1312 | 1312 | camera cam; |
|
1677 | 1677 | float R = cos(M_PI/4); |
1678 | 1678 | list[0] = new sphere(vec3(-R,0,-1), R, new lambertian(vec3(0, 0, 1))); |
1679 | 1679 | list[1] = new sphere(vec3( R,0,-1), R, new lambertian(vec3(1, 0, 0))); |
1680 | | - hitable *world = new hitable_list(list,2); |
| 1680 | + hittable *world = new hittable_list(list,2); |
1681 | 1681 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
1682 | 1682 |
|
1683 | 1683 | gives: |
|
1893 | 1893 | First let’s make the image on the cover of this book -- lots of random spheres: |
1894 | 1894 |
|
1895 | 1895 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1896 | | - hitable *random_scene() { |
| 1896 | + hittable *random_scene() { |
1897 | 1897 | int n = 500; |
1898 | | - hitable **list = new hitable*[n+1]; |
| 1898 | + hittable **list = new hittable*[n+1]; |
1899 | 1899 | list[0] = new sphere(vec3(0,-1000,0), 1000, new lambertian(vec3(0.5, 0.5, 0.5))); |
1900 | 1900 | int i = 1; |
1901 | 1901 | for (int a = -11; a < 11; a++) { |
|
1929 | 1929 | list[i++] = new sphere(vec3(-4, 1, 0), 1.0, new lambertian(vec3(0.4, 0.2, 0.1))); |
1930 | 1930 | list[i++] = new sphere(vec3(4, 1, 0), 1.0, new metal(vec3(0.7, 0.6, 0.5), 0.0)); |
1931 | 1931 |
|
1932 | | - return new hitable_list(list,i); |
| 1932 | + return new hittable_list(list,i); |
1933 | 1933 | } |
1934 | 1934 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
1935 | 1935 | </div> |
|
1965 | 1965 | blog. |
1966 | 1966 |
|
1967 | 1967 | 6. Volumes and media. Cool stuff and will challenge your software architecture. I favor making |
1968 | | - volumes have the hitable interface and probabilistically have intersections based on density. |
| 1968 | + volumes have the hittable interface and probabilistically have intersections based on density. |
1969 | 1969 | Your rendering code doesn’t even have to know it has volumes with that method. |
1970 | 1970 |
|
1971 | 1971 | 7. Parallelism. Run $N$ copies of your code on $N$ cores with different random seeds. Average the |
|
0 commit comments