Skip to content

Commit f655b1c

Browse files
committed
Move vec methods from material.h, pdf.h to vec3.h
Also, eliminate a duplicate (and inconsistent) implementations. It's interesting to note that this includes the formulation of random_unit_vector() that performs better than the method that picks random points from a box until one is chosen that lies in the inscribed sphere.
1 parent 359afb6 commit f655b1c

File tree

8 files changed

+62
-152
lines changed

8 files changed

+62
-152
lines changed

books/RayTracingInOneWeekend.html

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,19 +1316,19 @@
13161316
the unit ball, and then normalizing those.
13171317

13181318
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
1319-
vec3 random_on_unit_sphere() {
1319+
vec3 random_unit_vector() {
13201320
return unit_vector(random_in_unit_sphere());
13211321
}
13221322
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1323-
[Listing [random-on-unit-sphere]: <kbd>[material.h]</kbd> The random_on_unit_sphere() function]
1323+
[Listing [random-unit-vector]: <kbd>[vec3.h]</kbd> The random_unit_vector() function]
13241324

13251325
![Figure [rand-unit-vector]: Generating a random unit vector](../images/fig.rand-unitvector.png)
13261326

13271327
</div>
13281328

13291329

13301330
<div class='together'>
1331-
This `random_on_unit_sphere()` is a drop-in replacement for the existing `random_in_unit_sphere()`
1331+
This `random_unit_vector()` is a drop-in replacement for the existing `random_in_unit_sphere()`
13321332
function.
13331333

13341334
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
@@ -1338,7 +1338,7 @@
13381338
if (depth <= 0)
13391339
return vec3(0,0,0);
13401340
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
1341-
vec3 target = rec.p + rec.normal + random_on_unit_sphere();
1341+
vec3 target = rec.p + rec.normal + random_unit_vector();
13421342
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
13431343
return 0.5 * ray_color(ray(rec.p, target - rec.p), world, depth-1);
13441344
}
@@ -1399,10 +1399,8 @@
13991399
return -in_unit_sphere;
14001400
}
14011401
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1402-
[Listing [random-in-hemisphere]: <kbd>[material.h]</kbd> The random_in_hemisphere(normal) function]
1402+
[Listing [random-in-hemisphere]: <kbd>[vec3.h]</kbd> The random_in_hemisphere(normal) function]
14031403

1404-
Note that the functionality should be identical between `random_in_unit_sphere()` and
1405-
`random_on_unit_sphere()`
14061404
</div>
14071405

14081406
<div class='together'>
@@ -1435,7 +1433,8 @@
14351433
<div class='together'>
14361434
Scenes will become more complicated over the course of the book. You are encouraged to
14371435
switch between the different diffuse renderers presented here. Most scenes of interest will contain
1438-
a disproportionate amount of diffuse materials. You can gain valuable insight by understanding the effect of different diffuse methods on the lighting of the scene.
1436+
a disproportionate amount of diffuse materials. You can gain valuable insight by understanding the
1437+
effect of different diffuse methods on the lighting of the scene.
14391438
</div>
14401439

14411440
Metal
@@ -1616,7 +1615,7 @@
16161615
return v - 2*dot(v,n)*n;
16171616
}
16181617
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1619-
[Listing [vec3-reflect]: <kbd>[material.h]</kbd> vec3 reflection function]
1618+
[Listing [vec3-reflect]: <kbd>[vec3.h]</kbd> vec3 reflection function]
16201619
</div>
16211620

16221621
<div class='together'>
@@ -1729,18 +1728,9 @@
17291728
The bigger the sphere, the fuzzier the reflections will be. This suggests adding a fuzziness
17301729
parameter that is just the radius of the sphere (so zero is no perturbation). The catch is that for
17311730
big spheres or grazing rays, we may scatter below the surface. We can just have the surface
1732-
absorb those. We’ll put a maximum of 1 on the radius of the sphere which yields:
1731+
absorb those.
17331732

