Skip to content

Commit ce5bcb6

Browse files
committed
Render 2023 Christmas image
Merry (late) Christmas!
1 parent 66d10ec commit ce5bcb6

File tree

6 files changed

+233
-34
lines changed

6 files changed

+233
-34
lines changed
2.2 MB
Loading

src/bvh.h

+23-18
Original file line numberDiff line numberDiff line change
@@ -245,16 +245,16 @@ class BVH : public Hittable {
245245
continue;
246246
}
247247

248-
/* Divide `centroids_bounds[axis]` into `NUM_BUCKETS` equally-sized regions (each of these
249-
regions is called a "bucket") along the current axis. For each bucket, we then need to
250-
compute its corresponding `BucketInfo`: the number of primitives whose centroids lie
251-
inside that bucket, and the AABB of all those centroids. The `BucketInfo` for bucket
248+
/* Divide `centroids_bounds[axis]` into `NUM_BUCKETS` equally-sized regions (each of
249+
these regions is called a "bucket") along the current axis. For each bucket, we then
250+
need to compute its corresponding `BucketInfo`: the number of primitives whose centroids
251+
lie inside that bucket, and the AABB of all those centroids. The `BucketInfo` for bucket
252252
`i` is stored in `buckets[i]`. */
253253
std::vector<BucketInfo> buckets(NUM_BUCKETS);
254254
/* To compute the `BucketInfo` for all buckets (the number of primitives whose centroids
255255
lie inside each bucket, as well as the AABB for the centroids), we iterate through the
256-
all the primitives in `curr_primitives`. For each, determine which bucket (region) it lies
257-
in, and update that bucket correspondingly. */
256+
all the primitives in `curr_primitives`. For each primitive, we determine which bucket
257+
(region) it lies in, and update that bucket accordingly. */
258258
for (auto &primitive : curr_primitives) {
259259

260260
/* Compute the bucket along the current axis in which the current primitive's AABB's
@@ -368,8 +368,8 @@ class BVH : public Hittable {
368368
* static_cast<double>(num_primitives_after_split);
369369
}
370370

371-
/* Update `min_split_cost`, `optimal_split_bucket`, and `optimal_split_axis` with all the
372-
buckets we tested along the current `axis` */
371+
/* Update `min_split_cost`, `optimal_split_bucket`, and `optimal_split_axis` with all
372+
the buckets we tested along the current `axis` */
373373
for (size_t i = 0; i < NUM_BUCKETS - 1; ++i) {
374374
/* Again, we are looking for the split that leads to the minimum cost. */
375375
if (costs[i] < min_split_cost) {
@@ -410,14 +410,16 @@ class BVH : public Hittable {
410410
distribution to the current INTERIOR node's left and right children. */
411411
if (curr_primitives.size() > MAX_PRIMITIVES_IN_NODE || min_split_cost < leaf_cost) {
412412

413-
/* Split `objects` into two sets, the first containing all objects that fall into bucket
414-
at most `optimal_split_bucket` along the axis `optimal_split_axis`, and the second containing
415-
all other objects. To do this, we use `std::partition` on `objects`. */
413+
/* Split `objects` into two sets along the axis `optimal_split_axis`, the first of which
414+
will contain all primitives whose bucket number is at most `optimal_split_bucket`, and
415+
the second of which will contain all the other primitives. To perform the split, we
416+
apply `std::partition` to `objects`. */
416417
auto mid = std::partition(curr_primitives.begin(), curr_primitives.end(),
417-
[&](const std::shared_ptr<Hittable> &object) {
418-
/* Copied from above; determine which bucket the current `object`'s centroid lies
419-
in */
420-
auto offset = (object->get_aabb().centroid()[optimal_split_axis]
418+
[&](const std::shared_ptr<Hittable> &primitive) {
419+
/* First, we determine which bucket the current `primitive`'s centroid lies in.
420+
The code to determine the bucket for a given primitive is the same as used
421+
previously. */
422+
auto offset = (primitive->get_aabb().centroid()[optimal_split_axis]
421423
- centroids_bounds[optimal_split_axis].min)
422424
/ centroids_bounds[optimal_split_axis].size();
423425
auto curr_bucket = static_cast<size_t>(static_cast<double>(NUM_BUCKETS) * offset);
@@ -437,8 +439,11 @@ class BVH : public Hittable {
437439
axis `optimal_split_axis` that fall in buckets at most `optimal_split_bucket`; the
438440
primitives with axis coordinates at most the optimal coordinate split threshold),
439441
and the right child (`right_child`) will be built over the primitives to the right
440-
of the partition. */
441-
auto left_child = build_bvh_tree(curr_primitives.subspan(0, mid)); /* `std::span::subspan`! */
442+
of the partition. After applying `std::partition` to `curr_primitives`, this is
443+
equivalent to saying that `left_child` will be built over `curr_primitives[0..mid)`,
444+
and that `right_child` will be built over `curr_primitives[mid..)`. This is very
445+
conveniently expressed using `std::span::subspan`. */
446+
auto left_child = build_bvh_tree(curr_primitives.subspan(0, mid));
442447
auto right_child = build_bvh_tree(curr_primitives.subspan(mid));
443448

444449
/* Again, in this case, the current node will be an interior node. */
@@ -531,7 +536,7 @@ class BVH : public Hittable {
531536
}
532537

533538
/* Flattens the BVH tree constructed in `build_bvh_tree` (rooted at `tree_root`), and
534-
stores the result in `linear_bvh_nodes`. This consumes the BVH tree in the result,
539+
stores the result in `linear_bvh_nodes`. This consumes the BVH tree in the process,
535540
freeing all associated memory. */
536541
auto flatten_bvh_tree(std::unique_ptr<BVHTreeNode> tree_root) {
537542
/* Because we computed `total_bvhnodes`, we are able to allocate the exact

src/camera.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,8 @@ class Camera {
200200
}
201201

202202
/* Computes and returns the color of the light ray `ray` shot into the `Hittable`
203-
specified by `world`. If `ray` has bounced more than `depth_left` times, returns `RGB::zero()`. */
203+
specified by `world`. If `ray` has bounced more than `depth_left` times, returns
204+
`RGB::zero()`. */
204205
template<typename T>
205206
requires std::is_base_of_v<Hittable, T>
206207
auto ray_color(const Ray3D &ray, size_t depth_left, const T &world) {

src/image.h

+16-4
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class Image {
3535
auto aspect_ratio() const {return static_cast<double>(w) / static_cast<double>(h);}
3636

3737
/* Prints this `Image` in PPM format to the file with name specified by `destination`. */
38-
void send_as_ppm(const std::string &destination) {
38+
void send_as_ppm(const std::string &destination) const {
3939
if (std::ofstream fout(destination); !fout.is_open()) {
4040
std::cout << "Error: In Image::print_as_ppm(), could not open the file \""
4141
<< destination << "\"" << std::endl;
@@ -55,6 +55,18 @@ class Image {
5555
}
5656
}
5757

58+
auto& outline_border() {
59+
for (size_t row = 0; row < h; ++row) {
60+
pixels[row][0] = pixels[row][w - 1] = RGB::from_mag(1);
61+
}
62+
63+
for (size_t col = 1; col < w - 1; ++col) {
64+
pixels[0][col] = pixels[h - 1][col] = RGB::from_mag(1);
65+
}
66+
67+
return *this;
68+
}
69+
5870
/* --- NAMED CONSTRUCTORS --- */
5971

6072
/* Creates an image with width `width` and height `height` */
@@ -90,7 +102,7 @@ class Image {
90102
/* Try to open the file `file_name` */
91103
std::ifstream fin(file_name);
92104
if (!fin.is_open()) {
93-
std::cout << "Error: In Image::from_ppm_file(), could not open the file \""
105+
std::cout << "Error: In Image::from_ppm_file(), could not find/open the file \""
94106
<< file_name << "\"" << std::endl;
95107
std::exit(-1);
96108
}
@@ -104,15 +116,15 @@ class Image {
104116
std::exit(-1);
105117
}
106118

107-
/* Input image width and image height (should be line 2) */
119+
/* Input image width and image height */
108120
size_t image_width, image_height;
109121
if (!(fin >> image_width >> image_height)) {
110122
std::cout << "Error: In Image::from_ppm_file(\"" << file_name << "\"), could not "
111123
"parse image width and height (two integers) on second line" << std::endl;
112124
std::exit(-1);
113125
}
114126

115-
/* Input maximum RGB magnitude (should be line 3) */
127+
/* Input maximum RGB magnitude */
116128
int max_magnitude;
117129
if (!(fin >> max_magnitude)) {
118130
std::cout << "Error: In Image::from_ppm_file(\"" << file_name << "\"), could not "

0 commit comments

Comments
 (0)