|
90 | 90 |
|
91 | 91 | std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n"; |
92 | 92 |
|
93 | | - for (int j = image_height-1; j >= 0; --j) { |
| 93 | + for (int j = 0; j < image_height; ++j) { |
94 | 94 | for (int i = 0; i < image_width; ++i) { |
95 | 95 | auto r = double(i) / (image_width-1); |
96 | 96 | auto g = double(j) / (image_height-1); |
|
189 | 189 | instead write to the logging output stream (`std::clog`): |
190 | 190 |
|
191 | 191 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
192 | | - for (int j = image_height-1; j >= 0; --j) { |
| 192 | + for (int j = 0; j < image_height; ++j) { |
193 | 193 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
194 | | - std::clog << "\rScanlines remaining: " << j << ' ' << std::flush; |
| 194 | + std::clog << "\rScanlines remaining: " << (image_height - j) << ' ' << std::flush; |
195 | 195 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
196 | 196 | for (int i = 0; i < image_width; ++i) { |
197 | 197 | auto r = double(i) / (image_width-1); |
|
401 | 401 |
|
402 | 402 | std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n"; |
403 | 403 |
|
404 | | - for (int j = image_height-1; j >= 0; --j) { |
405 | | - std::clog << "\rScanlines remaining: " << j << ' ' << std::flush; |
| 404 | + for (int j = 0; j < image_height; ++j) { |
| 405 | + std::clog << "\rScanlines remaining: " << (image_height - j) << ' ' << std::flush; |
406 | 406 | for (int i = 0; i < image_width; ++i) { |
407 | 407 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
408 | 408 | color pixel_color(double(i)/(image_width-1), double(j)/(image_height-1), 0.25); |
|
484 | 484 | often, so I’ll use a non-square image. For now we'll use a 16:9 aspect ratio, since that's so |
485 | 485 | common. |
486 | 486 |
|
| 487 | + |
487 | 488 | In addition to setting up the pixel dimensions for the rendered image, we also need to set up a |
488 | 489 | virtual viewport through which to pass our scene rays. For the standard pixel spacing (equally |
489 | 490 | spaced in both the horizontal and vertical direction), the viewport's aspect ratio should be the |
|
547 | 548 |
|
548 | 549 | std::cout << "P3\n" << image_width << " " << image_height << "\n255\n"; |
549 | 550 |
|
550 | | - for (int j = image_height-1; j >= 0; --j) { |
551 | | - std::clog << "\rScanlines remaining: " << j << ' ' << std::flush; |
| 551 | + for (int j = 0; j < image_height; ++j) { |
| 552 | + std::clog << "\rScanlines remaining: " << (image_height - j) << ' ' << std::flush; |
552 | 553 | for (int i = 0; i < image_width; ++i) { |
553 | 554 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
554 | | - auto u = double(i) / (image_width-1); |
555 | | - auto v = double(j) / (image_height-1); |
556 | | - ray r(origin, lower_left_corner + u*horizontal + v*vertical - origin); |
| 555 | + auto s = double(i) / (image_width-1); |
| 556 | + auto t = double(j) / (image_height-1); |
| 557 | + ray r(origin, lower_left_corner + s*horizontal + (1-t)*vertical - origin); |
557 | 558 | color pixel_color = ray_color(r); |
558 | 559 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
559 | 560 | write_color(std::cout, pixel_color); |
|
1253 | 1254 |
|
1254 | 1255 | std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n"; |
1255 | 1256 |
|
1256 | | - for (int j = image_height-1; j >= 0; --j) { |
1257 | | - std::clog << "\rScanlines remaining: " << j << ' ' << std::flush; |
| 1257 | + for (int j = 0; j < image_height; ++j) { |
| 1258 | + std::clog << "\rScanlines remaining: " << (image_height - j) << ' ' << std::flush; |
1258 | 1259 | for (int i = 0; i < image_width; ++i) { |
1259 | | - auto u = double(i) / (image_width-1); |
1260 | | - auto v = double(j) / (image_height-1); |
1261 | | - ray r(origin, lower_left_corner + u*horizontal + v*vertical); |
| 1260 | + auto s = double(i) / (image_width-1); |
| 1261 | + auto t = double(j) / (image_height-1); |
| 1262 | + ray r(origin, lower_left_corner + s*horizontal + (1-t)*vertical); |
1262 | 1263 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
1263 | 1264 | color pixel_color = ray_color(r, world); |
1264 | 1265 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
|
1489 | 1490 | } |
1490 | 1491 |
|
1491 | 1492 | ray get_ray(double s, double t) const { |
1492 | | - return ray(origin, lower_left_corner + s*horizontal + t*vertical - origin); |
| 1493 | + // Return the ray from the projection point to the indicated pixel. Coordinates s,t are |
| 1494 | + // the normalized image-based coordinates of the pixel. Image left is s=0, image right |
| 1495 | + // is s=1, image top is t=0, image bottom is t=1. |
| 1496 | + |
| 1497 | + return ray(origin, lower_left_corner + s*horizontal + (1-t)*vertical - origin); |
1493 | 1498 | } |
1494 | 1499 |
|
1495 | 1500 | private: |
|
1590 | 1595 |
|
1591 | 1596 | std::cout << "P3\n" << image_width << " " << image_height << "\n255\n"; |
1592 | 1597 |
|
1593 | | - for (int j = image_height-1; j >= 0; --j) { |
1594 | | - std::clog << "\rScanlines remaining: " << j << ' ' << std::flush; |
| 1598 | + for (int j = 0; j < image_height; ++j) { |
| 1599 | + std::clog << "\rScanlines remaining: " << (image_height - j) << ' ' << std::flush; |
| 1600 | + auto t = (j + random_double()) / (image_height-1); |
| 1601 | + |
1595 | 1602 | for (int i = 0; i < image_width; ++i) { |
1596 | 1603 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
1597 | 1604 | color pixel_color(0, 0, 0); |
1598 | 1605 | for (int sample = 0; sample < samples_per_pixel; ++sample) { |
1599 | | - auto u = (i + random_double()) / (image_width-1); |
1600 | | - auto v = (j + random_double()) / (image_height-1); |
1601 | | - ray r = cam.get_ray(u, v); |
| 1606 | + auto s = (i + random_double()) / (image_width-1); |
| 1607 | + ray r = cam.get_ray(s, t); |
1602 | 1608 | pixel_color += ray_color(r, world); |
1603 | 1609 | } |
1604 | 1610 | write_color(std::cout, pixel_color, samples_per_pixel); |
|
1769 | 1775 |
|
1770 | 1776 | std::cout << "P3\n" << image_width << " " << image_height << "\n255\n"; |
1771 | 1777 |
|
1772 | | - for (int j = image_height-1; j >= 0; --j) { |
1773 | | - std::clog << "\rScanlines remaining: " << j << ' ' << std::flush; |
| 1778 | + for (int j = 0; j < image_height; ++j) { |
| 1779 | + std::clog << "\rScanlines remaining: " << (image_height - j) << ' ' << std::flush; |
| 1780 | + auto t = (j + random_double()) / (image_height-1); |
| 1781 | + |
1774 | 1782 | for (int i = 0; i < image_width; ++i) { |
1775 | 1783 | color pixel_color(0, 0, 0); |
1776 | 1784 | for (int sample = 0; sample < samples_per_pixel; ++sample) { |
1777 | | - auto u = (i + random_double()) / (image_width-1); |
1778 | | - auto v = (j + random_double()) / (image_height-1); |
1779 | | - ray r = cam.get_ray(u, v); |
| 1785 | + auto s = (i + random_double()) / (image_width-1); |
| 1786 | + ray r = cam.get_ray(s, t); |
1780 | 1787 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
1781 | 1788 | pixel_color += ray_color(r, world, max_depth); |
1782 | 1789 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
|
2367 | 2374 |
|
2368 | 2375 | // Render |
2369 | 2376 |
|
2370 | | - std::cout << "P3\n" << image_width << " " << image_height << "\n255\n"; |
2371 | | - |
2372 | | - for (int j = image_height-1; j >= 0; --j) { |
2373 | | - std::clog << "\rScanlines remaining: " << j << ' ' << std::flush; |
2374 | | - for (int i = 0; i < image_width; ++i) { |
2375 | | - color pixel_color(0, 0, 0); |
2376 | | - for (int sample = 0; sample < samples_per_pixel; ++sample) { |
2377 | | - auto u = (i + random_double()) / (image_width-1); |
2378 | | - auto v = (j + random_double()) / (image_height-1); |
2379 | | - ray r = cam.get_ray(u, v); |
2380 | | - pixel_color += ray_color(r, world, max_depth); |
2381 | | - } |
2382 | | - write_color(std::cout, pixel_color, samples_per_pixel); |
2383 | | - } |
2384 | | - } |
| 2377 | + ... |
2385 | 2378 |
|
2386 | 2379 | std::clog << "\nDone.\n"; |
2387 | 2380 | } |
|
2828 | 2821 | void render() { |
2829 | 2822 | std::cout << "P3\n" << image_width << " " << image_height << "\n255\n"; |
2830 | 2823 |
|
2831 | | - for (int j = image_height-1; j >= 0; --j) { |
2832 | | - std::clog << "\rScanlines remaining: " << j << ' ' << std::flush; |
| 2824 | + for (int j = 0; j < image_height; ++j) { |
| 2825 | + std::clog << "\rScanlines remaining: " << (image_height - j) << ' ' << std::flush; |
| 2826 | + auto t = (j + random_double()) / (image_height-1); |
| 2827 | + |
2833 | 2828 | for (int i = 0; i < image_width; ++i) { |
2834 | 2829 | color pixel_color(0,0,0); |
2835 | 2830 | for (int sample = 0; sample < samples_per_pixel; ++sample) { |
2836 | | - auto u = (i + random_double()) / (image_width-1); |
2837 | | - auto v = (j + random_double()) / (image_height-1); |
2838 | | - ray r = cam.get_ray(u, v); |
| 2831 | + auto s = (i + random_double()) / (image_width-1); |
| 2832 | + ray r = cam.get_ray(s, t); |
2839 | 2833 | pixel_color += ray_color(r, max_depth); |
2840 | 2834 | } |
2841 | 2835 | write_color(std::cout, pixel_color, samples_per_pixel); |
|
0 commit comments