-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.cpp
145 lines (123 loc) · 3.85 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <fstream>
#include <glm/glm.hpp>
#include <iostream>
#include <omp.h>
#include <toml.hpp>
#include "Hittable.hpp"
#include "constants.hpp"
#include "types.hpp"
#include "Camera.hpp"
#include "Image.hpp"
#include "Material.hpp"
#include "Ray.hpp"
#include "TOMLLoader.hpp"
#include "Util.hpp"
__host__ __device__ bool find_closest_hit(const scene *world, ray &r, num t_min,
num t_max, hit_record &hitrec) {
// Allocate thread-local stack
using node_ptr = hittable *;
node_ptr stack[32];
node_ptr *stack_ptr = stack;
// Initialize stack
*stack_ptr++ = NULL;
// Initialize local variables
hit_record temp_hitrec;
num closest_seen = t_max;
bool has_hit = false;
// Traverse tree starting from the root
node_ptr node = world->hittables;
do {
if (node->hit(r, t_min, closest_seen, temp_hitrec)) {
// node was hit, test for leaf
if (node->id != hittable_id::BoundingArrayNode) {
// node is a leaf
if (temp_hitrec.t < closest_seen) {
closest_seen = temp_hitrec.t;
hitrec = temp_hitrec;
}
has_hit = true;
} else {
// node is not a leaf, push left and right children onto stack.
*stack_ptr++ = world->hittables + node->as_bounding_array_node().left;
*stack_ptr++ = world->hittables + node->as_bounding_array_node().right;
}
}
// pop node off stack
node = *--stack_ptr;
} while (node != NULL);
return has_hit;
}
color trace_ray(RandomState *state, ray r, color background_color,
const scene *world, int depth) {
hit_record rec;
color attenuation;
color result_color(1, 1, 1);
while (depth > 0) {
// Test bvh for a hit
if (find_closest_hit(world, r, 0.0001f, infinity, rec)) {
if (world->materials[rec.mat_idx].scatter((RandomState *)state, r, rec,
attenuation, r)) {
result_color *= attenuation;
} else {
result_color *= world->materials[rec.mat_idx].emit();
break;
}
} else {
result_color *= background_color;
break;
}
--depth;
}
return result_color;
}
int main(int argc, char *argv[]) {
string filename{"scene.toml"};
string output{"image.ppm"};
if (argc > 1) {
filename = argv[1];
}
if (argc > 2) {
output = argv[2];
}
std::cerr << "Command: " << argv[0] << ' ' << filename << ' ' << output
<< '\n';
const auto scene_data = toml::parse(filename);
// Image
auto [samples_per_pixel, max_depth, image_width, image_height,
background_color] = loadParams(scene_data);
// World
scene world = loadScene(scene_data);
// Camera
camera cam = loadCamera(scene_data);
auto image = make_image<color>(image_width, image_height);
RandomStateCPU cpu_state;
RandomState *state = (RandomState *)&cpu_state;
auto start = omp_get_wtime();
// Rendering image
#pragma omp parallel for collapse(2) schedule(guided, 16)
for (int j = 0; j < image_height; ++j) {
for (int i = 0; i < image_width; ++i) {
color pixel_color(0.0, 0.0, 0.0);
for (int s = 0; s < samples_per_pixel; ++s) {
num u = (i + random_positive_unit(state)) / (image_width - 1);
num v = (j + random_positive_unit(state)) / (image_height - 1);
ray r = cam.get_ray(state, u, v);
pixel_color += trace_ray(state, r, background_color, &world, max_depth);
}
image(j, i) = pixel_color;
}
}
auto stop = omp_get_wtime();
std::cout << (stop - start) << std::endl;
std::ofstream ofs{output};
// Outputting Render Data
ofs << "P3\n";
ofs << image_width << " " << image_height << "\n";
ofs << 255 << "\n";
for (int j = image_height - 1; j >= 0; --j) {
for (int i = 0; i < image_width; ++i) {
auto pixel_color = image(j, i);
write_color(ofs, pixel_color, samples_per_pixel);
}
}
}