155 lines
4.1 KiB
Rust

extern crate image;
pub mod point;
pub mod rendering;
pub mod scene;
pub mod vector;
use image::GenericImage;
use image::Pixel;
use scene::Scene;
pub fn render(scene: &Scene) -> image::DynamicImage {
let mut image = image::DynamicImage::new_rgb8(scene.width, scene.height);
let black = image::Rgba::from_channels(0, 0, 0, 0);
for x in 0..scene.width {
for y in 0..scene.height {
let ray = rendering::Ray::create_prime(x, y, scene);
if let Some(intersection) = scene.trace(&ray) {
let hit_point = ray.origin + (&ray.direction * intersection.distance);
let surface_normal = intersection.object.surface_normal(&hit_point);
let direction_to_light = -scene.light.direction;
let c = &intersection.object.color();
image.put_pixel(x, y, image::Rgba(c.to_rgba()))
} else {
image.put_pixel(x, y, black);
}
}
}
image
}
#[test]
fn test_can_render_scene() {
use point::Point;
use rendering::Element;
use rendering::Plane;
use rendering::Sphere;
use scene::Color;
use scene::Light;
use vector::Vector3;
let scene = Scene {
width: 800,
height: 600,
fov: 90.0,
elements: vec![
Element::Plane(Plane {
origin: Point {
x: 0.0,
y: -2.0,
z: -5.0,
},
normal: Vector3 {
x: 0.0,
y: -1.0,
z: 0.0,
},
color: Color {
red: 0.2,
green: 0.2,
blue: 0.3,
},
}),
Element::Plane(Plane {
origin: Point {
x: 0.0,
y: 0.0,
z: -20.0,
},
normal: Vector3 {
x: 0.0,
y: 0.0,
z: -1.0,
},
color: Color {
red: 0.2,
green: 0.3,
blue: 1.0,
},
}),
Element::Sphere(Sphere {
center: Point {
x: 2.0,
y: 1.0,
z: -4.0,
},
radius: 1.5,
color: Color {
red: 1.0,
green: 0.2,
blue: 0.2,
},
}),
Element::Sphere(Sphere {
center: Point {
x: 0.0,
y: 0.0,
z: -5.0,
},
radius: 1.0,
color: Color {
red: 0.2,
green: 1.0,
blue: 0.2,
},
}),
Element::Sphere(Sphere {
center: Point {
x: -3.0,
y: 1.0,
z: -6.0,
},
radius: 2.0,
color: Color {
red: 0.2,
green: 0.2,
blue: 1.0,
},
}),
Element::Sphere(Sphere {
center: Point {
x: 2.0,
y: 1.0,
z: -10.0,
},
radius: 5.0,
color: Color {
red: 1.0,
green: 1.0,
blue: 1.0,
},
}),
],
light: Light {
direction: Vector3 {
x: 0.0,
y: 0.0,
z: -1.0,
},
color: Color {
red: 1.0,
green: 1.0,
blue: 1.0,
},
intensity: 0.0,
},
};
let img: image::DynamicImage = render(&scene);
assert_eq!(scene.width, img.width());
assert_eq!(scene.height, img.height());
img.save("/tmp/bheisler.png").unwrap();
}