-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCamera.h
More file actions
76 lines (66 loc) · 2.69 KB
/
Camera.h
File metadata and controls
76 lines (66 loc) · 2.69 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
#pragma once
#include <glm/glm.hpp>
#include <random>
#include "Ray.h"
/**
* @brief Configurable look-at camera for ray tracing with depth of field support
*/
class Camera {
private:
glm::vec3 origin;
glm::vec3 lower_left_corner;
glm::vec3 horizontal;
glm::vec3 vertical;
glm::vec3 u, v, w;
float lens_radius;
float focus_distance;
glm::vec3 random_in_unit_disk() const {
thread_local std::mt19937 gen(std::random_device{}());
thread_local std::uniform_real_distribution<float> dis(-1.0f, 1.0f);
while (true) {
glm::vec3 p = glm::vec3(dis(gen), dis(gen), 0.0f);
if (glm::dot(p, p) < 1.0f) return p;
}
}
public:
/**
* @brief Construct a configurable camera
* @param look_from Camera position (where the camera is)
* @param look_at Point the camera is looking at
* @param vup "Up" direction vector
* @param vfov Vertical field of view in degrees
* @param aspect_ratio Width / height ratio
* @param aperture Lens aperture diameter (0.0 = no blur, pinhole camera)
* @param focus_dist Distance to focus plane (set to distance to look_at point usually)
*/
Camera(const glm::vec3& look_from, const glm::vec3& look_at, const glm::vec3& vup,
float vfov, float aspect_ratio, float aperture = 0.0f, float focus_dist = 1.0f) {
float theta = glm::radians(vfov);
float h = glm::tan(theta / 2.0f);
float viewport_height = 2.0f * h;
float viewport_width = aspect_ratio * viewport_height;
w = glm::normalize(look_from - look_at);
u = glm::normalize(glm::cross(vup, w));
v = glm::cross(w, u);
lens_radius = aperture / 2.0f;
focus_distance = focus_dist;
origin = look_from;
horizontal = focus_distance * viewport_width * u;
vertical = focus_distance * viewport_height * v;
lower_left_corner = origin - horizontal / 2.0f - vertical / 2.0f - focus_distance * w;
}
/**
* @brief Generate a ray for the given normalized screen coordinates
* @param s Horizontal coordinate in [0, 1] (0 = left, 1 = right)
* @param t Vertical coordinate in [0, 1] (0 = bottom, 1 = top)
* @return Ray from camera through the (s, t) point on the image plane
*/
Ray get_ray(float s, float t) const {
glm::vec3 rd = lens_radius * random_in_unit_disk();
glm::vec3 offset = u * rd.x + v * rd.y;
glm::vec3 point = lower_left_corner + s * horizontal + t * vertical;
return Ray(origin + offset, point - origin - offset);
}
glm::vec3 get_origin() const { return origin; }
glm::vec3 get_forward() const { return -w; }
};