Skip to content

Commit

Permalink
Add some reflections and native color mixing
Browse files Browse the repository at this point in the history
  • Loading branch information
jstasiak committed Jul 10, 2019
1 parent d2ff35a commit c069f83
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 11 deletions.
Binary file modified output.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 35 additions & 8 deletions src/lib.rs
Expand Up @@ -185,6 +185,13 @@ impl Ray {
dir: self.dir,
}
}

pub fn reflected(&self, position: Vector, normal: &UnitVector) -> Ray {
Ray {
pos: position,
dir: self.dir.reflected(normal),
}
}
}

impl AlmostEqual for Ray {
Expand Down Expand Up @@ -336,7 +343,13 @@ pub fn posunit_to_unit(value: f32) -> f32 {

pub struct Radians(pub f32);

pub fn render(spheres: &[Sphere], camera: &Camera, width: usize, height: usize) -> Image {
pub fn render(
spheres: &[Sphere],
camera: &Camera,
width: usize,
height: usize,
bounces: usize,
) -> Image {
let mut image = Image::new(width, height);
for i in 0..width {
for j in 0..height {
Expand All @@ -345,19 +358,33 @@ pub fn render(spheres: &[Sphere], camera: &Camera, width: usize, height: usize)
i as f32 / (width - 1) as f32,
j as f32 / (height - 1) as f32,
);
let color = match closest_intersection(&spheres, &ray) {
None => Color::new_black(),
Some(intersection) => {
let brightness = intersection.normal.0.dot(&-ray.dir.0);
intersection.sphere.color * brightness
}
};
let color = trace_ray(&spheres, &ray, bounces);
image.set_color(i, j, color);
}
}
image
}

pub fn trace_ray(spheres: &[Sphere], ray: &Ray, bounces: usize) -> Color {
match closest_intersection(&spheres, &ray) {
None => Color::new_black(),
Some(intersection) => {
let brightness = intersection.normal.0.dot(&-ray.dir.0);

let mut color = intersection.sphere.color;
if bounces > 0 {
color = color
+ trace_ray(
&spheres,
&ray.reflected(intersection.position, &intersection.normal),
bounces - 1,
);
}
color * brightness
}
}
}

pub fn closest_intersection<'a>(spheres: &'a [Sphere], ray: &Ray) -> Option<Intersection<'a>> {
let mut closest_hit = None;
let mut closest_hit_distance = f32::MAX;
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Expand Up @@ -56,6 +56,6 @@ fn main() {
aspect_ratio: 4.0 / 3.0,
fovx: Radians(90.0f32.to_radians()),
};
let image = render(&spheres, &camera, 800, 600);
let image = render(&spheres, &camera, 800, 600, 3);
image_to_file(&image, &mut file);
}
49 changes: 47 additions & 2 deletions tests/lib.rs
@@ -1,6 +1,6 @@
use raytracer::{
closest_intersection, image_to_file, AlmostEqual, Camera, Color, Image, Intersection, Radians,
Ray, Sphere, UnitVector, Vector,
closest_intersection, image_to_file, trace_ray, AlmostEqual, Camera, Color, Image,
Intersection, Radians, Ray, Sphere, UnitVector, Vector,
};
use std::str;

Expand Down Expand Up @@ -450,3 +450,48 @@ fn test_color_addition() {
);
assert_almost_eq!(Color::new_red() + Color::new_red(), Color::new_red());
}

#[test]
fn test_trace_ray() {
let spheres = [
Sphere {
center: Vector {
x: 2.0,
y: 1.0,
z: 1.0,
},
radius: 1.0,
color: Color::new_red(),
},
Sphere {
center: Vector {
x: 4.0,
y: 4.0,
z: 1.0,
},
radius: 1.0,
color: Color::new_green(),
},
];
let ray = Ray {
pos: Vector {
x: 1.0,
y: 3.0,
z: 1.0,
},
dir: Vector {
x: 1.0,
y: -1.0,
z: 0.0,
}
.normalized(),
};
assert_almost_eq!(
trace_ray(&spheres, &ray, 0),
45.0f32.to_radians().cos() * Color::new_red(),
);
assert_almost_eq!(
trace_ray(&spheres, &ray, 1),
45.0f32.to_radians().cos() * (Color::new_red() + Color::new_green()),
);
}

0 comments on commit c069f83

Please sign in to comment.