|
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