additional materials
This commit is contained in:
parent
d6e92fa2ba
commit
613bf68fb6
4 changed files with 64 additions and 15 deletions
|
@ -50,7 +50,7 @@ impl HitRecord {
|
|||
Self::new(
|
||||
Point3::null(),
|
||||
Vec3::null(),
|
||||
Arc::new(Metal::new(&Color::null())),
|
||||
Arc::new(Metal::new(&Color::null(), 0.0)),
|
||||
0.0,
|
||||
false,
|
||||
)
|
||||
|
|
27
src/main.rs
27
src/main.rs
|
@ -19,7 +19,7 @@ use std::env;
|
|||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
use std::sync::Arc;
|
||||
use vec3::{Color, Point3, Vec3};
|
||||
use material::{Material, Lambertian, Metal, Mirror};
|
||||
use material::{Material, Lambertian, Metal, Dielectric};
|
||||
|
||||
fn ray_color(r: &Ray, world: &HittableList, depth: u32) -> Color {
|
||||
let mut rec = HitRecord::empty();
|
||||
|
@ -50,7 +50,7 @@ fn main() {
|
|||
|
||||
// Image
|
||||
let aspect_ratio = 16.0 / 9.0;
|
||||
let image_width = 1000;
|
||||
let image_width = 1920;
|
||||
let image_height = (image_width as f64 / aspect_ratio) as u32;
|
||||
let samples_per_pixel = 100_u32;
|
||||
let max_depth = 50;
|
||||
|
@ -60,9 +60,12 @@ fn main() {
|
|||
|
||||
let material_ground = Arc::new(Lambertian::new(&Color::new(0.8, 0.8, 0.0)));
|
||||
let material_center = Arc::new(Lambertian::new(&Color::new(0.7, 0.1, 0.2)));
|
||||
//let material_center = Arc::new(Dielectric::new(1.5));
|
||||
let material_blue = Arc::new(Lambertian::new(&Color::new(0.2, 0.1, 0.7)));
|
||||
let material_metal = Arc::new(Metal::new(&Color::new(0.8, 0.8, 0.8)));
|
||||
let _material_mirror = Arc::new(Mirror::new(&Color::new(0.99, 0.99, 0.99)));
|
||||
let material_metal = Arc::new(Metal::new(&Color::new(0.8, 0.8, 0.8), 0.1));
|
||||
let material_metal_fuzz = Arc::new(Metal::new(&Color::new(0.8, 0.8, 0.8), 1.0));
|
||||
let material_mirror = Arc::new(Metal::new(&Color::new(0.8, 0.8, 0.8), 0.0));
|
||||
let material_dielectric = Arc::new(Dielectric::new(1.5));
|
||||
|
||||
|
||||
|
||||
|
@ -72,24 +75,24 @@ fn main() {
|
|||
material_ground.clone(),
|
||||
)));
|
||||
world.add(Box::<Sphere>::new(Sphere::new(
|
||||
Point3::new(0.0, -0.1, -1.0),
|
||||
0.4,
|
||||
Point3::new(0.0, 0.0, -1.0),
|
||||
0.5,
|
||||
material_center.clone(),
|
||||
)));
|
||||
world.add(Box::<Sphere>::new(Sphere::new(
|
||||
Point3::new(-1.0, 0.0, -1.0),
|
||||
Point3::new(-1.0, -0.15, -1.0),
|
||||
0.5,
|
||||
material_metal.clone(),
|
||||
material_dielectric.clone(),
|
||||
)));
|
||||
world.add(Box::<Sphere>::new(Sphere::new(
|
||||
Point3::new(1.3, 0.3, -1.5),
|
||||
0.8,
|
||||
material_metal.clone(),
|
||||
Point3::new(1.0, 0.0, -1.0),
|
||||
-0.4,
|
||||
material_dielectric.clone(),
|
||||
)));
|
||||
world.add(Box::<Sphere>::new(Sphere::new(
|
||||
Point3::new(-1.5, 1.3, -1.7),
|
||||
0.4,
|
||||
material_metal.clone(),
|
||||
material_mirror.clone(),
|
||||
)));
|
||||
world.add(Box::<Sphere>::new(Sphere::new(
|
||||
Point3::new(-0.5, 0.5, 1.0),
|
||||
|
|
|
@ -12,12 +12,17 @@ pub struct Lambertian {
|
|||
|
||||
pub struct Metal {
|
||||
albedo: Color,
|
||||
fuzz: f64,
|
||||
}
|
||||
|
||||
pub struct Mirror {
|
||||
albedo: Color,
|
||||
}
|
||||
|
||||
pub struct Dielectric {
|
||||
ir: f64,
|
||||
}
|
||||
|
||||
|
||||
pub trait Material: Sync + Send {
|
||||
fn scatter(&self,r_in: &Ray, rec: &HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool;
|
||||
|
@ -46,9 +51,10 @@ impl Material for Lambertian {
|
|||
}
|
||||
|
||||
impl Metal {
|
||||
pub fn new(a: &Color) -> Self {
|
||||
pub fn new(a: &Color, f: f64) -> Self {
|
||||
Metal {
|
||||
albedo: *a,
|
||||
fuzz: f,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +63,7 @@ impl Material for Metal {
|
|||
fn scatter(&self, r_in: &Ray, rec: &HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool {
|
||||
let reflected = Vec3::reflect(&Vec3::unit_vector(r_in.direction()), &rec.normal);
|
||||
|
||||
*scattered = Ray::new(rec.p, reflected);
|
||||
*scattered = Ray::new(rec.p, reflected + self.fuzz*Vec3::random_in_unit_sphere());
|
||||
*attenuation = self.albedo.clone();
|
||||
|
||||
return Vec3::dot(scattered.direction(), rec.normal) > 0.0;
|
||||
|
@ -91,3 +97,36 @@ impl Material for Mirror {
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl Dielectric {
|
||||
pub fn new(index_of_refraction: f64) -> Self {
|
||||
Dielectric {
|
||||
ir: index_of_refraction,
|
||||
}
|
||||
}
|
||||
|
||||
fn reflectance(cosine: f64, ref_idx: f64) -> f64 {
|
||||
let r0 = ((1.0-ref_idx) / (1.0+ref_idx)).powi(2);
|
||||
return r0 + (1.0-r0)*(1.0 - cosine).powi(5);
|
||||
}
|
||||
}
|
||||
|
||||
impl Material for Dielectric {
|
||||
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 = if rec.front_face { 1.0 / self.ir } else { self.ir };
|
||||
|
||||
let unit_direction = Vec3::unit_vector(r_in.direction());
|
||||
let cos_theta = Vec3::dot(-1.0 * unit_direction, rec.normal).min(1.0);
|
||||
let sin_theta = (1.0 - cos_theta*cos_theta).sqrt();
|
||||
|
||||
let mut direction = Vec3::refract(&unit_direction, &rec.normal, refraction_ratio); // can reflect
|
||||
|
||||
if refraction_ratio * sin_theta > 1.0 || Dielectric::reflectance(cos_theta, refraction_ratio) > utility::random_f64() { // must reflect
|
||||
direction = Vec3::reflect(&unit_direction, &rec.normal);
|
||||
}
|
||||
|
||||
*scattered = Ray::new(rec.p, direction);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -50,6 +50,13 @@ impl Vec3 {
|
|||
*v - 2.0*Self::dot(*v, *n) * *(n)
|
||||
}
|
||||
|
||||
pub fn refract(uv: &Self, n: &Self, etai_over_etat: f64) -> Self {
|
||||
let cos_theta = Self::dot(-1.0 * *uv, *n).min(1.0); // Minimum aus 1.0 und Punktprodukt
|
||||
let r_out_perp = etai_over_etat * (*uv + cos_theta * *n);
|
||||
let r_out_parallel = -(1.0 - r_out_perp.length_squared()).abs().sqrt() * *n;
|
||||
return r_out_perp + r_out_parallel;
|
||||
}
|
||||
|
||||
pub fn near_zero(&self) -> bool {
|
||||
let s = 1e-8;
|
||||
return (self.e[0].abs() < s) && (self.e[1].abs() < s) && (self.e[2].abs() < s);
|
||||
|
|
Loading…
Reference in a new issue