1734-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
1735-
vec3 random_in_unit_sphere() {
1736-
vec3 p;
1737-
do {
1738-
p = 2*vec3(random_double(), random_double(), random_double()) - vec3(1,1,1);
1739-
} while (p.squared_length() >= 1);
1740-
return p;
1741-
}
17421733
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
1743-
17441734
class metal : public material {
17451735
public:
17461736
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
@@ -1763,7 +1753,7 @@
17631753
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
17641754
};
17651755
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1766-
[Listing [metal-fuzz]: <kbd>[main.cc]</kbd> Metal spheres with fuzziness]
1756+
[Listing [metal-fuzz]: <kbd>[material.h]</kbd> Metal spheres with fuzziness]
17671757

17681758
In order to generate a random point inside a unit sphere (`random_in_unit_sphere()`), we used one of
17691759
the easiest algorithms: a rejection method. First, pick a random point in the unit cube where x, y,
@@ -1832,7 +1822,7 @@
18321822
return true;
18331823
}
18341824
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1835-
[Listing [refract]: <kbd>[material.h]</kbd> Refraction function]
1825+
[Listing [refract]: <kbd>[vec3.h]</kbd> Refraction function]
18361826
</div>
18371827

18381828
<div class='together'>

books/RayTracingTheRestOfYourLife.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -548,11 +548,11 @@
548548
return p;
549549
}
550550

