/
main.cpp
135 lines (116 loc) · 4.56 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
#include "camera.h"
#include "color.h"
#include "hittable_list.h"
#include "rtweekend.h"
#include "sphere.h"
#include "material.h"
#include <iostream>
hittable_list random_scene(){
hittable_list world;
auto ground_material = make_shared<lambertian>(color(0.5, 0.5, 0.5));
world.add(make_shared<sphere>(point3(0,-1000,0), 1000, ground_material));
for (int a = -11; a < 11; a++){
for (int b = -11; b < 11; b++){
auto choose_mat = random_double();
point3 center(a + 0.9 * random_double(), 0.2, b + 0.9*random_double());
if ((center - point3(4, 0.2, 0)).length() > 0.9){
shared_ptr<material> sphere_material;
if (choose_mat < 0.8){
// difuse, little diffuse balls
auto albedo = color::random() * color::random();
sphere_material = make_shared<lambertian>(albedo);
world.add(make_shared<sphere>(center, 0.2, sphere_material));
} else if (choose_mat < 0.95){
// metal, little metal balls
auto albedo = color::random(0.5, 1);
auto fuzz = random_double(0, 0.5);
sphere_material = make_shared<metal>(albedo, fuzz);
world.add(make_shared<sphere>(center, 0.2, sphere_material));
} else {
// glass
sphere_material = make_shared<dielectric>(1.5);
world.add(make_shared<sphere>(center, 0.2, sphere_material));
}
}
}
}
auto material1 = make_shared<dielectric>(1.5);
world.add(make_shared<sphere>(point3(0, 1, 0), 1.0, material1));
auto material2 = make_shared<lambertian>(color(0.4, 0.2, 0.1));
world.add(make_shared<sphere>(point3(-4, 1, 0), 1.0, material2));
auto material3 = make_shared<metal>(color(0.7, 0.6, 0.5), 0.0);
world.add(make_shared<sphere>(point3(4, 1, 0), 1.0, material3));
return world;
}
// get the color of the ray
// this is the core of the ray tracing
color ray_color(const ray &r, const hittable &world, int depth) {
hit_record rec;
// return black if were at the depth limit
if (depth <= 0){
return color(0,0,0);
}
if (world.hit(r, 0.001, infinity, rec)) {
ray scattered;
color attenuation;
if (rec.mat_ptr->scatter(r, rec, attenuation, scattered))
return attenuation * ray_color(scattered, world, depth - 1);
return color (0,0,0);
}
vec3 unit_direction = unit_vector(r.direction());
auto opacity = 0.5;
auto t = (unit_direction.y() + 1.0) * opacity;
// blended value = (1-t) * startValue + t * endValue;
return (1.0 - t) * color(1.0, 1.0, 1.0) + t * color(0.5, 0.7, 1.0);
}
int main() {
// image
const auto aspect_ratio = 3.0/2.0;
const int image_width = 1200;
const int image_height = image_width / aspect_ratio;
const int samples_per_pixel = 100; // for AA
// be caureful this number basically makes the render X times longer, as it is per pixel,
// sample: 1, makes it really jagged
// sample: 10, image looks noisy, dark spots are present, depth makes it a bit less noisy
// sample: 50, image looks somewhat noisy but better than 10 (at 6 depth, but at depth 20 is perfect)
// sample: 100 image looks good enough, anything beyond is too much
const int max_depth = 50; // depth cant be too large as it could blow the stack (recursion)
// depth 1 makes everything black
// depth 2 allows for small shdows but no dielectric properties (refraction, reflection)
// depth 3 makes some reflection
// depth 6 makes good enough reflection
// depth 10 looks good
// depth 50 looks great? - havent test it much
// World
auto world = random_scene();
// Camera
point3 lookfrom(13,2,3);
point3 lookat(0,0,0);
vec3 vup(0,1,0);
auto dist_to_focus = 10.0;
auto aperture = 0.1;
// the bigger the number the more blurred
// aperture: 0, sharp asf
// aperture: 0.1, pretty sharp
// aperture: 2, kinda blurry
// aperture: 10, blurry af
// Old lf la, point3(-2,2,1), point3(0,0,-1), vec3(0,1,0)
camera cam(lookfrom, lookat, vup, 20.0, aspect_ratio, aperture, dist_to_focus);
std::cout << "P3\n" << image_width << " " << image_height << "\n255\n";
for (int j = image_height - 1; j >= 0; j--) {
std::cerr << "\rScanlines remaining: " << j << ' ' << std::flush;
for (int i = 0; i < image_width; i++) {
color pixel_color(0, 0, 0); // it starts as blac
// for clarity and antialiasing, "super sampling" every pixel
#pragma omp parallel for num_threads(4)
for (int s = 0; s < samples_per_pixel; ++s) {
auto u = (i + random_double()) / (image_width - 1);
auto v = (j + random_double()) / (image_height - 1);
ray r = cam.get_ray(u, v);
pixel_color += ray_color(r, world, max_depth);
}
write_color(std::cout, pixel_color, samples_per_pixel);
}
}
std::cerr << "\nDone.\n";
}