-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcamera.h
More file actions
140 lines (106 loc) · 5.04 KB
/
camera.h
File metadata and controls
140 lines (106 loc) · 5.04 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
131
132
133
134
135
136
137
138
139
140
#ifndef CAMERA_H
#define CAMERA_H
#include "rtweekend.h"
#include "color.h"
#include "hittable.h"
#include "material.h"
#include <iostream>
class camera {
public:
double aspect_ratio = 1.0; // Ratio of image width over height
int image_width = 100; // Rendered image width in pixel count
int max_depth = 10; // Maximum number of ray bounces into scene
double vfov = 90; // Vertical view angle (field of view)
point3 lookfrom = point3(0,0,0); // Point camera is looking from
point3 lookat = point3(0,0,-1); // Point camera is looking at
vec3 vup = vec3(0,1,0); // Camera-relative "up" direction
double defocus_angle = 0; // Variation angle of rays through each pixel
double focus_dist = 10; // Distance from camera lookfrom point to plane of perfect focus
int samples_per_pixel = 10; // Count of random samples for each pixel
void render(const hittable& world) {
initialize();
std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n";
for (int j = 0; j < image_height; ++j) {
std::clog << "Scanlines remaining: " << (image_height - j) << "\n";
for (int i = 0; i < image_width; ++i) {
color pixel_color(0,0,0);
for (int sample = 0; sample < samples_per_pixel; sample++){
// auto offset = sample_square();
auto offset = vec3(0,0,0);
auto pixel_center = 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_center - ray_origin;
ray r(ray_origin, ray_direction);
pixel_color += ray_color(r, max_depth, world);
}
write_color(std::cout, pixel_color / samples_per_pixel);
}
}
std::clog << "Done. \n";
}
private:
int image_height; // Rendered image height
point3 center; // Camera center
point3 pixel00_loc; // Location of pixel 0, 0
vec3 pixel_delta_u; // Offset to pixel to the right
vec3 pixel_delta_v; // Offset to pixel below
vec3 u, v, w; // Camera frame basis vectors
vec3 defocus_disk_u; // Defocus disk horizontal radius
vec3 defocus_disk_v; // Defocus disk vertical radius
void initialize() {
image_height = static_cast<int>(image_width / aspect_ratio);
image_height = (image_height < 1) ? 1 : image_height;
center = lookfrom;
// Determine viewport dimensions.
auto theta = degrees_to_radians(vfov);
auto h = tan(theta/2);
auto viewport_height = 2 * h * focus_dist;
auto viewport_width = viewport_height * (static_cast<double>(image_width)/image_height);
// Calculate the u,v,w unit basis vectors for the camera coordinate frame.
w = unit_vector(lookfrom - lookat);
u = unit_vector(cross(vup, w));
v = cross(w, u);
// Calculate the vectors across the horizontal and down the vertical viewport edges.
auto viewport_u = viewport_width * u;
auto viewport_v = viewport_height * -v;
// Calculate the horizontal and vertical delta vectors from pixel to pixel.
pixel_delta_u = viewport_u / image_width;
pixel_delta_v = viewport_v / image_height;
// Calculate the location of the upper left pixel.
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);
// Calculate the camera defocus disk basis vectors.
auto defocus_radius = focus_dist * tan(degrees_to_radians(defocus_angle / 2));
defocus_disk_u = u * defocus_radius;
defocus_disk_v = v * defocus_radius;
}
point3 defocus_disk_sample() const {
// Returns a random point in the camera defocus disk.
auto p = random_in_unit_disk();
return center + (p[0] * defocus_disk_u) + (p[1] * defocus_disk_v);
}
vec3 sample_square() const {
// Returns the vector to a random point in the [-.5,-.5]-[+.5,+.5] unit square.
return vec3(random_double() - 0.5, random_double() - 0.5, 0);
}
color ray_color(const ray& r, int depth, const hittable& world) const {
hit_record rec;
if(depth == 0){
return color(0,0,0);
}
if (world.hit(r, interval(0.000001, infinity), rec)) {
ray scattered;
color attenuation;
if(rec.mat->scatter(r, rec, attenuation, scattered)) {
return attenuation * ray_color(scattered, depth - 1, world);
} else {
return color(0, 0, 0);
}
}
vec3 unit_direction = unit_vector(r.direction());
auto a = 0.5*(unit_direction.y() + 1.0);
return (1.0-a)*color(1.0, 1.0, 1.0) + a*color(0.5, 0.7, 1.0);
}
};
#endif