-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcamera.h
More file actions
130 lines (102 loc) · 4.02 KB
/
camera.h
File metadata and controls
130 lines (102 loc) · 4.02 KB
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
#ifndef CAMERA_H
#define CAMERA_H
#include "rtweekend.h"
#include "material.h"
#include "hittable.h"
#include <fstream>
class camera {
public:
double aspect_ratio = 1.0;
int image_width = 100;
int samples_per_pixel = 10;
int max_depth = 10;
color background;
double vfov = 90;
point3 lookfrom = point3(0, 0, 0);
point3 lookat = point3(0, 0, -1);
vec3 vup = vec3(0, 1, 0);
double defocus_angle = 0;
double focus_dist = 10;
void render(const hittable& world) {
initialize();
std::ofstream outfile("image.ppm");
outfile << "P3\n" << image_width << ' ' << image_height << "\n255\n";
for (int j = 0; j < image_height; j++) {
std::clog << "\rScanlines remaining: " << (image_height - j) << ' ' << std::flush;
for (int i = 0; i < image_width; i++) {
color pixel_color(0, 0, 0);
for (int sample = 0; sample < samples_per_pixel; ++sample) {
ray r = get_ray(i, j);
pixel_color += ray_color(r, max_depth, world);
}
write_color(outfile, pixel_samples_scale * pixel_color);
}
}
std::clog << "\rDone. \n";
outfile.close();
}
private:
int image_height = 0;
double pixel_samples_scale = 0;
point3 center;
point3 pixel00_loc;
vec3 pixel_delta_u;
vec3 pixel_delta_v;
vec3 u, v, w;
vec3 defocus_disk_u;
vec3 defocus_disk_v;
void initialize() {
image_height = int(image_width / aspect_ratio);
image_height = (image_height < 1) ? 1 : image_height;
pixel_samples_scale = 1.0 / samples_per_pixel;
center = lookfrom;
auto theta = degrees_to_radians(vfov);
auto h = std::tan(theta / 2);
auto viewport_height = 2 * h * focus_dist;
auto viewport_width = viewport_height * (double(image_width) / image_height);
w = unit_vector(lookfrom - lookat);
u = unit_vector(cross(vup, w));
v = cross(w, u);
vec3 viewport_u = viewport_width * u;
vec3 viewport_v = viewport_height * -v;
pixel_delta_u = viewport_u / image_width;
pixel_delta_v = viewport_v / image_height;
auto viewport_upper_left = center - (focus_dist * w) - viewport_u / 2 - viewport_v / 2;
pixel00_loc = viewport_upper_left + 0.5 * (pixel_delta_u + pixel_delta_v);
auto defocus_radius = focus_dist * std::tan(degrees_to_radians(defocus_angle / 2));
defocus_disk_u = u * defocus_radius;
defocus_disk_v = v * defocus_radius;
}
ray get_ray(int i, int j) const {
auto offset = sample_square();
auto pixel_sample = pixel00_loc
+ ((i + offset.x()) * pixel_delta_u)
+ ((j + offset.y()) * pixel_delta_v);
auto ray_origin = (defocus_angle <= 0) ? center : defocus_disk_sample();
auto ray_direction = pixel_sample - ray_origin;
auto ray_time = random_double();
return ray(ray_origin, ray_direction, ray_time);
}
vec3 sample_square() const {
return vec3(random_double() - 0.5, random_double() - 0.5, 0);
}
point3 defocus_disk_sample() const {
auto p = random_in_unit_disk();
return center + (p[0] * defocus_disk_u) + (p[1] * defocus_disk_v);
}
color ray_color(const ray& r, int depth, const hittable& world) const {
if (depth <= 0)
return color(0, 0, 0);
hit_record rec;
if (!world.hit(r, interval(0.001, infinity), rec))
return background;
ray scattered;
color attenuation;
color color_from_emission = rec.mat->emitted(rec.u, rec.v, rec.p);
if (!rec.mat->scatter(r, rec, attenuation, scattered))
return color_from_emission;
color color_from_scatter = attenuation * ray_color(scattered, depth - 1, world);
return color_from_emission + color_from_scatter;
}
};
#endif