105 lines
3.3 KiB
Rust
105 lines
3.3 KiB
Rust
use crate::camera::Camera;
|
|
use crate::hittable::{Hittable, Sphere};
|
|
use crate::ray::Ray;
|
|
use crate::vec3::{Color, Point3, Vec3};
|
|
use rand::distributions::{Distribution, Uniform};
|
|
use crate::material::{Dielectric, Lambertian, Material, Metal};
|
|
|
|
mod vec3;
|
|
mod ray;
|
|
mod hittable;
|
|
mod material;
|
|
mod camera;
|
|
|
|
fn random_scene() -> Vec<Box<dyn Hittable>> {
|
|
let mut world:Vec<Box<dyn Hittable>> = Vec::new();
|
|
|
|
let material_ground = Material::Lambertian(Lambertian::new(Color::new(0.5, 0.5, 0.5)));
|
|
let ground = Sphere {
|
|
center: Point3::new(0.0, -1000.0, 0.0),
|
|
radius: 1000.0,
|
|
material: material_ground
|
|
};
|
|
world.push(Box::new(ground));
|
|
|
|
let unit_range = Uniform::from(0.0..1.0);
|
|
let fuzz_range = Uniform::from(0.0..0.5);
|
|
let mut rng = rand::thread_rng();
|
|
let p = Point3::new(4.0, 0.2, 0.0);
|
|
for a in -1..11 {
|
|
for b in -11..11 {
|
|
let choose_material = unit_range.sample(&mut rng);
|
|
let center = Point3::new(
|
|
(a as f64) + 0.9*unit_range.sample(&mut rng),
|
|
0.2,
|
|
(b as f64) + 0.9*unit_range.sample(&mut rng));
|
|
if (center - p).length() < 0.9 {
|
|
continue;
|
|
}
|
|
let material = match choose_material {
|
|
_ if choose_material < 0.8 => Material::Lambertian(Lambertian::new(
|
|
Color::random(0.0, 1.0) * Color::random(0.0, 1.0))),
|
|
_ if choose_material < 0.95 => Material::Metal(Metal::new(
|
|
Color::random(0.5, 1.0),
|
|
fuzz_range.sample(&mut rng))),
|
|
_ => Material::Dielectric(Dielectric::new(1.5)),
|
|
};
|
|
let sphere = Box::new(Sphere {
|
|
center,
|
|
radius: 0.2,
|
|
material
|
|
});
|
|
world.push(sphere);
|
|
}
|
|
}
|
|
world
|
|
}
|
|
|
|
fn main() {
|
|
// Image
|
|
const ASPECT_RATIO: f64 = 3.0 / 2.0;
|
|
const IMAGE_WIDTH: i32 = 1200;
|
|
const IMAGE_HEIGHT: i32 = (IMAGE_WIDTH as f64 / ASPECT_RATIO) as i32;
|
|
const SAMPLES_PER_PIXEL: i32 = 10;
|
|
const MAX_DEPTH: i32 = 50;
|
|
|
|
let look_from = Point3::new(13.0, 2.0, 3.0);
|
|
let look_at = Point3::new(0.0, 0.0, 0.0);
|
|
let focus_dist = 10.0;
|
|
// Camera
|
|
let cam = Camera::new(
|
|
look_from,
|
|
look_at,
|
|
Vec3::new(0.0, 1.0, 0.0),
|
|
ASPECT_RATIO,
|
|
20.0,
|
|
0.1,
|
|
focus_dist);
|
|
|
|
// World
|
|
let world= random_scene();
|
|
|
|
println!("P3\n{} {}\n255", IMAGE_WIDTH, IMAGE_HEIGHT);
|
|
|
|
let between = Uniform::from(0.0..1.0);
|
|
let mut rng = rand::thread_rng();
|
|
for j in (0..IMAGE_HEIGHT).rev() {
|
|
eprint!("\rScanlines remaining: {} ", j);
|
|
for i in 0..IMAGE_WIDTH {
|
|
let mut color = Color::default();
|
|
for s in 0..SAMPLES_PER_PIXEL {
|
|
let random_number = between.sample(&mut rng);
|
|
let u = (i as f64 + random_number) / (IMAGE_WIDTH - 1) as f64;
|
|
let v = (j as f64 + random_number) / (IMAGE_HEIGHT - 1) as f64;
|
|
let ray = cam.get_ray(u, v);
|
|
if i == 200 && (j == 112 || j == 113) {
|
|
let tt = 0;
|
|
}
|
|
color += ray.pixel_color(&world, MAX_DEPTH);
|
|
}
|
|
color.write_color(SAMPLES_PER_PIXEL);
|
|
}
|
|
}
|
|
eprintln!("\nDone");
|
|
}
|