|
501 | 501 | I will have the y-axis go up, and the x-axis to the right.
|
502 | 502 | In order to respect the convention of a right handed coordinate system, into the screen is the
|
503 | 503 | negative z-axis.
|
| 504 | + |
| 505 | +Now the inevitable tricky part. |
| 506 | +While our 3D space has the conventions above, this conflicts with the standard _image_ coordinates, |
| 507 | +where the Y axis is inverted. |
| 508 | +In image coordinates, Y=0 denotes the top of the image, and Y=1 denotes the bottom. |
| 509 | + |
| 510 | +To help keep things straight, we'll compute two normalized (that is, in the range [0,1]) image |
| 511 | +coordinates: $s$ (horizontal) and $t$ (vertical). |
| 512 | +$s=0$ is image left, $s=1$ is image right, $t=0$ is image top, and $t=1$ is image bottom. |
| 513 | +That means that we get our vertical axis flip at the right point by computing $t = 1 - y$, where $y$ |
| 514 | +is the vertical component of our 3D coordinate system, and $t$ is the flipped vertical component of |
| 515 | +our image coordinate system. |
| 516 | + |
504 | 517 | I will traverse the screen from the upper left hand corner, and use two offset vectors along the
|
505 | 518 | screen sides to move the ray endpoint across the screen.
|
506 | 519 | Note that I do not make the ray direction a unit length vector because I think not doing that makes
|
|
509 | 522 | ![Figure [cam-geom]: Camera geometry](../images/fig-1.03-cam-geom.jpg)
|
510 | 523 |
|
511 | 524 | <div class='together'>
|
512 |
| -Below in code, the ray `r` goes to approximately the pixel centers (I won’t worry about exactness |
513 |
| -for now because we’ll add antialiasing later): |
| 525 | +Below in code, the ray `r` goes to the current image pixel: |
514 | 526 |
|
515 | 527 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
516 | 528 | #include "color.h"
|
|
525 | 537 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
|
526 | 538 | color ray_color(const ray& r) {
|
527 | 539 | vec3 unit_direction = unit_vector(r.direction());
|
528 |
| - auto t = 0.5*(unit_direction.y() + 1.0); |
529 |
| - return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0); |
| 540 | + auto a = 0.5*(unit_direction.y() + 1.0); |
| 541 | + return (1.0-a)*color(1.0, 1.0, 1.0) + a*color(0.5, 0.7, 1.0); |
530 | 542 | }
|
531 | 543 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
532 | 544 |
|
|
580 | 592 | Because we're looking at the $y$ height after normalizing the vector, you'll notice a horizontal
|
581 | 593 | gradient to the color in addition to the vertical gradient.
|
582 | 594 |
|
583 |
| -I then did a standard graphics trick of scaling that to $0.0 ≤ t ≤ 1.0$. |
584 |
| -When $t = 1.0$ I want blue. |
585 |
| -When $t = 0.0$ I want white. |
| 595 | +I then did a standard graphics trick of scaling that to $0.0 ≤ a ≤ 1.0$. |
| 596 | +When $a = 1.0$, I want blue. |
| 597 | +When $a = 0.0$, I want white. |
586 | 598 | In between, I want a blend.
|
587 |
| -This forms a “linear blend”, or “linear interpolation”: commonly referred to as a _lerp_, between |
588 |
| -two things. |
| 599 | +This forms a “linear blend”, or “linear interpolation”. |
| 600 | +This is commonly referred to as a _lerp_ between two values. |
589 | 601 | A lerp is always of the form
|
590 | 602 |
|
591 |
| - $$ \text{blendedValue} = (1-t)\cdot\text{startValue} + t\cdot\text{endValue}, $$ |
| 603 | + $$ \text{blendedValue} = (1-a)\cdot\text{startValue} + a\cdot\text{endValue}, $$ |
592 | 604 |
|
593 |
| -with $t$ going from zero to one. |
| 605 | +with $a$ going from zero to one. |
594 | 606 | In our case this produces:
|
595 | 607 |
|
596 | 608 | ![Image 2: A blue-to-white gradient depending on ray Y coordinate
|
|
697 | 709 | return color(1, 0, 0);
|
698 | 710 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
699 | 711 | vec3 unit_direction = unit_vector(r.direction());
|
700 |
| - auto t = 0.5*(unit_direction.y() + 1.0); |
701 |
| - return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0); |
| 712 | + auto a = 0.5*(unit_direction.y() + 1.0); |
| 713 | + return (1.0-a)*color(1.0, 1.0, 1.0) + a*color(0.5, 0.7, 1.0); |
702 | 714 | }
|
703 | 715 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
704 | 716 | [Listing [main-red-sphere]: <kbd>[main.cc]</kbd> Rendering a red sphere]
|
|
772 | 784 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
773 | 785 | vec3 unit_direction = unit_vector(r.direction());
|
774 | 786 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
|
775 |
| - t = 0.5*(unit_direction.y() + 1.0); |
| 787 | + a = 0.5*(unit_direction.y() + 1.0); |
776 | 788 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
777 |
| - return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0); |
| 789 | + return (1.0-a)*color(1.0, 1.0, 1.0) + a*color(0.5, 0.7, 1.0); |
778 | 790 | }
|
779 | 791 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
780 | 792 | [Listing [render-surface-normal]: <kbd>[main.cc]</kbd> Rendering surface normals on a sphere]
|
|
1230 | 1242 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
1231 | 1243 | vec3 unit_direction = unit_vector(r.direction());
|
1232 | 1244 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
|
1233 |
| - auto t = 0.5*(unit_direction.y() + 1.0); |
| 1245 | + auto a = 0.5*(unit_direction.y() + 1.0); |
1234 | 1246 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
1235 |
| - return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0); |
| 1247 | + return (1.0-a)*color(1.0, 1.0, 1.0) + a*color(0.5, 0.7, 1.0); |
1236 | 1248 | }
|
1237 | 1249 |
|
1238 | 1250 | int main() {
|
|
1562 | 1574 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1563 | 1575 | [Listing [write-color-clamped]: <kbd>[color.h]</kbd> The multi-sample write_color() function]
|
1564 | 1576 |
|
1565 |
| -<div class='together'> |
1566 |
| -Main is also changed: |
| 1577 | +Main is also changed. |
| 1578 | +Note that in the image scanning loops, we take the opportunity to hoist the computation of the image |
| 1579 | +$t$ coordinate out of the inner loop, since it is the same value for the entire scanline. |
1567 | 1580 |
|
1568 | 1581 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
1569 | 1582 | #include "rtweekend.h"
|
|
1630 | 1643 | }
|
1631 | 1644 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1632 | 1645 | [Listing [main-multi-sample]: <kbd>[main.cc]</kbd> Rendering with multi-sampled pixels]
|
1633 |
| -</div> |
1634 | 1646 |
|
1635 | 1647 | Zooming into the image that is produced, we can see the difference in edge pixels.
|
1636 | 1648 |
|
|
1730 | 1742 | }
|
1731 | 1743 |
|
1732 | 1744 | vec3 unit_direction = unit_vector(r.direction());
|
1733 |
| - auto t = 0.5*(unit_direction.y() + 1.0); |
1734 |
| - return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0); |
| 1745 | + auto a = 0.5*(unit_direction.y() + 1.0); |
| 1746 | + return (1.0-a)*color(1.0, 1.0, 1.0) + a*color(0.5, 0.7, 1.0); |
1735 | 1747 | }
|
1736 | 1748 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1737 | 1749 | [Listing [ray-color-random-unit]: <kbd>[main.cc]</kbd> ray_color() using a random ray direction]
|
|
1766 | 1778 | }
|
1767 | 1779 |
|
1768 | 1780 | vec3 unit_direction = unit_vector(r.direction());
|
1769 |
| - auto t = 0.5*(unit_direction.y() + 1.0); |
1770 |
| - return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0); |
| 1781 | + auto a = 0.5*(unit_direction.y() + 1.0); |
| 1782 | + return (1.0-a)*color(1.0, 1.0, 1.0) + a*color(0.5, 0.7, 1.0); |
1771 | 1783 | }
|
1772 | 1784 |
|
1773 | 1785 | ...
|
|
1891 | 1903 | }
|
1892 | 1904 |
|
1893 | 1905 | vec3 unit_direction = unit_vector(r.direction());
|
1894 |
| - auto t = 0.5*(unit_direction.y() + 1.0); |
1895 |
| - return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0); |
| 1906 | + auto a = 0.5*(unit_direction.y() + 1.0); |
| 1907 | + return (1.0-a)*color(1.0, 1.0, 1.0) + a*color(0.5, 0.7, 1.0); |
1896 | 1908 | }
|
1897 | 1909 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1898 | 1910 | [Listing [reflect-tolerance]: <kbd>[main.cc]</kbd>
|
|
1953 | 1965 | }
|
1954 | 1966 |
|
1955 | 1967 | vec3 unit_direction = unit_vector(r.direction());
|
1956 |
| - auto t = 0.5*(unit_direction.y() + 1.0); |
1957 |
| - return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0); |
| 1968 | + auto a = 0.5*(unit_direction.y() + 1.0); |
| 1969 | + return (1.0-a)*color(1.0, 1.0, 1.0) + a*color(0.5, 0.7, 1.0); |
1958 | 1970 | }
|
1959 | 1971 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1960 | 1972 | [Listing [ray-color-unit-sphere]: <kbd>[main.cc]</kbd> ray_color() with replacement diffuse]
|
|
2035 | 2047 | }
|
2036 | 2048 |
|
2037 | 2049 | vec3 unit_direction = unit_vector(r.direction());
|
2038 |
| - auto t = 0.5*(unit_direction.y() + 1.0); |
2039 |
| - return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0); |
| 2050 | + auto a = 0.5*(unit_direction.y() + 1.0); |
| 2051 | + return (1.0-a)*color(1.0, 1.0, 1.0) + a*color(0.5, 0.7, 1.0); |
2040 | 2052 | }
|
2041 | 2053 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
2042 | 2054 | [Listing [ray-color-hemisphere]: <kbd>[main.cc]</kbd> ray_color() with hemispherical scattering]
|
|
2327 | 2339 | }
|
2328 | 2340 |
|
2329 | 2341 | vec3 unit_direction = unit_vector(r.direction());
|
2330 |
| - auto t = 0.5*(unit_direction.y() + 1.0); |
2331 |
| - return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0); |
| 2342 | + auto a = 0.5*(unit_direction.y() + 1.0); |
| 2343 | + return (1.0-a)*color(1.0, 1.0, 1.0) + a*color(0.5, 0.7, 1.0); |
2332 | 2344 | }
|
2333 | 2345 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
2334 | 2346 | [Listing [ray-color-scatter]: <kbd>[main.cc]</kbd> Ray color with scattered reflectance]
|
|
2879 | 2891 | }
|
2880 | 2892 |
|
2881 | 2893 | vec3 unit_direction = unit_vector(r.direction());
|
2882 |
| - auto t = 0.5*(unit_direction.y() + 1.0); |
2883 |
| - return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0); |
| 2894 | + auto a = 0.5*(unit_direction.y() + 1.0); |
| 2895 | + return (1.0-a)*color(1.0, 1.0, 1.0) + a*color(0.5, 0.7, 1.0); |
2884 | 2896 | }
|
2885 | 2897 | };
|
2886 | 2898 |
|
|
0 commit comments