Skip to content

Commit 2710a1d

Browse files
committed
Untested: ray_color takes in lights
The prior code had multiple implementations of `ray_color()` that created a new light on every ray bounce. This change now passes in the light shape from the scene. NOTE: This change is untested. We have big changes pending for book three when we begin v4.0.0 development soon, so I expect that this code will be heavily modified (and tested) at that time. Resolves #759
1 parent 1602c7c commit 2710a1d

File tree

3 files changed

+69
-91
lines changed

3 files changed

+69
-91
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Change Log -- Ray Tracing in One Weekend
1717
(#748)
1818
- Fix: Synchronize book and source for `cornell_box()` function.
1919
- Fix: Introduction of light code was introduced out of sequence (#738, #740)
20+
- Fix: `ray_color()` was creating a new light for every ray bounce (#759)
2021

2122

2223
----------------------------------------------------------------------------------------------------

books/RayTracingTheNextWeek.html

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,10 +1399,7 @@
13991399

14001400
camera cam(lookfrom, lookat, vup, vfov, aspect_ratio, aperture, dist_to_focus, 0.0, 1.0);
14011401
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
1402-
1403-
// Render
1404-
1405-
std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n";
1402+
...
14061403
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14071404
[Listing [scene-two-checker-view]: <kbd>[main.cc]</kbd> Second scene]
14081405
</div>
@@ -1856,7 +1853,7 @@
18561853
auto vv = v*v*(3-2*v);
18571854
auto ww = w*w*(3-2*w);
18581855
auto accum = 0.0;
1859-
1856+
18601857
for (int i=0; i < 2; i++)
18611858
for (int j=0; j < 2; j++)
18621859
for (int k=0; k < 2; k++) {
@@ -1866,7 +1863,7 @@
18661863
* (k*ww + (1-k)*(1-ww))
18671864
* dot(c[i][j][k], weight_v);
18681865
}
1869-
1866+
18701867
return accum;
18711868
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
18721869
}

books/RayTracingTheRestOfYourLife.html

Lines changed: 65 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1764,17 +1764,13 @@
17641764
<div class='together'>
17651765
And then change `ray_color()`:
17661766

1767+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
1768+
color ray_color(
1769+
const ray& r, const color& background, const hittable& world,
1770+
shared_ptr<hittable>& lights, int depth
1771+
) {
17671772
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
1768-
color ray_color(const ray& r, const color& background, const hittable& world, int depth) {
1769-
hit_record rec;
1770-
1771-
// If we've exceeded the ray bounce limit, no more light is gathered.
1772-
if (depth <= 0)
1773-
return color(0,0,0);
1774-
1775-
// If the ray hits nothing, return the background color.
1776-
if (!world.hit(r, 0.001, infinity, rec))
1777-
return background;
1773+
...
17781774

17791775
ray scattered;
17801776
color attenuation;
@@ -1786,18 +1782,39 @@
17861782

17871783

17881784
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
1789-
shared_ptr<hittable> light_shape =
1790-
make_shared<xz_rect>(213, 343, 227, 332, 554, shared_ptr<material>());
1791-
hittable_pdf p(light_shape, rec.p);
1785+
hittable_pdf light_pdf(lights, rec.p);
1786+
scattered = ray(rec.p, light_pdf.generate(), r.time());
1787+
pdf_val = light_pdf.value(scattered.direction());
17921788
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
17931789

1794-
scattered = ray(rec.p, p.generate(), r.time());
1795-
pdf_val = p.value(scattered.direction());
1796-
17971790
return emitted
17981791
+ albedo * rec.mat_ptr->scattering_pdf(r, rec, scattered)
1799-
* ray_color(scattered, background, world, depth-1) / pdf_val;
1792+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
1793+
* ray_color(scattered, background, world, lights, depth-1) / pdf_val;
1794+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
18001795
}
1796+
1797+
...
1798+
int main() {
1799+
...
1800+
// World
1801+
1802+
auto world = cornell_box();
1803+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
1804+
shared_ptr<hittable> lights =
1805+
make_shared<xz_rect>(213, 343, 227, 332, 554, shared_ptr<material>());
1806+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
1807+
1808+
...
1809+
for (int j = image_height-1; j >= 0; --j) {
1810+
std::cerr << "\rScanlines remaining: " << j << ' ' << std::flush;
1811+
for (int i = 0; i < image_width; ++i) {
1812+
...
1813+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
1814+
pixel_color += ray_color(r, background, world, lights, max_depth);
1815+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
1816+
...
1817+
18011818
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18021819
[Listing [ray-color-hittable-pdf]: <kbd>[main.cc]</kbd> ray_color function with hittable PDF]
18031820
</div>
@@ -1847,16 +1864,11 @@
18471864
And plugging it into `ray_color()`:
18481865

18491866
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
1850-
color ray_color(const ray& r, const color& background, const hittable& world, int depth) {
1851-
hit_record rec;
1852-
1853-
// If we've exceeded the ray bounce limit, no more light is gathered.
1854-
if (depth <= 0)
1855-
return color(0,0,0);
1856-
1857-
// If the ray hits nothing, return the background color.
1858-
if (!world.hit(r, 0.001, infinity, rec))
1859-
return background;
1867+
color ray_color(
1868+
const ray& r, const color& background, const hittable& world,
1869+
shared_ptr<hittable>& lights, int depth
1870+
) {
1871+
...
18601872

18611873
ray scattered;
18621874
color attenuation;
@@ -1866,20 +1878,16 @@
18661878
if (!rec.mat_ptr->scatter(r, rec, albedo, scattered, pdf_val))
18671879
return emitted;
18681880

1869-
shared_ptr<hittable> light_shape =
1870-
make_shared<xz_rect>(213, 343, 227, 332, 554, make_shared<material>());
18711881
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
1872-
auto p0 = make_shared<hittable_pdf>(light_shape, rec.p);
1882+
auto p0 = make_shared<hittable_pdf>(lights, rec.p);
18731883
auto p1 = make_shared<cosine_pdf>(rec.normal);
1874-
mixture_pdf p(p0, p1);
1875-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
1884+
mixture_pdf mixed_pdf(p0, p1);
18761885

1877-
scattered = ray(rec.p, p.generate(), r.time());
1878-
pdf_val = p.value(scattered.direction());
1886+
scattered = ray(rec.p, mixed_pdf.generate(), r.time());
1887+
pdf_val = mixed_pdf.value(scattered.direction());
1888+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
18791889

1880-
return emitted
1881-
+ albedo * rec.mat_ptr->scattering_pdf(r, rec, scattered)
1882-
* ray_color(scattered, background, world, depth-1) / pdf_val;
1890+
...
18831891
}
18841892
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18851893
[Listing [ray-color-mixture]: <kbd>[main.cc]</kbd> The ray_color function, using mixture PDF]
@@ -2043,15 +2051,16 @@
20432051
<div class='together'>
20442052
And `ray_color()` changes are small:
20452053

2046-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
2054+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
20472055
color ray_color(
20482056
const ray& r,
20492057
const color& background,
20502058
const hittable& world,
2051-
shared_ptr<hittable> lights,
2059+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
2060+
shared_ptr<hittable>& lights,
2061+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
20522062
int depth
20532063
) {
2054-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
20552064
hit_record rec;
20562065

20572066
// If we've exceeded the ray bounce limit, no more light is gathered.
@@ -2086,22 +2095,13 @@
20862095
...
20872096
// World
20882097

2098+
auto world = cornell_box();
20892099
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
20902100
auto lights = make_shared<hittable_list>();
20912101
lights->add(make_shared<xz_rect>(213, 343, 227, 332, 554, shared_ptr<material>()));
20922102
lights->add(make_shared<sphere>(point3(190, 90, 190), 90, shared_ptr<material>()));
20932103
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
2094-
2095-
auto world = cornell_box();
2096-
2097-
color background(0,0,0);
2098-
2099-
for (int j = image_height-1; j >= 0; --j) {
2100-
std::cerr << "\rScanlines remaining: " << j << ' ' << std::flush;
2101-
for (int i = 0; i < image_width; ++i) {
2102-
...
2103-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
2104-
pixel_color += ray_color(r, background, world, lights, max_depth);
2104+
...
21052105
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21062106
[Listing [ray-color-scatter]: <kbd>[main.cc]</kbd> Ray color with scatter]
21072107
</div>
@@ -2173,41 +2173,25 @@
21732173
const ray& r,
21742174
const color& background,
21752175
const hittable& world,
2176-
shared_ptr<hittable> lights,
2176+
shared_ptr<hittable>& lights,
21772177
int depth
21782178
) {
2179-
hit_record rec;
2180-
2181-
// If we've exceeded the ray bounce limit, no more light is gathered.
2182-
if (depth <= 0)
2183-
return color(0,0,0);
2184-
2185-
// If the ray hits nothing, return the background color.
2186-
if (!world.hit(r, 0.001, infinity, rec))
2187-
return background;
2179+
...
21882180

21892181
scatter_record srec;
21902182
color emitted = rec.mat_ptr->emitted(r, rec, rec.u, rec.v, rec.p);
21912183
if (!rec.mat_ptr->scatter(r, rec, srec))
21922184
return emitted;
21932185

2186+
21942187
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
21952188
if (srec.is_specular) {
21962189
return srec.attenuation
21972190
* ray_color(srec.specular_ray, background, world, lights, depth-1);
21982191
}
21992192
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
22002193

2201-
shared_ptr<pdf> light_ptr = make_shared<hittable_pdf>(lights, rec.p);
2202-
mixture_pdf p(light_ptr, srec.pdf_ptr);
2203-
2204-
ray scattered = ray(rec.p, p.generate(), r.time());
2205-
auto pdf_val = p.value(scattered.direction());
2206-
delete srec.pdf_ptr;
2207-
2208-
return emitted + srec.attenuation
2209-
* rec.mat_ptr->scattering_pdf(r, rec, scattered)
2210-
* ray_color(scattered, background, world, lights, depth-1) / pdf_val;
2194+
...
22112195
}
22122196
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22132197
[Listing [ray-color-implicit]: <kbd>[main.cc]</kbd>
@@ -2383,21 +2367,17 @@
23832367
We can first try just sampling the sphere rather than the light:
23842368

23852369
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
2386-
shared_ptr<hittable> light_shape = make_shared<xz_rect>(213, 343, 227, 332, 554, 0);
2387-
shared_ptr<hittable> glass_sphere = make_shared<sphere>(point3(190, 90, 190), 90, 0);
2388-
2389-
...
2370+
int main() {
2371+
...
2372+
// World
23902373

2391-
for (int j = image_height-1; j >= 0; --j) {
2392-
std::cerr << "\rScanlines remaining: " << j << ' ' << std::flush;
2393-
for (int i = 0; i < image_width; ++i) {
2394-
color pixel_color(0, 0, 0);
2395-
for (int s=0; s < ns; ++s) {
2396-
auto u = (i + random_double()) / image_width;
2397-
auto v = (j + random_double()) / image_height;
2398-
ray r = cam->get_ray(u, v);
2399-
pixel_color += ray_color(r, background, world, glass_sphere, max_depth);
2400-
}
2374+
auto world = cornell_box();
2375+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
2376+
shared_ptr<hittable> lights =
2377+
// make_shared<xz_rect>(213, 343, 227, 332, 554, shared_ptr<material>());
2378+
make_shared<sphere>(point3(190, 90, 190), 90, shared_ptr<material>());
2379+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
2380+
...
24012381
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24022382
[Listing [sampling-sphere]: <kbd>[main.cc]</kbd> Sampling just the sphere]
24032383
</div>

0 commit comments

Comments
 (0)