551-
vec3 random_on_unit_sphere() {
551+
vec3 random_unit_vector() {
552552
return unit_vector(random_in_unit_sphere());
553553
}
554554
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
555-
[Listing [random-on-unit-sphere]: <kbd>[pdf.h]</kbd> Random point on the unit sphere]
555+
[Listing [random-unit-vector]: <kbd>[vec3.h]</kbd> Random vector of unit length]
556556
</div>
557557

558558
<div class='together'>
@@ -569,7 +569,7 @@
569569
int N = 1000000;
570570
auto sum = 0.0;
571571
for (int i = 0; i < N; i++) {
572-
vec3 d = random_on_unit_sphere();
572+
vec3 d = random_unit_vector();
573573
auto cosine_squared = d.z()*d.z();
574574
sum += cosine_squared / pdf(d);
575575
}
@@ -809,7 +809,7 @@
809809
bool scatter(
810810
const ray& r_in, const hit_record& rec, vec3& alb, ray& scattered, double& pdf
811811
) const {
812-
vec3 target = rec.p + rec.normal + random_on_unit_sphere();
812+
vec3 target = rec.p + rec.normal + random_unit_vector();
813813
scattered = ray(rec.p, unit_vector(target-rec.p), r_in.time());
814814
alb = albedo->value(rec.u, rec.v, rec.p);
815815
pdf = dot(rec.normal, scattered.direction()) / pi;

src/InOneWeekend/material.h

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -24,50 +24,6 @@ double schlick(double cosine, double ref_idx) {
2424
}
2525

2626

27-
bool refract(const vec3& v, const vec3& n, double ni_over_nt, vec3& refracted) {
28-
vec3 uv = unit_vector(v);
29-
auto dt = dot(uv, n);
30-
auto discriminant = 1.0 - ni_over_nt*ni_over_nt*(1-dt*dt);
31-
32-
if (discriminant <= 0)
33-
return false;
34-
35-
refracted = ni_over_nt*(uv - n*dt) - n*sqrt(discriminant);
36-
return true;
37-
}
38-
39-
40-
vec3 reflect(const vec3& v, const vec3& n) {
41-
return v - 2*dot(v,n)*n;
42-
}
43-
44-
45-
vec3 random_unit_vector() {
46-
auto a = 2*pi * random_double();
47-
auto z = 2*random_double() - 1;
48-
auto r = sqrt(1 - z*z);
49-
return vec3(r*cos(a), r*sin(a), z);
50-
}
51-
52-
53-
vec3 random_in_unit_sphere() {
54-
vec3 p;
55-
do {
56-
p = 2.0*vec3(random_double(),random_double(),random_double()) - vec3(1,1,1);
57-
} while (p.squared_length() >= 1.0);
58-
return p;
59-
}
60-
61-
62-
vec3 random_in_hemisphere(const vec3& normal) {
63-
vec3 in_unit_sphere = random_in_unit_sphere();
64-
if (dot(in_unit_sphere, normal) > 0.0) // In the same hemisphere as the normal
65-
return in_unit_sphere;
66-
else
67-
return -in_unit_sphere;
68-
}
69-
70-
7127
class material {
7228
public:
7329
virtual bool scatter(

src/TheNextWeek/material.h

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -22,40 +22,6 @@ double schlick(double cosine, double ref_idx) {
2222
return r0 + (1-r0)*pow((1 - cosine),5);
2323
}
2424

25-
bool refract(const vec3& v, const vec3& n, double ni_over_nt, vec3& refracted) {
26-
vec3 uv = unit_vector(v);
27-
auto dt = dot(uv, n);
28-
auto discriminant = 1.0 - ni_over_nt*ni_over_nt*(1-dt*dt);
29-
30-
if (discriminant <= 0)
31-
return false;
32-
33-
refracted = ni_over_nt*(uv - n*dt) - n*sqrt(discriminant);
34-
return true;
35-
}
36-
37-
38-
vec3 reflect(const vec3& v, const vec3& n) {
39-
return v - 2*dot(v,n)*n;
40-
}
41-
42-
43-
vec3 random_unit_vector() {
44-
auto a = 2*pi * random_double();
45-
auto z = 2*random_double() - 1;
46-
auto r = sqrt(1 - z*z);
47-
return vec3(r*cos(a), r*sin(a), z);
48-
}
49-
50-
51-
vec3 random_in_unit_sphere() {
52-
vec3 p;
53-
do {
54-
p = 2.0*vec3(random_double(),random_double(),random_double()) - vec3(1,1,1);
55-
} while (dot(p,p) >= 1.0);
56-
return p;
57-
}
58-
5925

6026
class material {
6127
public:

src/TheRestOfYourLife/material.h

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,6 @@ double schlick(double cosine, double ref_idx) {
2323
}
2424

2525

26-
bool refract(const vec3& v, const vec3& n, double ni_over_nt, vec3& refracted) {
27-
vec3 uv = unit_vector(v);
28-
auto dt = dot(uv, n);
29-
auto discriminant = 1.0 - ni_over_nt*ni_over_nt*(1-dt*dt);
30-
31-
if (discriminant <= 0)
32-
return false;
33-
34-
refracted = ni_over_nt*(uv - n*dt) - n*sqrt(discriminant);
35-
return true;
36-
}
37-
38-
39-
vec3 reflect(const vec3& v, const vec3& n) {
40-
return v - 2*dot(v,n)*n;
41-
}
42-
43-
4426
struct scatter_record
4527
{
4628
ray specular_ray;

src/TheRestOfYourLife/pdf.h

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ inline vec3 random_cosine_direction() {
2525
return vec3(x, y, z);
2626
}
2727

28+
2829
inline vec3 random_to_sphere(double radius, double distance_squared) {
2930
auto r1 = random_double();
3031
auto r2 = random_double();
@@ -35,25 +36,6 @@ inline vec3 random_to_sphere(double radius, double distance_squared) {
3536
return vec3(x, y, z);
3637
}
3738

38-
vec3 random_in_unit_sphere() {
39-
vec3 p;
40-
do {
41-
p = 2*vec3(random_double(),random_double(),random_double()) - vec3(1,1,1);
42-
} while (p.squared_length() >= 1);
43-
return p;
44-
}
45-
46-
vec3 random_on_unit_sphere() {
47-
return unit_vector(random_in_unit_sphere());
48-
}
49-
50-
vec3 random_in_hemisphere(const vec3& normal) {
51-
vec3 in_unit_sphere = random_in_unit_sphere();
52-
if (dot(in_unit_sphere, normal) > 0.0) // In the same hemisphere as the normal
53-
return in_unit_sphere;
54-
else
55-
return -in_unit_sphere;
56-
}
5739

5840
class pdf {
5941
public:
@@ -62,6 +44,7 @@ class pdf {
6244
virtual ~pdf() {}
6345
};
6446

47+
6548
class cosine_pdf : public pdf {
6649
public:
6750
cosine_pdf(const vec3& w) { uvw.build_from_w(w); }
@@ -78,6 +61,7 @@ class cosine_pdf : public pdf {
7861
onb uvw;
7962
};
8063

64+
8165
class hittable_pdf : public pdf {
8266
public:
8367
hittable_pdf(hittable *p, const vec3& origin) : ptr(p), o(origin) {}
@@ -91,6 +75,7 @@ class hittable_pdf : public pdf {
9175
hittable *ptr;
9276
};
9377

78+
9479
class mixture_pdf : public pdf {
9580
public:
9681
mixture_pdf(pdf *p0, pdf *p1) { p[0] = p0; p[1] = p1; }
@@ -106,4 +91,5 @@ class mixture_pdf : public pdf {
10691
pdf *p[2];
10792
};
10893

94+
10995
#endif

src/TheRestOfYourLife/sphere_importance.cc

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,17 @@
1616
#include <math.h>
1717
#include <stdlib.h>
1818

19-
vec3 random_in_unit_sphere() {
20-
vec3 p;
21-
do {
22-
p = 2*vec3(random_double(), random_double(), random_double()) - vec3(1,1,1);
23-
} while (p.squared_length() >= 1);
24-
return p;
25-
}
26-
27-
vec3 random_on_unit_sphere() {
28-
return unit_vector(random_in_unit_sphere());
29-
}
3019

3120
inline double pdf(const vec3& p) {
3221
return 1.0 / (4.0*pi);
3322
}
3423

24+
3525
int main() {
3626
int N = 1000000;
3727
auto sum = 0.0;
3828
for (int i = 0; i < N; i++) {
39-
vec3 d = random_on_unit_sphere();
29+
vec3 d = random_unit_vector();
4030
auto cosine_squared = d.z()*d.z();
4131
sum += cosine_squared / pdf(d);
4232
}

src/common/vec3.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,44 @@ vec3 random_in_unit_disk() {
131131
return p;
132132
}
133133

134+
vec3 random_unit_vector() {
135+
auto a = 2*pi * random_double();
136+
auto z = 2*random_double() - 1;
137+
auto r = sqrt(1 - z*z);
138+
return vec3(r*cos(a), r*sin(a), z);
139+
}
140+
141+
vec3 random_in_unit_sphere() {
142+
vec3 p;
143+
do {
144+
p = 2.0*vec3(random_double(),random_double(),random_double()) - vec3(1,1,1);
145+
} while (p.squared_length() >= 1.0);
146+
return p;
147+
}
148+
149+
vec3 random_in_hemisphere(const vec3& normal) {
150+
vec3 in_unit_sphere = random_in_unit_sphere();
151+
if (dot(in_unit_sphere, normal) > 0.0) // In the same hemisphere as the normal
152+
return in_unit_sphere;
153+
else
154+
return -in_unit_sphere;
155+
}
156+
157+
vec3 reflect(const vec3& v, const vec3& n) {
158+
return v - 2*dot(v,n)*n;
159+
}
160+
161+
bool refract(const vec3& v, const vec3& n, double ni_over_nt, vec3& refracted) {
162+
vec3 uv = unit_vector(v);
163+
auto dt = dot(uv, n);
164+
auto discriminant = 1.0 - ni_over_nt*ni_over_nt*(1-dt*dt);
165+
166+
if (discriminant <= 0)
167+
return false;
168+
169+
refracted = ni_over_nt*(uv - n*dt) - n*sqrt(discriminant);
170+
return true;
171+
}
172+
173+
134174
#endif

0 commit comments

Comments
 (0)