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
|
use crate::calculus::calculus::{sample_square, Point3, Ray, Vec3};
use crate::global::{get_image_height, Color, DisplayBuffer, Pixel, ASPECT_RATIO, CAMERA_CENTER, FOCAL_LENGTH, IMG_WIDTH, SAMPLES_PER_PIXEL, VIEWPORT_HEIGHT};
use crate::interval::Interval;
use crate::object::{HitRecord, Hittable, HittableList};
pub struct Camera {
pub aspect_ratio: f32,
pub image_width: usize,
pub samples_per_pixel: usize,
image_height: usize,
center: Point3,
pixel_upper_left: Point3,
delta_pixel_u: Vec3,
delta_pixel_v: Vec3,
pixel_samples_scale: f32,
max_depth: usize,
}
impl Camera {
pub fn new() -> Self {
let aspect_ratio = ASPECT_RATIO;
let image_width = IMG_WIDTH;
let image_height = get_image_height(image_width, aspect_ratio);
let center = CAMERA_CENTER;
let focal_length = FOCAL_LENGTH;
let samples_per_pixel = SAMPLES_PER_PIXEL;
let pixel_samples_scale = 1.0 / samples_per_pixel as f32;
let viewport_height = VIEWPORT_HEIGHT;
let viewport_width = viewport_height * (image_width as f32 / image_height as f32);
let viewport_hor_vector = Vec3{ x: viewport_width, y: 0.0, z: 0.0 };
let viewport_ver_vector = Vec3 { x: 0.0, y: -1f32 * viewport_height, z: 0.0 };
let delta_pixel_u = viewport_hor_vector.scalar_mul(1.0 / image_width as f32);
let delta_pixel_v = viewport_ver_vector.scalar_mul(1.0 / image_height as f32);
let viewport_upper_left = center
.sub(&Vec3 { x: 0f32, y: 0f32, z: focal_length})
.sub(&viewport_hor_vector.scalar_mul(0.5))
.sub(&viewport_ver_vector.scalar_mul(0.5));
let pixel_upper_left = viewport_upper_left.add(
&delta_pixel_u.add(&delta_pixel_u).scalar_mul(0.5)
);
let max_depth = 50;
Self {
aspect_ratio,
image_width,
image_height,
center,
pixel_upper_left,
delta_pixel_u,
delta_pixel_v,
samples_per_pixel,
pixel_samples_scale,
max_depth
}
}
fn get_ray(&self, i: usize, j: usize) -> Ray {
let offset = sample_square();
let pixel_sample = self.pixel_upper_left
.add(&self.delta_pixel_u.scalar_mul(i as f32 + offset.x))
.add(&self.delta_pixel_v.scalar_mul(j as f32 + offset.y));
let ray_origin = self.center;
let ray_direction = pixel_sample.sub(&ray_origin);
Ray {
origin: ray_origin,
direction: ray_direction,
}
}
fn ray_color(&self, ray: &Ray, world: &HittableList, depth: usize) -> Color {
if depth <= 0 {
return Color::new(0.0, 0.0, 0.0);
}
let mut rec = HitRecord::default();
let ray_t = Interval::new(0.0, f32::INFINITY);
if world.hit(ray, ray_t, &mut rec) {
let direction = Vec3::random_on_hemisphere(&rec.normal);
let origin = rec.position.clone();
let r = Ray { origin, direction };
return self.ray_color(&r, world, depth - 1).mul_scalar(0.5);
}
let unit_direction = ray.direction.unit();
let a = 0.5 * (unit_direction.y + 1.0);
let color1 = Color::new(1.0, 1.0, 1.0).mul_scalar(1.0 - a);
let color2 = Color::new(0.5, 0.7, 1.0).mul_scalar(a);
color1.add(&color2)
}
pub fn render(&self, display_buffer: &mut DisplayBuffer, world: &HittableList) {
(0..self.image_height).for_each(|j| {
(0..self.image_width).for_each(|i| {
println!("Processing line {} col {}", j, i);
let mut pixel_color = Color::new(0.0, 0.0, 0.0);
(0..self.samples_per_pixel).for_each(|_| {
let r = self.get_ray(i, j);
let ray_color = self.ray_color(&r, world, self.max_depth);
pixel_color = pixel_color.add(&ray_color);
});
pixel_color = pixel_color.mul_scalar(self.pixel_samples_scale);
display_buffer[j][i] = Pixel::from_color(&pixel_color);
})
})
}
}
|