58 lines
1.7 KiB
Rust
58 lines
1.7 KiB
Rust
use anyhow::Result;
|
|
|
|
use rtchallenge::{
|
|
canvas::Canvas,
|
|
lights::PointLight,
|
|
materials::{lighting, Material},
|
|
rays::Ray,
|
|
shapes::{intersect, Shape},
|
|
tuples::{Color, Tuple},
|
|
Float, WHITE,
|
|
};
|
|
|
|
fn main() -> Result<()> {
|
|
let w = 640;
|
|
let h = w;
|
|
let bg = Color::new(0.2, 0.2, 0.2);
|
|
let mut c = Canvas::new(w, h, bg);
|
|
let ray_origin = Tuple::point(0., 0., -5.);
|
|
let wall_z = 10.;
|
|
let wall_size = 7.;
|
|
let pixel_size = wall_size / w as Float;
|
|
let half = wall_size / 2.;
|
|
let mut shape = Shape::sphere();
|
|
shape.material = Material {
|
|
color: Color::new(1., 0.2, 1.).into(),
|
|
specular: 0.5,
|
|
diffuse: 0.7,
|
|
shininess: 30.,
|
|
..Material::default()
|
|
};
|
|
let light_position = Tuple::point(-10., 10., -10.);
|
|
let light_color = WHITE;
|
|
let light = PointLight::new(light_position, light_color);
|
|
let in_shadow = false;
|
|
for y in 0..h {
|
|
let world_y = half - pixel_size * y as Float;
|
|
for x in 0..w {
|
|
let world_x = -half + pixel_size * x as Float;
|
|
let position = Tuple::point(world_x, world_y, wall_z);
|
|
let direction = (position - ray_origin).normalize();
|
|
let r = Ray::new(ray_origin, direction);
|
|
let xs = intersect(&shape, &r);
|
|
if let Some(hit) = xs.hit() {
|
|
let point = r.position(hit.t);
|
|
let normal = hit.object.normal_at(point);
|
|
let eye = -r.direction;
|
|
let color = lighting(&hit.object.material, &light, point, eye, normal, in_shadow);
|
|
c.set(x, y, color);
|
|
}
|
|
}
|
|
}
|
|
|
|
let path = "/tmp/eoc6.png";
|
|
println!("saving output to {}", path);
|
|
c.write_to_file(path)?;
|
|
Ok(())
|
|
}
|