|
2065 | 2065 | virtual bool scatter(
|
2066 | 2066 | const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered
|
2067 | 2067 | ) const override {
|
2068 |
| - vec3 scatter_direction = rec.normal + random_unit_vector(); |
| 2068 | + auto scatter_direction = rec.normal + random_unit_vector(); |
2069 | 2069 | scattered = ray(rec.p, scatter_direction);
|
2070 | 2070 | attenuation = albedo;
|
2071 | 2071 | return true;
|
|
2081 | 2081 | Note we could just as well only scatter with some probability $p$ and have attenuation be
|
2082 | 2082 | $albedo/p$. Your choice.
|
2083 | 2083 |
|
| 2084 | +If you read the code above carefully, you'll notice a small chance of mischief. If the random unit |
| 2085 | +vector we generate is exactly opposite the normal vector, the two will sum to zero, which will |
| 2086 | +result in a zero scatter direction vector. This leads to bad scenarios later on (infinities and |
| 2087 | +NaNs), so we need to intercept the condition before we pass it on. |
| 2088 | + |
| 2089 | +<div class='together'> |
| 2090 | +In service of this, we'll create a new vector method -- `vec3::near_zero()` -- that returns true if |
| 2091 | +the vector is very close to zero in all dimensions. |
| 2092 | + |
| 2093 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
| 2094 | + class vec3 { |
| 2095 | + ... |
| 2096 | + bool near_zero() const { |
| 2097 | + // Return true if the vector is close to zero in all dimensions. |
| 2098 | + const auto s = 1e-8; |
| 2099 | + return (fabs(e[0]) < s) && (fabs(e[1]) < s) && (fabs(e[2]) < s); |
| 2100 | + } |
| 2101 | + ... |
| 2102 | + }; |
| 2103 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 2104 | + [Listing [vec3-near-zero]: <kbd>[vec3.h]</kbd> The vec3::near_zero() method] |
| 2105 | + |
| 2106 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
| 2107 | + class lambertian : public material { |
| 2108 | + public: |
| 2109 | + lambertian(const color& a) : albedo(a) {} |
| 2110 | + |
| 2111 | + virtual bool scatter( |
| 2112 | + const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered |
| 2113 | + ) const override { |
| 2114 | + auto scatter_direction = rec.normal + random_unit_vector(); |
| 2115 | + |
| 2116 | + |
| 2117 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
| 2118 | + // Catch degenerate scatter direction |
| 2119 | + if (scatter_direction.near_zero()) |
| 2120 | + scatter_direction = rec.normal; |
| 2121 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
| 2122 | + |
| 2123 | + scattered = ray(rec.p, scatter_direction); |
| 2124 | + attenuation = albedo; |
| 2125 | + return true; |
| 2126 | + } |
| 2127 | + |
| 2128 | + public: |
| 2129 | + color albedo; |
| 2130 | + }; |
| 2131 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 2132 | + [Listing [lambertian-catch-zero]: <kbd>[material.h]</kbd> Lambertian scatter, bullet-proof] |
| 2133 | +</div> |
| 2134 | + |
2084 | 2135 |
|
2085 | 2136 | Mirrored Light Reflection
|
2086 | 2137 | --------------------------
|
|
0 commit comments