extern crate image; mod color; mod hittable; mod hittable_list; mod ray; mod vec3; mod utility; use std::env; use std::fs::File; use std::io::BufWriter; use std::io::Write; use vec3::{Color, Point3, Vec3}; use hittable::{Hittable, Sphere, HitRecord}; use hittable_list::HittableList; use ray::Ray; use image::{ImageBuffer, Rgb, RgbImage}; fn hit_sphere(center: &Point3, radius: f64, r: &Ray) -> f64 { let oc = r.origin() - *center; let a = r.direction().length_squared(); // gleiches Ergebnis wie Skalarprodukt let b = 2.0 * Vec3::dot(oc, r.direction()); let c = oc.length_squared() - 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, world: &HittableList) -> Color { let mut rec = HitRecord::empty(); if world.hit(r, 0.0, f64::INFINITY, &mut rec) { return 0.5 * (rec.normal + Color::new(1.0, 1.0, 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); } fn main() { // File let mut default_file = "image.ppm"; // Image let aspect_ratio = 16.0 / 9.0; let image_width = 1000; let image_height = (image_width as f64 / aspect_ratio) as u32; // World let mut world = HittableList::new(); world.add(Box::::new(Sphere::new(Point3::new(0.0, 0.0, -1.0), 0.5))); world.add(Box::::new(Sphere::new(Point3::new(0.0, -100.5, -1.0), 100.0))); // Camera let viewport_height = 2.0; let viewport_width = aspect_ratio * viewport_height; let focal_length = 1.0; 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 = env::args().collect(); if args.len() > 1 && args[1] != "" { default_file = &args[1]; } //let mut image = RgbImage::new(image_width, image_height); let mut file = BufWriter::new(File::create(default_file).unwrap()); writeln!(&mut file, "P3\n{image_width} {image_height}\n255\n").unwrap(); 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, &mut world); color::write_color(&mut file, &pixel_color); //color::put_color(&mut image, &pixel_color, image_width-i-1, image_height-j-1); } } //image.save(default_file).unwrap(); eprintln!("\nDone!"); }