|
292 | 292 |
|
293 | 293 | #endif
|
294 | 294 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
295 |
| - [Listing [vec3-class]: <kbd>[vec3.h]</kbd> `vec3` class] |
| 295 | + [Listing [vec3-class]: <kbd>[vec3.h]</kbd> vec3 class] |
296 | 296 | </div>
|
297 | 297 |
|
298 | 298 | We use `double` here, but some ray tracers use `float`. Either one is fine -- follow your own
|
|
350 | 350 | return v / v.length();
|
351 | 351 | }
|
352 | 352 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
353 |
| - [Listing [vec3-utility]: <kbd>[vec3.h]</kbd> `vec3` utility functions] |
| 353 | + [Listing [vec3-utility]: <kbd>[vec3.h]</kbd> vec3 utility functions] |
354 | 354 |
|
355 | 355 | <div class='together'>
|
356 | 356 | Now we can change our main to use this:
|
|
391 | 391 | --------------
|
392 | 392 | <div class='together'>
|
393 | 393 | The one thing that all ray tracers have is a ray class, and a computation of what color is seen
|
394 |
| -along a ray. Let’s think of a ray as a function: |
395 |
| - |
396 |
| - $$ \mathbf{p}(t) = \mathbf{a} + t \vec{\mathbf{b}} $$ |
397 |
| - |
398 |
| -Where $\mathbf{p}$ is a 3D position along a line in 3D, $\mathbf{a}$ is the ray origin, and |
| 394 | +along a ray. Let’s think of a ray as a function $\mathbf{p}(t) = \mathbf{a} + t \vec{\mathbf{b}}$. |
| 395 | +Here $\mathbf{p}$ is a 3D position along a line in 3D. $\mathbf{a}$ is the ray origin and |
399 | 396 | $\vec{\mathbf{b}}$ is the ray direction. The ray parameter $t$ is a real number (`double` in the
|
400 |
| -code). Plug in a different $t$ and $\mathbf{p}(t)$ moves the point along the ray. Add in negative |
401 |
| -$t$ and you can go anywhere on the 3D line. For positive $t$, you get only the parts in front of |
402 |
| -$\mathbf{a}$, and this is what is often called a half-line or ray. This is where the _ray_ in |
| 397 | +code). Plug in a different $t$ and $p(t)$ moves the point along the ray. Add in negative $t$ and you |
| 398 | +can go anywhere on the 3D line. For positive $t$, you get only the parts in front of $\mathbf{a}$, |
| 399 | +and this is what is often called a half-line or ray. This is where the _ray_ in |
403 | 400 | _ray tracing_ comes from.
|
404 | 401 |
|
405 | 402 | ![Figure [lerp]: Linear interpolation](../images/fig.lerp.jpg)
|
406 | 403 |
|
407 | 404 | </div>
|
408 | 405 |
|
409 | 406 | <div class='together'>
|
410 |
| -The function $\mathbf{p}(t)$ in more verbose code form I call `ray::at(t)`: |
| 407 | +The function $p(t)$ in more verbose code form I call `ray::at(t)`: |
411 | 408 |
|
412 | 409 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
413 | 410 | #ifndef RAY_H
|
|
436 | 433 |
|
437 | 434 | #endif
|
438 | 435 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
439 |
| - [Listing [ray-initial]: <kbd>[ray.h]</kbd> The `ray` class] |
| 436 | + [Listing [ray-initial]: <kbd>[ray.h]</kbd> The ray class] |
440 | 437 | </div>
|
441 | 438 |
|
442 | 439 |
|
|
569 | 566 |
|
570 | 567 | <div class='together'>
|
571 | 568 | We can read this as “any point $\mathbf{p}$ that satisfies this equation is on the sphere”. We want
|
572 |
| -to know if our ray $\mathbf{p}(t) = \mathbf{a} + t\vec{\mathbf{b}}$ ever hits the sphere anywhere. |
573 |
| -If it does hit the sphere, there is some $t$ for which $\mathbf{p}(t)$ satisfies the sphere |
574 |
| -equation. So we are looking for any $t$ where this is true: |
| 569 | +to know if our ray $p(t) = \mathbf{a} + t\vec{\mathbf{b}}$ ever hits the sphere anywhere. If it does |
| 570 | +hit the sphere, there is some $t$ for which $p(t)$ satisfies the sphere equation. So we are looking |
| 571 | +for any $t$ where this is true: |
575 | 572 |
|
576 |
| - $$ (\mathbf{p}(t) - \mathbf{c})\cdot(\mathbf{p}(t) - \mathbf{c}) = R^2 $$ |
| 573 | + $$ (p(t) - \mathbf{c})\cdot(p(t) - \mathbf{c}) = R^2 $$ |
577 | 574 |
|
578 | 575 | or expanding the full form of the ray $p(t)$:
|
579 | 576 |
|
|
810 | 807 |
|
811 | 808 | #endif
|
812 | 809 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
813 |
| - [Listing [hittable-initial]: <kbd>[hittable.h]</kbd> The `hittable` class] |
| 810 | + [Listing [hittable-initial]: <kbd>[hittable.h]</kbd> The hittable class] |
814 | 811 | </div>
|
815 | 812 |
|
816 | 813 | <div class='together'>
|
|
865 | 862 |
|
866 | 863 | #endif
|
867 | 864 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
868 |
| - [Listing [sphere-initial]: <kbd>[sphere.h]</kbd> The `sphere` class] |
| 865 | + [Listing [sphere-initial]: <kbd>[sphere.h]</kbd> The sphere class] |
869 | 866 |
|
870 | 867 | </div>
|
871 | 868 |
|
|
963 | 960 |
|
964 | 961 | #endif
|
965 | 962 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
966 |
| - [Listing [hittable-time-side]: <kbd>[hittable.h]</kbd> The `hittable` class with time and side] |
| 963 | + [Listing [hittable-time-side]: <kbd>[hittable.h]</kbd> The hittable class with time and side] |
967 | 964 |
|
968 | 965 | <div class='together'>
|
969 | 966 | And then we add the surface side determination to the class:
|
|
1002 | 999 | return false;
|
1003 | 1000 | }
|
1004 | 1001 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1005 |
| - [Listing [sphere-final]: <kbd>[sphere.h]</kbd> The `sphere` class with normal determination] |
| 1002 | + [Listing [sphere-final]: <kbd>[sphere.h]</kbd> The sphere class with normal determination] |
1006 | 1003 |
|
1007 | 1004 | </div>
|
1008 | 1005 |
|
|
1057 | 1054 |
|
1058 | 1055 | #endif
|
1059 | 1056 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1060 |
| - [Listing [hittable-list-initial]: <kbd>[hittable_list.h]</kbd> The `hittable_list` class] |
| 1057 | + [Listing [hittable-list-initial]: <kbd>[hittable_list.h]</kbd> The hittable_list class] |
1061 | 1058 | </div>
|
1062 | 1059 |
|
1063 | 1060 |
|
|
1092 | 1089 | auto vec3_ptr = make_shared<vec3>(1.414214, 2.718281, 1.618034);
|
1093 | 1090 | auto sphere_ptr = make_shared<sphere>(point3(0,0,0), 1.0);
|
1094 | 1091 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1095 |
| - [Listing [shared-ptr-auto]: An example allocation using `shared_ptr` with `auto` type] |
| 1092 | + [Listing [shared-ptr-auto]: An example allocation using shared_ptr with auto type] |
1096 | 1093 |
|
1097 | 1094 | </div>
|
1098 | 1095 |
|
|
1159 | 1156 |
|
1160 | 1157 | #endif
|
1161 | 1158 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1162 |
| - [Listing [rtweekend-initial]: <kbd>[rtweekend.h]</kbd> The `rtweekend.h` common header] |
| 1159 | + [Listing [rtweekend-initial]: <kbd>[rtweekend.h]</kbd> The rtweekend.h common header] |
1163 | 1160 | </div>
|
1164 | 1161 |
|
1165 | 1162 | <div class='together'>
|
|
1226 | 1223 | std::cerr << "\nDone.\n";
|
1227 | 1224 | }
|
1228 | 1225 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1229 |
| - [Listing [main-with-rtweekend-h]: <kbd>[main.cc]</kbd> The new main with `hittables`] |
| 1226 | + [Listing [main-with-rtweekend-h]: <kbd>[main.cc]</kbd> The new main with hittables] |
1230 | 1227 | </div>
|
1231 | 1228 |
|
1232 | 1229 | <div class='together'>
|
|
1279 | 1276 | return min + (max-min)*random_double();
|
1280 | 1277 | }
|
1281 | 1278 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1282 |
| - [Listing [random-double]: <kbd>[rtweekend.h]</kbd> `random_double()` functions] |
| 1279 | + [Listing [random-double]: <kbd>[rtweekend.h]</kbd> random_double() functions] |
1283 | 1280 | </div>
|
1284 | 1281 |
|
1285 | 1282 | <div class='together'>
|
|
1299 | 1296 | return rand_generator();
|
1300 | 1297 | }
|
1301 | 1298 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1302 |
| - [Listing [random-double-alt]: <kbd>[rtweekend.h]</kbd> `random_double()`, alternate implemenation] |
| 1299 | + [Listing [random-double-alt]: <kbd>[rtweekend.h]</kbd> random_double(), alternate implemenation] |
1303 | 1300 | </div>
|
1304 | 1301 |
|
1305 | 1302 |
|
|
1344 | 1341 | };
|
1345 | 1342 | #endif
|
1346 | 1343 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1347 |
| - [Listing [camera-initial]: <kbd>[camera.h]</kbd> The `camera` class] |
| 1344 | + [Listing [camera-initial]: <kbd>[camera.h]</kbd> The camera class] |
1348 | 1345 | </div>
|
1349 | 1346 |
|
1350 | 1347 | To handle the multi-sampled color computation, we update the `vec3::write_color()` function. Rather
|
|
1360 | 1357 | return x;
|
1361 | 1358 | }
|
1362 | 1359 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1363 |
| - [Listing [clamp]: <kbd>[rtweekend.h]</kbd> The `clamp()` utility function] |
| 1360 | + [Listing [clamp]: <kbd>[rtweekend.h]</kbd> The clamp() utility function] |
1364 | 1361 |
|
1365 | 1362 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
1366 | 1363 | void write_color(std::ostream &out, int samples_per_pixel) {
|
|
1376 | 1373 | << static_cast<int>(256 * clamp(b, 0.0, 0.999)) << '\n';
|
1377 | 1374 | }
|
1378 | 1375 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1379 |
| - [Listing [write-color-clamped]: <kbd>[vec3.h]</kbd> The `write_color()` function] |
| 1376 | + [Listing [write-color-clamped]: <kbd>[vec3.h]</kbd> The write_color() function] |
1380 | 1377 |
|
1381 | 1378 | <div class='together'>
|
1382 | 1379 | Main is also changed:
|
|
1496 | 1493 | return vec3(random_double(min,max), random_double(min,max), random_double(min,max));
|
1497 | 1494 | }
|
1498 | 1495 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1499 |
| - [Listing [vec-rand-util]: <kbd>[vec3.h]</kbd> `vec3` random utility functions] |
| 1496 | + [Listing [vec-rand-util]: <kbd>[vec3.h]</kbd> vec3 random utility functions] |
1500 | 1497 |
|
1501 | 1498 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
1502 | 1499 | vec3 random_in_unit_sphere() {
|
|
1507 | 1504 | }
|
1508 | 1505 | }
|
1509 | 1506 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1510 |
| - [Listing [random-in-unit-sphere]: <kbd>[vec3.h]</kbd> The `random_in_unit_sphere()` function] |
| 1507 | + [Listing [random-in-unit-sphere]: <kbd>[vec3.h]</kbd> The random_in_unit_sphere() function] |
1511 | 1508 | </div>
|
1512 | 1509 |
|
1513 | 1510 | <div class='together'>
|
|
1529 | 1526 | return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0);
|
1530 | 1527 | }
|
1531 | 1528 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1532 |
| - [Listing [ray-color-random-unit]: <kbd>[main.cc]</kbd> `ray_color()` using a random ray direction] |
| 1529 | + [Listing [ray-color-random-unit]: <kbd>[main.cc]</kbd> ray_color() using a random ray direction] |
1533 | 1530 | </div>
|
1534 | 1531 |
|
1535 | 1532 |
|
|
1595 | 1592 | std::cerr << "\nDone.\n";
|
1596 | 1593 | }
|
1597 | 1594 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1598 |
| - [Listing [ray-color-depth]: <kbd>[main.cc]</kbd> `ray_color()` with depth limiting] |
| 1595 | + [Listing [ray-color-depth]: <kbd>[main.cc]</kbd> ray_color() with depth limiting] |
1599 | 1596 | </div>
|
1600 | 1597 |
|
1601 | 1598 | <div class='together'>
|
|
1639 | 1636 | << static_cast<int>(256 * clamp(b, 0.0, 0.999)) << '\n';
|
1640 | 1637 | }
|
1641 | 1638 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1642 |
| - [Listing [write-color-gamma]: <kbd>[vec3.h]</kbd> `write_color()`, with gamma correction] |
| 1639 | + [Listing [write-color-gamma]: <kbd>[vec3.h]</kbd> write_color(), with gamma correction] |
1643 | 1640 |
|
1644 | 1641 | </div>
|
1645 | 1642 |
|
|
1694 | 1691 | return vec3(r*cos(a), r*sin(a), z);
|
1695 | 1692 | }
|
1696 | 1693 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1697 |
| - [Listing [random-unit-vector]: <kbd>[vec3.h]</kbd> The `random_unit_vector()` function] |
| 1694 | + [Listing [random-unit-vector]: <kbd>[vec3.h]</kbd> The random_unit_vector() function] |
1698 | 1695 |
|
1699 | 1696 | ![Figure [rand-unit-vector]: Generating a random unit vector](../images/fig.rand-unitvector.png)
|
1700 | 1697 |
|
|
1724 | 1721 | return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0);
|
1725 | 1722 | }
|
1726 | 1723 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1727 |
| - [Listing [ray-color-unit-sphere]: <kbd>[main.cc]</kbd> `ray_color()` with replacement diffuse] |
| 1724 | + [Listing [ray-color-unit-sphere]: <kbd>[main.cc]</kbd> ray_color() with replacement diffuse] |
1728 | 1725 | </div>
|
1729 | 1726 |
|
1730 | 1727 | <div class='together'>
|
|
1782 | 1779 | return -in_unit_sphere;
|
1783 | 1780 | }
|
1784 | 1781 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1785 |
| - [Listing [random-in-hemisphere]: <kbd>[vec3.h]</kbd> The `random_in_hemisphere(normal)` function] |
| 1782 | + [Listing [random-in-hemisphere]: <kbd>[vec3.h]</kbd> The random_in_hemisphere(normal) function] |
1786 | 1783 |
|
1787 | 1784 | </div>
|
1788 | 1785 |
|
|
1809 | 1806 | return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0);
|
1810 | 1807 | }
|
1811 | 1808 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1812 |
| - [Listing [ray-color-hemisphere]: <kbd>[main.cc]</kbd> `ray_color()` with hemispherical scattering] |
| 1809 | + [Listing [ray-color-hemisphere]: <kbd>[main.cc]</kbd> ray_color() with hemispherical scattering] |
1813 | 1810 |
|
1814 | 1811 | Gives us the following image:
|
1815 | 1812 |
|
|
1860 | 1857 |
|
1861 | 1858 | #endif
|
1862 | 1859 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1863 |
| - [Listing [material-initial]: <kbd>[material.h]</kbd> The `material` class] |
| 1860 | + [Listing [material-initial]: <kbd>[material.h]</kbd> The material class] |
1864 | 1861 | </div>
|
1865 | 1862 |
|
1866 | 1863 |
|
|
2003 | 2000 | color albedo;
|
2004 | 2001 | };
|
2005 | 2002 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
2006 |
| - [Listing [lambertian-initial]: <kbd>[material.h]</kbd> The `lambertian` material class] |
| 2003 | + [Listing [lambertian-initial]: <kbd>[material.h]</kbd> The lambertian material class] |
2007 | 2004 | </div>
|
2008 | 2005 |
|
2009 | 2006 | Note we could just as well only scatter with some probability $p$ and have attenuation be
|
|
2031 | 2028 | return v - 2*dot(v,n)*n;
|
2032 | 2029 | }
|
2033 | 2030 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
2034 |
| - [Listing [vec3-reflect]: <kbd>[vec3.h]</kbd> `vec3` reflection function] |
| 2031 | + [Listing [vec3-reflect]: <kbd>[vec3.h]</kbd> vec3 reflection function] |
2035 | 2032 | </div>
|
2036 | 2033 |
|
2037 | 2034 | <div class='together'>
|
|
2351 | 2348 |
|
2352 | 2349 | The value of $\sin\theta'$ cannot be greater than 1. So, if,
|
2353 | 2350 |
|
2354 |
| - $$ \frac{1.5}{1.0} \cdot \sin\theta > 1.0 $$ |
| 2351 | + $$ \frac{1.5}{1.0} \cdot \sin\theta > 1.0 $$, |
2355 | 2352 |
|
2356 | 2353 | <div class="together">
|
2357 | 2354 | the equality between the two sides of the equation is broken and a solution cannot exist. If a
|
|
2655 | 2652 | ![Figure [cam-up]: Camera view up direction](../images/fig.cam-up.jpg)
|
2656 | 2653 |
|
2657 | 2654 | Remember that `vup`, `v`, and `w` are all in the same plane. Note that, like before when our fixed
|
2658 |
| -camera faced `-Z`, our arbitrary view camera faces `-w`. And keep in mind that we can -- but we |
2659 |
| -don’t have to -- use world up `(0,1,0)` to specify vup. This is convenient and will naturally keep |
2660 |
| -your camera horizontally level until you decide to experiment with crazy camera angles. |
| 2655 | +camera faced -Z, our arbitrary view camera faces -w. And keep in mind that we can -- but we don’t |
| 2656 | +have to -- use world up $(0,1,0)$ to specify vup. This is convenient and will naturally keep your |
| 2657 | +camera horizontally level until you decide to experiment with crazy camera angles. |
2661 | 2658 |
|
2662 | 2659 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
2663 | 2660 | class camera {
|
|
0 commit comments