2022-04-12 19:14:11 +02:00
|
|
|
mod vec3;
|
2022-04-20 18:58:58 +02:00
|
|
|
mod color;
|
|
|
|
mod ray;
|
2022-04-12 19:14:11 +02:00
|
|
|
use vec3::Vec3;
|
2022-04-20 18:58:58 +02:00
|
|
|
use vec3::Color;
|
|
|
|
use vec3::Point3;
|
|
|
|
use ray::Ray;
|
|
|
|
use std::env;
|
|
|
|
use std::fs::File;
|
|
|
|
use std::io::BufWriter;
|
|
|
|
use std::io::Write;
|
|
|
|
|
|
|
|
fn hit_sphere(center: &Point3, radius: f64, r: &Ray) -> f64 {
|
|
|
|
let oc = r.origin() - *center;
|
|
|
|
let a = Vec3::dot(r.direction(), r.direction());
|
|
|
|
let b = 2.0 * Vec3::dot(oc, r.direction());
|
|
|
|
let c = Vec3::dot(oc, oc) - radius*radius;
|
|
|
|
let discriminant = b*b - 4.0*a*c;
|
|
|
|
|
|
|
|
if discriminant < 0.0 {
|
|
|
|
return -1.0;
|
|
|
|
} else {
|
|
|
|
return (-b - discriminant.sqrt()) / (2.0*a);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn ray_color(r: &Ray) -> Color{
|
|
|
|
let t = hit_sphere(&Point3::new(0.0, 0.0, -1.0), 0.5, r);
|
|
|
|
if t > 0.0 {
|
|
|
|
let n = Vec3::unit_vector(r.at(t) - Vec3::new(0.0, 0.0, -1.0));
|
|
|
|
return 0.5*Color::new(n.x()+1.0, n.y()+1.0, n.z()+1.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
let unit_direction = r.direction();
|
|
|
|
let t = 0.5*(unit_direction.y() + 1.0);
|
|
|
|
return (1.0-t)*Color::new(1.0,1.0,1.0) + t*Color::new(0.5,0.7,1.0);
|
|
|
|
}
|
2022-04-12 19:14:11 +02:00
|
|
|
|
2022-04-07 23:04:50 +02:00
|
|
|
fn main() {
|
|
|
|
|
2022-04-20 18:58:58 +02:00
|
|
|
// File
|
|
|
|
let mut default_file = "image.ppm";
|
|
|
|
|
|
|
|
// Image
|
|
|
|
let aspect_ratio = 16.0 / 9.0;
|
|
|
|
let image_width = 800;
|
|
|
|
let image_height = (image_width as f64 / aspect_ratio) as u64;
|
|
|
|
|
|
|
|
// Camera
|
|
|
|
let viewport_height = 2.0;
|
|
|
|
let viewport_width = aspect_ratio * viewport_height;
|
|
|
|
let focal_length = 1.0;
|
2022-04-07 23:04:50 +02:00
|
|
|
|
2022-04-20 18:58:58 +02:00
|
|
|
let origin = Point3::new(0.0,0.0,0.0);
|
|
|
|
let horizontal = Vec3::new(viewport_width, 0.0, 0.0);
|
|
|
|
let vertical = Vec3::new(0.0, viewport_height, 0.0);
|
|
|
|
let lower_left_corner = origin - horizontal/2.0 - vertical/2.0 - Vec3::new(0.0, 0.0, focal_length);
|
|
|
|
|
|
|
|
// Render
|
|
|
|
let args: Vec<String> = env::args().collect();
|
|
|
|
if args.len() > 1 && args[1] != "" {
|
|
|
|
default_file = &args[1];
|
|
|
|
}
|
|
|
|
let mut file = BufWriter::new(File::create(default_file).unwrap());
|
|
|
|
writeln!(&mut file,"P3\n{image_width} {image_height}\n255\n").unwrap();
|
2022-04-07 23:04:50 +02:00
|
|
|
|
2022-04-20 18:58:58 +02:00
|
|
|
for j in (0..image_height).rev() {
|
|
|
|
eprint!("\rScanlines remaining: {j:5}");
|
|
|
|
for i in 0..image_width {
|
|
|
|
let u = i as f64 / (image_width-1) as f64;
|
|
|
|
let v = j as f64 / (image_height-1) as f64;
|
|
|
|
let r = Ray::new(origin, lower_left_corner + u*horizontal + v*vertical - origin);
|
|
|
|
let pixel_color = ray_color(&r);
|
2022-04-07 23:04:50 +02:00
|
|
|
|
2022-04-20 18:58:58 +02:00
|
|
|
color::write_color(&mut file, pixel_color);
|
2022-04-07 23:04:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
eprintln!("\nDone!");
|
2022-04-20 18:58:58 +02:00
|
|
|
}
|