This commit is contained in:
2023-02-02 16:05:53 +01:00
parent 32cb8b4554
commit a28e2e98d1
3 changed files with 82 additions and 29 deletions

66
img.ppm

File diff suppressed because one or more lines are too long

View File

@@ -23,18 +23,18 @@ use crate::{
camera::*, material::{Lambertian, Dielectric},
};
fn ray_color(r: &Ray, world: &mut dyn Hittable, depth: i32) -> Color {
fn ray_color(r: Ray, world: &mut dyn Hittable, depth: i32) -> Color {
// Limit the bounces
if depth <= 0 {
return Color::new(0.0, 0.0, 0.0);
}
if let Some(rec) = world.hit(r, 0.001, INFINITY) {
if let Some(rec) = world.hit(&r, 0.001, INFINITY) {
let mut scattered = Ray::new_empty();
let mut attenuation = Color::new_empty();
if rec.mat_ptr.scatter(r, rec, &mut attenuation, &mut scattered) {
return attenuation * ray_color(&scattered, world, depth - 1);
return attenuation * ray_color(scattered, world, depth - 1);
}
return Color::new_empty();
}
@@ -50,7 +50,7 @@ fn main() {
let aspect_ratio: f64 = 1.0 / 1.0;
let image_width: i32 = 512;
let image_height: i32 = (image_width as f64 / aspect_ratio as f64) as i32;
let samples_per_pixel: i32 = 100;
let samples_per_pixel: i32 = 200;
let max_depth: i32 = 4;
// World
@@ -58,15 +58,15 @@ fn main() {
static MATERIAL_GROUND: Lambertian = Lambertian::new(Color::new(0.3, 0.8, 0.0));
static MATERIAL_CENTER: Lambertian = Lambertian::new(Color::new(0.1, 0.2, 0.5));
static MATERIAL_LEFT: Dielectric = Dielectric::new(1.5);
static MATERIAL_RIGHT: Metal = Metal::new(Color::new(0.8, 0.6, 0.2), 0.0);
static MATERIAL_RIGHT: Metal = Metal::new(Color::new(0.8, 0.6, 0.2), 0.3);
world.add(Box::new(Sphere::new(Point3::new(0.0, -100.5, -1.0), 100.0, &MATERIAL_GROUND)));
world.add(Box::new(Sphere::new(Point3::new(0.0, 0.0, -1.0), 0.5, &MATERIAL_CENTER)));
world.add(Box::new(Sphere::new(Point3::new(-1.0, 0.0, -1.0), -0.5, &MATERIAL_LEFT)));
world.add(Box::new(Sphere::new(Point3::new(-1.0, 0.0, -1.0), 0.5, &MATERIAL_LEFT)));
world.add(Box::new(Sphere::new(Point3::new(1.0, 0.0, -1.0), 0.5, &MATERIAL_RIGHT)));
// Camera
let cam = Camera::new(120.0, aspect_ratio);
let cam = Camera::new(90.0, aspect_ratio);
// Render
//let mut rng = rand::thread_rng();
@@ -83,7 +83,7 @@ fn main() {
let u = (i as f64 + random_f64()) / (image_width - 1) as f64;
let v = (j as f64 + random_f64()) / (image_height - 1) as f64;
let r: Ray = cam.get_ray(u, v);
pixel_color += ray_color(&r, &mut world, max_depth)
pixel_color += ray_color(r, &mut world, max_depth)
}
write_color_bin(&mut file, pixel_color, samples_per_pixel);
}

View File

@@ -3,8 +3,21 @@ use crate::ray::Ray;
use crate::rtweekend::random_f64;
use crate::vec3::{Color, random_unit_vector, reflect, refract};
pub trait Material: {
fn scatter(&self, r_in: &Ray, rec: HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool;
//More rusty
/*
pub struct ScatterData {
attenuation: Color,
scattered: Ray
}
pub trait Material {
fn scatter(&self, r_in: Ray, rec: HitRecord) -> Option<ScatterData>;
}
*/
pub trait Material {
fn scatter(&self, r_in: Ray, rec: HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool;
}
pub struct Lambertian {
@@ -18,7 +31,7 @@ impl Lambertian {
}
impl Material for Lambertian {
fn scatter(&self, _r_in: &Ray, rec: HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool {
fn scatter(&self, _r_in: Ray, rec: HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool {
let mut scatter_direction = rec.normal + random_unit_vector();
if scatter_direction.near_zero() {
@@ -43,7 +56,7 @@ impl Metal {
}
impl Material for Metal {
fn scatter(&self, r_in: &Ray, rec: HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool {
fn scatter(&self, r_in: Ray, rec: HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool {
let reflected = reflect(&r_in.direction(), &rec.normal);
*scattered = Ray::new(rec.p, reflected + self.fuzz*random_unit_vector());
*attenuation = self.albedo;
@@ -65,13 +78,13 @@ impl Dielectric {
// Schlick
let mut r0 = (1.0-ref_idx) / (1.0+ref_idx);
r0 = r0*r0;
r0 + (1.0-r0)*f64::powf(1.0 - cosine, 5.0)
return r0 + (1.0-r0)*f64::powf(1.0 - cosine, 5.0);
}
}
impl Material for Dielectric {
fn scatter(&self, r_in: &Ray, rec: HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool {
fn scatter(&self, r_in: Ray, rec: HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool {
*attenuation = Color::new(1.0, 1.0, 1.0);
let refraction_ratio: f64 = if rec.front_face {
1.0/self.ir
@@ -83,7 +96,7 @@ impl Material for Dielectric {
let cos_theta = f64::min(-unit_direction.dot(&rec.normal), 1.0);
let sin_theta = f64::sqrt(1.0 - cos_theta*cos_theta);
let cannot_refract = refraction_ratio * sin_theta > 1.0;
let cannot_refract = (refraction_ratio * sin_theta )> 1.0;
let direction = if cannot_refract || Dielectric::reflectance(self, cos_theta, refraction_ratio) > random_f64() {
reflect(&unit_direction, &rec.normal)