Skip to content

Commit 96c28a3

Browse files
authored
Merge pull request #885 from RayTracing/tdb/isotropic
Added isotropic changes for book 3. Made some changes to prior books.
2 parents fa37d12 + 4854d72 commit 96c28a3

File tree

8 files changed

+253
-14
lines changed

8 files changed

+253
-14
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Change Log -- Ray Tracing in One Weekend
2222
- Change: general rename of `mat_ptr` to `mat` (material)
2323
- Change: hittable::bounding_box() signature has changed to always return a value (#859)
2424
- Fix: Enabled compiler warnings for MSVC, Clang, GNU. Cleaned up warnings as fit (#865)
25+
- Change: replaced random vector in `isotropic` with `random_unit_vector`
2526

2627
### In One Weekend
2728
- Added: More commentary about the choice between `double` and `float` (#752)
@@ -35,7 +36,9 @@ Change Log -- Ray Tracing in One Weekend
3536
- Fix: Fixed `bvh_node` constructor definition signature (#872)
3637

3738
### The Rest of Your Life
39+
- Fix: Added missing functionality for `isotropic` (#664)
3840
- Fix: Variable `direction` was used without being defined in listing 11 (#831)
41+
- Fix: Added missing functionality for `isotropic` (#664)
3942

4043

4144
----------------------------------------------------------------------------------------------------

books/RayTracingTheNextWeek.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3145,7 +3145,7 @@
31453145

31463146
bool scatter(const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered)
31473147
const override {
3148-
scattered = ray(rec.p, random_in_unit_sphere(), r_in.time());
3148+
scattered = ray(rec.p, random_unit_vector(), r_in.time());
31493149
attenuation = albedo->value(rec.u, rec.v, rec.p);
31503150
return true;
31513151
}

books/RayTracingTheRestOfYourLife.html

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2143,6 +2143,7 @@
21432143
class lambertian : public material {
21442144
public:
21452145
...
2146+
21462147
bool scatter(
21472148
const ray& r_in, const hit_record& rec, color& alb, ray& scattered, double& pdf
21482149
) const override {
@@ -2158,6 +2159,9 @@
21582159
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
21592160
return true;
21602161
}
2162+
2163+
...
2164+
}
21612165
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21622166
[Listing [scatter-onb]: <kbd>[material.h]</kbd> Scatter function, with orthonormal basis]
21632167
</div>
@@ -2171,6 +2175,44 @@
21712175
Let’s get rid of some of that noise.
21722176
</div>
21732177

2178+
<div class='together'>
2179+
But first, let's quickly update the `isotropic` material:
2180+
2181+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
2182+
class isotropic : public material {
2183+
public:
2184+
isotropic(color c) : albedo(make_shared<solid_color>(c)) {}
2185+
isotropic(shared_ptr<texture> a) : albedo(a) {}
2186+
2187+
2188+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
2189+
bool scatter(
2190+
const ray& r_in, const hit_record& rec, color& alb, ray& scattered, double& pdf
2191+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
2192+
) const override {
2193+
scattered = ray(rec.p, random_unit_vector(), r_in.time());
2194+
attenuation = albedo->value(rec.u, rec.v, rec.p);
2195+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
2196+
pdf = 1 / (4 * pi);
2197+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
2198+
return true;
2199+
}
2200+
2201+
2202+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
2203+
double scattering_pdf(const ray& r_in, const hit_record& rec, const ray& scattered)
2204+
const override {
2205+
return 1 / (4 * pi);
2206+
}
2207+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
2208+
2209+
public:
2210+
shared_ptr<texture> albedo;
2211+
};
2212+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2213+
[Listing [class-isotropic-impsample]: <kbd>[material.h]</kbd>
2214+
Isotropic material, modified for importance sampling]
2215+
</div>
21742216

21752217

21762218
Sampling Lights Directly
@@ -2438,8 +2480,26 @@
24382480
</div>
24392481

24402482
<div class='together'>
2441-
We’ll see if we need to add anything else to `pdf` by fleshing out the subclasses. First, let’s try
2442-
a cosine density:
2483+
We’ll see if we need to add anything else to `pdf` by fleshing out the subclasses. First, we'll
2484+
create a uniform density over the unit sphere:
2485+
2486+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
2487+
class sphere_pdf : public pdf {
2488+
public:
2489+
sphere_pdf() { }
2490+
2491+
double value(const vec3& direction) const override {
2492+
return 1/ (4 * pi);
2493+
}
2494+
2495+
vec3 generate() const override {
2496+
return random_unit_vector();
2497+
}
2498+
};
2499+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2500+
[Listing [class-uni-pdf]: <kbd>[pdf.h]</kbd> The uniform_pdf class]
2501+
2502+
Next, let’s try a cosine density:
24432503

24442504
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
24452505
class cosine_pdf : public pdf {
@@ -2903,14 +2963,15 @@
29032963
</div>
29042964

29052965
<div class='together'>
2906-
The Lambertian material becomes simpler:
2966+
The `lambertian` material becomes simpler:
29072967

29082968
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
29092969
class lambertian : public material {
29102970
public:
29112971
lambertian(const color& a) : albedo(make_shared<solid_color>(a)) {}
29122972
lambertian(shared_ptr<texture> a) : albedo(a) {}
29132973

2974+
29142975
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
29152976
bool scatter(const ray& r_in, const hit_record& rec, scatter_record& srec) const override {
29162977
srec.attenuation = albedo->value(rec.u, rec.v, rec.p);
@@ -2932,6 +2993,38 @@
29322993
[Listing [lambertian-scatter]: <kbd>[material.h]</kbd> New lambertian scatter() method]
29332994
</div>
29342995

2996+
<div class='together'>
2997+
As does the `isotropic` material:
2998+
2999+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
3000+
class isotropic : public material {
3001+
public:
3002+
isotropic(color c) : albedo(make_shared<solid_color>(c)) {}
3003+
isotropic(shared_ptr<texture> a) : albedo(a) {}
3004+
3005+
3006+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
3007+
bool scatter(const ray& r_in, const hit_record& rec, scatter_record& srec) const override {
3008+
srec.attenuation = albedo->value(rec.u, rec.v, rec.p);
3009+
srec.pdf_ptr = make_shared<sphere_pdf>();
3010+
srec.skip_pdf = false;
3011+
return true;
3012+
}
3013+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
3014+
3015+
3016+
double scattering_pdf(const ray& r_in, const hit_record& rec, const ray& scattered)
3017+
const override {
3018+
return 1 / (4 * pi);
3019+
}
3020+
3021+
public:
3022+
shared_ptr<texture> albedo;
3023+
};
3024+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3025+
[Listing [isotropic-scatter]: <kbd>[material.h]</kbd> New isotropic scatter() method]
3026+
</div>
3027+
29353028
<div class='together'>
29363029
And `ray_color()` changes are small:
29373030

src/TheNextWeek/material.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ class isotropic : public material {
136136

137137
bool scatter(const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered)
138138
const override {
139-
scattered = ray(rec.p, random_in_unit_sphere(), r_in.time());
139+
scattered = ray(rec.p, random_unit_vector(), r_in.time());
140140
attenuation = albedo->value(rec.u, rec.v, rec.p);
141141
return true;
142142
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#ifndef CONSTANT_MEDIUM_H
2+
#define CONSTANT_MEDIUM_H
3+
//==============================================================================================
4+
// Originally written in 2016 by Peter Shirley <[email protected]>
5+
//
6+
// To the extent possible under law, the author(s) have dedicated all copyright and related and
7+
// neighboring rights to this software to the public domain worldwide. This software is
8+
// distributed without any warranty.
9+
//
10+
// You should have received a copy (see file COPYING.txt) of the CC0 Public Domain Dedication
11+
// along with this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
12+
//==============================================================================================
13+
14+
#include "rtweekend.h"
15+
16+
#include "hittable.h"
17+
#include "material.h"
18+
#include "texture.h"
19+
20+
21+
class constant_medium : public hittable {
22+
public:
23+
constant_medium(shared_ptr<hittable> b, double d, shared_ptr<texture> a)
24+
: boundary(b), neg_inv_density(-1/d), phase_function(make_shared<isotropic>(a))
25+
{}
26+
27+
constant_medium(shared_ptr<hittable> b, double d, color c)
28+
: boundary(b), neg_inv_density(-1/d), phase_function(make_shared<isotropic>(c))
29+
{}
30+
31+
bool hit(const ray& r, interval ray_t, hit_record& rec) const override {
32+
// Print occasional samples when debugging. To enable, set enableDebug true.
33+
const bool enableDebug = false;
34+
const bool debugging = enableDebug && random_double() < 0.00001;
35+
36+
hit_record rec1, rec2;
37+
38+
if (!boundary->hit(r, interval::universe, rec1))
39+
return false;
40+
41+
if (!boundary->hit(r, interval(rec1.t+0.0001, infinity), rec2))
42+
return false;
43+
44+
if (debugging) std::cerr << "\nt_min=" << rec1.t << ", t_max=" << rec2.t << '\n';
45+
46+
if (rec1.t < ray_t.min) rec1.t = ray_t.min;
47+
if (rec2.t > ray_t.max) rec2.t = ray_t.max;
48+
49+
if (rec1.t >= rec2.t)
50+
return false;
51+
52+
if (rec1.t < 0)
53+
rec1.t = 0;
54+
55+
const auto ray_length = r.direction().length();
56+
const auto distance_inside_boundary = (rec2.t - rec1.t) * ray_length;
57+
const auto hit_distance = neg_inv_density * log(random_double());
58+
59+
if (hit_distance > distance_inside_boundary)
60+
return false;
61+
62+
rec.t = rec1.t + hit_distance / ray_length;
63+
rec.p = r.at(rec.t);
64+
65+
if (debugging) {
66+
std::cerr << "hit_distance = " << hit_distance << '\n'
67+
<< "rec.t = " << rec.t << '\n'
68+
<< "rec.p = " << rec.p << '\n';
69+
}
70+
71+
rec.normal = vec3(1,0,0); // arbitrary
72+
rec.front_face = true; // also arbitrary
73+
rec.mat = phase_function;
74+
75+
return true;
76+
}
77+
78+
aabb bounding_box() const override { return boundary->bounding_box(); }
79+
80+
public:
81+
shared_ptr<hittable> boundary;
82+
double neg_inv_density;
83+
shared_ptr<material> phase_function;
84+
};
85+
86+
87+
#endif

src/TheRestOfYourLife/main.cc

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "box.h"
1616
#include "camera.h"
1717
#include "color.h"
18+
#include "constant_medium.h"
1819
#include "hittable_list.h"
1920
#include "material.h"
2021
#include "scene.h"
@@ -63,6 +64,48 @@ void cornell_box(scene& scene_desc) {
6364
lights.add(make_shared<sphere>(point3(190, 90, 190), 90, shared_ptr<material>()));
6465
}
6566

67+
void cornell_smoke(scene& scene_desc) {
68+
scene_desc.image_width = 600;
69+
scene_desc.aspect_ratio = 1.0;
70+
scene_desc.samples_per_pixel = 100;
71+
scene_desc.max_depth = 50;
72+
scene_desc.background = color(0,0,0);
73+
74+
scene_desc.cam.lookfrom = point3(278, 278, -800);
75+
scene_desc.cam.lookat = point3(278, 278, 0);
76+
scene_desc.cam.vup = vec3(0, 1, 0);
77+
scene_desc.cam.vfov = 40.0;
78+
scene_desc.cam.aperture = 0.0;
79+
scene_desc.cam.focus_dist = 10.0;
80+
81+
hittable_list& world = scene_desc.world;
82+
83+
auto red = make_shared<lambertian>(color(.65, .05, .05));
84+
auto white = make_shared<lambertian>(color(.73, .73, .73));
85+
auto green = make_shared<lambertian>(color(.12, .45, .15));
86+
auto light = make_shared<diffuse_light>(color(15, 15, 15));
87+
88+
world.add(make_shared<yz_rect>(0, 555, 0, 555, 555, green));
89+
world.add(make_shared<yz_rect>(0, 555, 0, 555, 0, red));
90+
world.add(make_shared<flip_face>(make_shared<xz_rect>(213, 343, 227, 332, 554, light)));
91+
world.add(make_shared<xz_rect>(0, 555, 0, 555, 555, white));
92+
world.add(make_shared<xz_rect>(0, 555, 0, 555, 0, white));
93+
world.add(make_shared<xy_rect>(0, 555, 0, 555, 555, white));
94+
95+
shared_ptr<hittable> box1 = make_shared<box>(point3(0,0,0), point3(165,330,165), white);
96+
box1 = make_shared<rotate_y>(box1, 15);
97+
box1 = make_shared<translate>(box1, vec3(265,0,295));
98+
99+
shared_ptr<hittable> box2 = make_shared<box>(point3(0,0,0), point3(165,165,165), white);
100+
box2 = make_shared<rotate_y>(box2, -18);
101+
box2 = make_shared<translate>(box2, vec3(130,0,65));
102+
103+
world.add(make_shared<constant_medium>(box1, 0.01, color(0,0,0)));
104+
world.add(make_shared<constant_medium>(box2, 0.01, color(1,1,1)));
105+
106+
hittable_list& lights = scene_desc.lights;
107+
lights.add(make_shared<xz_rect>(213, 343, 227, 332, 554, shared_ptr<material>()));
108+
}
66109

67110
int main() {
68111
scene scene_desc;

src/TheRestOfYourLife/material.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -151,18 +151,17 @@ class isotropic : public material {
151151
isotropic(color c) : albedo(make_shared<solid_color>(c)) {}
152152
isotropic(shared_ptr<texture> a) : albedo(a) {}
153153

154-
#if 0
155-
// Issue #669
156-
// This method doesn't match the signature in the base `material` class, so this one's
157-
// never actually called. Disabling this definition until we sort this out.
154+
bool scatter(const ray& r_in, const hit_record& rec, scatter_record& srec) const override {
155+
srec.attenuation = albedo->value(rec.u, rec.v, rec.p);
156+
srec.pdf_ptr = make_shared<sphere_pdf>();
157+
srec.skip_pdf = false;
158+
return true;
159+
}
158160

159-
bool scatter(const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered)
161+
double scattering_pdf(const ray& r_in, const hit_record& rec, const ray& scattered)
160162
const override {
161-
scattered = ray(rec.p, random_in_unit_sphere(), r_in.time());
162-
attenuation = albedo->value(rec.u, rec.v, rec.p);
163-
return true;
163+
return 1 / (4 * pi);
164164
}
165-
#endif
166165

167166
public:
168167
shared_ptr<texture> albedo;

src/TheRestOfYourLife/pdf.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,20 @@ class cosine_pdf : public pdf {
4343
};
4444

4545

46+
class sphere_pdf : public pdf {
47+
public:
48+
sphere_pdf() { }
49+
50+
double value(const vec3& direction) const override {
51+
return 1/ (4 * pi);
52+
}
53+
54+
vec3 generate() const override {
55+
return random_unit_vector();
56+
}
57+
};
58+
59+
4660
class hittable_pdf : public pdf {
4761
public:
4862
hittable_pdf(const hittable_list& _objects, const point3& _origin)

0 commit comments

Comments
 (0)