|
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