|
544 | 544 |
|
545 | 545 | $$ \int cos^2(\theta) $$ |
546 | 546 |
|
547 | | -<div class='together'> |
548 | 547 | By MC integration, we should just be able to sample $\cos^2(\theta) / p(\text{direction})$, but what |
549 | | -is direction in that context? We could make it based on polar coordinates, so $p$ would be in terms |
550 | | -of $(\theta, \phi)$. However you do it, remember that a PDF has to integrate to 1 and represent the |
551 | | -relative probability of that direction being sampled. We have a method from the last books to take |
552 | | -uniform random samples in or on a unit sphere: |
553 | | - |
554 | | - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
555 | | - vec3 random_unit_vector() { |
556 | | - auto a = random_double(0, 2*pi); |
557 | | - auto z = random_double(-1, 1); |
558 | | - auto r = sqrt(1 - z*z); |
559 | | - return vec3(r*cos(a), r*sin(a), z); |
560 | | - } |
561 | | - |
562 | | - ... |
563 | | - |
564 | | - vec3 random_in_unit_sphere() { |
565 | | - while (true) { |
566 | | - auto p = vec3::random(-1,1); |
567 | | - if (p.length_squared() >= 1) continue; |
568 | | - return p; |
569 | | - } |
570 | | - } |
571 | | - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
572 | | - [Listing [random-unit-vector]: <kbd>[vec3.h]</kbd> Random vector of unit length] |
573 | | -</div> |
| 548 | +is _direction_ in that context? We could make it based on polar coordinates, so $p$ would be in |
| 549 | +terms of $(\theta, \phi)$. However you do it, remember that a PDF has to integrate to 1 and |
| 550 | +represent the relative probability of that direction being sampled. Recall that we have vec3 |
| 551 | +functions to take uniform random samples in (`random_in_unit_sphere()`) or on |
| 552 | +(`random_unit_vector()`) a unit sphere. |
574 | 553 |
|
575 | 554 | <div class='together'> |
576 | 555 | Now what is the PDF of these uniform points? As a density on the unit sphere, it is $1/\text{area}$ |
|
757 | 736 |
|
758 | 737 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
759 | 738 | ... |
760 | | - color ray_color( |
| 739 | + color ray_color(...) { |
761 | 740 | ... |
| 741 | + } |
762 | 742 |
|
763 | 743 | hittable_list cornell_box() { |
764 | | - hittable_list world; |
| 744 | + hittable_list objects; |
765 | 745 |
|
766 | 746 | auto red = make_shared<lambertian>(color(.65, .05, .05)); |
767 | 747 | auto white = make_shared<lambertian>(color(.73, .73, .73)); |
768 | 748 | auto green = make_shared<lambertian>(color(.12, .45, .15)); |
769 | 749 | auto light = make_shared<diffuse_light>(color(15, 15, 15)); |
770 | 750 |
|
771 | | - world.add(make_shared<yz_rect>(0, 555, 0, 555, 555, green)); |
772 | | - world.add(make_shared<yz_rect>(0, 555, 0, 555, 0, red)); |
773 | | - world.add(make_shared<xz_rect>(213, 343, 227, 332, 554, light)); |
774 | | - world.add(make_shared<xz_rect>(0, 555, 0, 555, 555, white)); |
775 | | - world.add(make_shared<xz_rect>(0, 555, 0, 555, 0, white)); |
776 | | - world.add(make_shared<xy_rect>(0, 555, 0, 555, 555, white)); |
| 751 | + objects.add(make_shared<yz_rect>(0, 555, 0, 555, 555, green)); |
| 752 | + objects.add(make_shared<yz_rect>(0, 555, 0, 555, 0, red)); |
| 753 | + objects.add(make_shared<xz_rect>(213, 343, 227, 332, 554, light)); |
| 754 | + objects.add(make_shared<xz_rect>(0, 555, 0, 555, 555, white)); |
| 755 | + objects.add(make_shared<xz_rect>(0, 555, 0, 555, 0, white)); |
| 756 | + objects.add(make_shared<xy_rect>(0, 555, 0, 555, 555, white)); |
777 | 757 |
|
778 | 758 | shared_ptr<hittable> box1 = make_shared<box>(point3(0,0,0), point3(165,330,165), white); |
779 | 759 | box1 = make_shared<rotate_y>(box1, 15); |
780 | 760 | box1 = make_shared<translate>(box1, vec3(265,0,295)); |
781 | | - world.add(box1); |
| 761 | + objects.add(box1); |
782 | 762 |
|
783 | 763 | shared_ptr<hittable> box2 = make_shared<box>(point3(0,0,0), point3(165,165,165), white); |
784 | 764 | box2 = make_shared<rotate_y>(box2, -18); |
785 | 765 | box2 = make_shared<translate>(box2, vec3(130,0,65)); |
786 | | - world.add(box2); |
| 766 | + objects.add(box2); |
787 | 767 |
|
788 | | - return world; |
| 768 | + return objects; |
789 | 769 | } |
790 | 770 |
|
791 | 771 | int main() { |
|
799 | 779 |
|
800 | 780 | // World |
801 | 781 |
|
802 | | - auto lights = make_shared<hittable_list>(); |
803 | | - lights->add(make_shared<xz_rect>(213, 343, 227, 332, 554, shared_ptr<material>())); |
804 | | - lights->add(make_shared<sphere>(point3(190, 90, 190), 90, shared_ptr<material>())); |
805 | | - |
806 | 782 | auto world = cornell_box(); |
807 | 783 |
|
808 | 784 | color background(0,0,0); |
|
1524 | 1500 |
|
1525 | 1501 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1526 | 1502 | hittable_list cornell_box() { |
1527 | | - hittable_list world; |
| 1503 | + hittable_list objects; |
1528 | 1504 |
|
1529 | 1505 | auto red = make_shared<lambertian>(color(.65, .05, .05)); |
1530 | 1506 | auto white = make_shared<lambertian>(color(.73, .73, .73)); |
1531 | 1507 | auto green = make_shared<lambertian>(color(.12, .45, .15)); |
1532 | 1508 | auto light = make_shared<diffuse_light>(color(15, 15, 15)); |
1533 | 1509 |
|
1534 | | - world.add(make_shared<yz_rect>(0, 555, 0, 555, 555, green)); |
1535 | | - world.add(make_shared<yz_rect>(0, 555, 0, 555, 0, red)); |
| 1510 | + objects.add(make_shared<yz_rect>(0, 555, 0, 555, 555, green)); |
| 1511 | + objects.add(make_shared<yz_rect>(0, 555, 0, 555, 0, red)); |
1536 | 1512 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
1537 | | - world.add(make_shared<flip_face>(make_shared<xz_rect>(213, 343, 227, 332, 554, light))); |
| 1513 | + objects.add(make_shared<flip_face>(make_shared<xz_rect>(213, 343, 227, 332, 554, light))); |
1538 | 1514 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
1539 | | - world.add(make_shared<xz_rect>(0, 555, 0, 555, 555, white)); |
1540 | | - world.add(make_shared<xz_rect>(0, 555, 0, 555, 0, white)); |
1541 | | - world.add(make_shared<xy_rect>(0, 555, 0, 555, 555, white)); |
| 1515 | + objects.add(make_shared<xz_rect>(0, 555, 0, 555, 555, white)); |
| 1516 | + objects.add(make_shared<xz_rect>(0, 555, 0, 555, 0, white)); |
| 1517 | + objects.add(make_shared<xy_rect>(0, 555, 0, 555, 555, white)); |
1542 | 1518 |
|
1543 | 1519 | ... |
1544 | 1520 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
1690 | 1666 |
|
1691 | 1667 | return emitted |
1692 | 1668 | + albedo * rec.mat_ptr->scattering_pdf(r, rec, scattered) |
1693 | | - * ray_color(scattered, background, world, depth-1) |
1694 | | - / pdf_val; |
| 1669 | + * ray_color(scattered, background, world, depth-1) / pdf_val; |
1695 | 1670 | } |
1696 | 1671 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
1697 | 1672 | [Listing [ray-color-cos-pdf]: <kbd>[main.cc]</kbd> The ray_color function, using cosine pdf] |
|
1821 | 1796 |
|
1822 | 1797 | return emitted |
1823 | 1798 | + albedo * rec.mat_ptr->scattering_pdf(r, rec, scattered) |
1824 | | - * ray_color(scattered, background, world, depth-1) |
1825 | | - / pdf_val; |
| 1799 | + * ray_color(scattered, background, world, depth-1) / pdf_val; |
1826 | 1800 | } |
1827 | 1801 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
1828 | 1802 | [Listing [ray-color-hittable-pdf]: <kbd>[main.cc]</kbd> ray_color function with hittable PDF] |
|
1872 | 1846 | <div class='together'> |
1873 | 1847 | And plugging it into `ray_color()`: |
1874 | 1848 |
|
1875 | | - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
1876 | | - color ray_color( |
1877 | | - const ray& r, |
1878 | | - const color& background, |
1879 | | - const hittable& world, |
1880 | | - shared_ptr<hittable> lights, |
1881 | | - int depth |
1882 | | - ) { |
1883 | 1849 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
| 1850 | + color ray_color(const ray& r, const color& background, const hittable& world, int depth) { |
1884 | 1851 | hit_record rec; |
1885 | 1852 |
|
1886 | 1853 | // If we've exceeded the ray bounce limit, no more light is gathered. |
|
1912 | 1879 |
|
1913 | 1880 | return emitted |
1914 | 1881 | + albedo * rec.mat_ptr->scattering_pdf(r, rec, scattered) |
1915 | | - * ray_color(scattered, background, world, lights, depth-1) |
1916 | | - / pdf_val; |
| 1882 | + * ray_color(scattered, background, world, depth-1) / pdf_val; |
1917 | 1883 | } |
1918 | 1884 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
1919 | 1885 | [Listing [ray-color-mixture]: <kbd>[main.cc]</kbd> The ray_color function, using mixture PDF] |
|
1972 | 1938 |
|
1973 | 1939 |
|
1974 | 1940 |
|
1975 | | -Cleaning Up PDF Management. |
| 1941 | +Cleaning Up PDF Management |
1976 | 1942 | ==================================================================================================== |
1977 | 1943 |
|
1978 | 1944 | <div class='together'> |
|
2077 | 2043 | <div class='together'> |
2078 | 2044 | And `ray_color()` changes are small: |
2079 | 2045 |
|
2080 | | - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
| 2046 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
2081 | 2047 | color ray_color( |
2082 | 2048 | const ray& r, |
2083 | 2049 | const color& background, |
2084 | 2050 | const hittable& world, |
2085 | 2051 | shared_ptr<hittable> lights, |
2086 | 2052 | int depth |
2087 | 2053 | ) { |
| 2054 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
2088 | 2055 | hit_record rec; |
2089 | 2056 |
|
2090 | 2057 | // If we've exceeded the ray bounce limit, no more light is gathered. |
|
2109 | 2076 |
|
2110 | 2077 | return emitted |
2111 | 2078 | + srec.attenuation * rec.mat_ptr->scattering_pdf(r, rec, scattered) |
2112 | | - * ray_color(scattered, background, world, lights, depth-1) |
2113 | | - / pdf_val; |
| 2079 | + * ray_color(scattered, background, world, lights, depth-1) / pdf_val; |
2114 | 2080 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
2115 | 2081 | } |
| 2082 | + |
| 2083 | + ... |
| 2084 | + |
| 2085 | + int main() { |
| 2086 | + ... |
| 2087 | + // World |
| 2088 | + |
| 2089 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
| 2090 | + auto lights = make_shared<hittable_list>(); |
| 2091 | + lights->add(make_shared<xz_rect>(213, 343, 227, 332, 554, shared_ptr<material>())); |
| 2092 | + lights->add(make_shared<sphere>(point3(190, 90, 190), 90, shared_ptr<material>())); |
| 2093 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
| 2094 | + |
| 2095 | + auto world = cornell_box(); |
| 2096 | + |
| 2097 | + color background(0,0,0); |
| 2098 | + |
| 2099 | + for (int j = image_height-1; j >= 0; --j) { |
| 2100 | + std::cerr << "\rScanlines remaining: " << j << ' ' << std::flush; |
| 2101 | + for (int i = 0; i < image_width; ++i) { |
| 2102 | + ... |
| 2103 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
| 2104 | + pixel_color += ray_color(r, background, world, lights, max_depth); |
2116 | 2105 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
2117 | 2106 | [Listing [ray-color-scatter]: <kbd>[main.cc]</kbd> Ray color with scatter] |
2118 | 2107 | </div> |
|
2218 | 2207 |
|
2219 | 2208 | return emitted + srec.attenuation |
2220 | 2209 | * rec.mat_ptr->scattering_pdf(r, rec, scattered) |
2221 | | - * ray_color(scattered, background, world, lights, depth-1) |
2222 | | - / pdf_val; |
| 2210 | + * ray_color(scattered, background, world, lights, depth-1) / pdf_val; |
2223 | 2211 | } |
2224 | 2212 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
2225 | 2213 | [Listing [ray-color-implicit]: <kbd>[main.cc]</kbd> |
2226 | 2214 | Ray color function with implicitly-sampled rays] |
2227 | 2215 | </div> |
2228 | 2216 |
|
2229 | 2217 | <div class='together'> |
2230 | | -We also need to change the block to metal. |
| 2218 | +We also need to change the block to metal. We'll also swap out the short block for a glass sphere. |
2231 | 2219 |
|
2232 | 2220 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
2233 | | - hittable_list cornell_box(camera& cam, double aspect) { |
2234 | | - hittable_list world; |
| 2221 | + hittable_list cornell_box() { |
| 2222 | + hittable_list objects; |
2235 | 2223 |
|
2236 | 2224 | auto red = make_shared<lambertian>(color(.65, .05, .05)); |
2237 | 2225 | auto white = make_shared<lambertian>(color(.73, .73, .73)); |
2238 | 2226 | auto green = make_shared<lambertian>(color(.12, .45, .15)); |
2239 | 2227 | auto light = make_shared<diffuse_light>(color(15, 15, 15)); |
2240 | 2228 |
|
2241 | | - world.add(make_shared<yz_rect>(0, 555, 0, 555, 555, green)); |
2242 | | - world.add(make_shared<yz_rect>(0, 555, 0, 555, 0, red)); |
2243 | | - world.add(make_shared<xz_rect>(213, 343, 227, 332, 554, light)); |
2244 | | - world.add(make_shared<xz_rect>(0, 555, 0, 555, 555, white)); |
2245 | | - world.add(make_shared<xz_rect>(0, 555, 0, 555, 0, white)); |
2246 | | - world.add(make_shared<xy_rect>(0, 555, 0, 555, 555, white)); |
| 2229 | + objects.add(make_shared<yz_rect>(0, 555, 0, 555, 555, green)); |
| 2230 | + objects.add(make_shared<yz_rect>(0, 555, 0, 555, 0, red)); |
| 2231 | + objects.add(make_shared<flip_face>(make_shared<xz_rect>(213, 343, 227, 332, 554, light))); |
| 2232 | + objects.add(make_shared<xz_rect>(0, 555, 0, 555, 555, white)); |
| 2233 | + objects.add(make_shared<xz_rect>(0, 555, 0, 555, 0, white)); |
| 2234 | + objects.add(make_shared<xy_rect>(0, 555, 0, 555, 555, white)); |
2247 | 2235 |
|
2248 | 2236 |
|
2249 | 2237 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
|
2252 | 2240 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
2253 | 2241 | box1 = make_shared<rotate_y>(box1, 15); |
2254 | 2242 | box1 = make_shared<translate>(box1, vec3(265,0,295)); |
2255 | | - world.add(box1); |
2256 | | - |
2257 | | - shared_ptr<hittable> box2 = make_shared<box>(point3(0,0,0), point3(165,165,165), white); |
2258 | | - box2 = make_shared<rotate_y>(box2, -18); |
2259 | | - box2 = make_shared<translate>(box2, vec3(130,0,65); |
2260 | | - world.add(box2); |
| 2243 | + objects.add(box1); |
2261 | 2244 |
|
2262 | | - point3 lookfrom(278, 278, -800); |
2263 | | - point3 lookat(278, 278, 0); |
2264 | | - vec3 vup(0, 1, 0); |
2265 | | - auto dist_to_focus = 10.0; |
2266 | | - auto aperture = 0.0; |
2267 | | - auto vfov = 40.0; |
2268 | | - auto time0 = 0.0; |
2269 | | - auto time1 = 1.0; |
2270 | 2245 |
|
2271 | | - cam = camera(lookfrom, lookat, vup, vfov, aspect, aperture, dist_to_focus, time0, time1); |
| 2246 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
| 2247 | + auto glass = make_shared<dielectric>(1.5); |
| 2248 | + objects.add(make_shared<sphere>(point3(190,90,190), 90 , glass)); |
| 2249 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
2272 | 2250 |
|
2273 | | - return world; |
| 2251 | + return objects; |
2274 | 2252 | } |
2275 | 2253 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
2276 | 2254 | [Listing [scene-cornell-al]: <kbd>[main.cc]</kbd> Cornell box scene with aluminum material] |
|
2511 | 2489 | auto g = pixel_color.y(); |
2512 | 2490 | auto b = pixel_color.z(); |
2513 | 2491 |
|
| 2492 | + |
2514 | 2493 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
2515 | 2494 | // Replace NaN components with zero. See explanation in Ray Tracing: The Rest of Your Life. |
2516 | 2495 | if (r != r) r = 0.0; |
|
0 commit comments