M src/main.rs => src/main.rs +11 -5
@@ 35,9 35,14 @@ fn hit_sphere(center: &Point3, radius: f64, r: &Ray) -> f64 {
}
}
-fn ray_color(r: &Ray, world: &dyn Hittable) -> Color {
- if let Some(rec) = world.hit(r, 0.0, INFINITY) {
- return 0.5 * (rec.normal + Color::new(1.0, 1.0, 1.0));
+fn ray_color(r: &Ray, world: &dyn Hittable, depth: isize) -> Color {
+ // If we've exceeded the ray bounce limit, no more light is gathered.
+ if depth <= 0 {
+ return Color::default();
+ }
+ if let Some(rec) = world.hit(r, 0.001, INFINITY) {
+ let target = rec.p + rec.normal + random_unit_vector();
+ return 0.5 * ray_color(&Ray::new(&rec.p, &(target - rec.p)), world, depth - 1);
}
let unit_direction = unit_vector(r.direction());
let t = 0.5 * (unit_direction.y() + 1.0);
@@ 51,9 56,10 @@ fn main() {
// Image
let aspect_ratio = 16.0 / 9.0;
let image_width = 400;
- // let image_width = 1600;
+ let image_width = 1600;
let image_height = (image_width as f64 / aspect_ratio) as i32;
let samples_per_pixel = 100;
+ let max_depth = 50;
// World
let mut world = HittableList::empty();
@@ 75,7 81,7 @@ fn main() {
let u = (i as f64 + random_double()) / (image_width - 1) as f64;
let v = (j as f64 + random_double()) / (image_height - 1) as f64;
let r = cam.get_ray(u, v);
- pixel_color += ray_color(&r, &world);
+ pixel_color += ray_color(&r, &world, max_depth);
}
write_color(&mut handle, pixel_color, samples_per_pixel);
}
M src/vec3.rs => src/vec3.rs +32 -3
@@ 1,3 1,6 @@
+use crate::{random_double, random_double_range};
+use std::ops::Range;
+
#[derive(Debug, Clone, Copy)]
pub struct Vec3 {
e: [f64; 3],
@@ 28,6 31,18 @@ impl Vec3 {
pub fn length_squared(&self) -> f64 {
self.e[0] * self.e[0] + self.e[1] * self.e[1] + self.e[2] * self.e[2]
}
+
+ pub fn random() -> Self {
+ Self::new(random_double(), random_double(), random_double())
+ }
+
+ pub fn random_range(r: Range<f64>) -> Self {
+ Self::new(
+ random_double_range(r.clone()),
+ random_double_range(r.clone()),
+ random_double_range(r.clone()),
+ )
+ }
}
impl std::ops::Neg for &Vec3 {
@@ 170,9 185,9 @@ pub fn write_color(out: &mut impl std::io::Write, pixel_color: Color, samples_pe
// Divide the color by the number of samples.
let scale = 1.0 / samples_per_pixel as f64;
- r *= scale;
- g *= scale;
- b *= scale;
+ r = (scale * r).sqrt();
+ g = (scale * g).sqrt();
+ b = (scale * b).sqrt();
write!(
out,
@@ 183,3 198,17 @@ pub fn write_color(out: &mut impl std::io::Write, pixel_color: Color, samples_pe
)
.unwrap();
}
+
+pub fn random_in_unit_sphere() -> Vec3 {
+ loop {
+ let p = Vec3::random_range(-1.0..1.0);
+ if p.length_squared() >= 1.0 {
+ continue;
+ }
+ return p;
+ }
+}
+
+pub fn random_unit_vector() -> Vec3 {
+ unit_vector(random_in_unit_sphere())
+}