More spheres, formatting
This commit is contained in:
parent
398b9c1c29
commit
745fafeaad
6 changed files with 133 additions and 124 deletions
|
@ -9,22 +9,21 @@ pub struct Camera {
|
||||||
v: Vec3,
|
v: Vec3,
|
||||||
w: Vec3,
|
w: Vec3,
|
||||||
lens_radius: f64,
|
lens_radius: f64,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Camera {
|
impl Camera {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
lookfrom: Point3,
|
lookfrom: Point3,
|
||||||
lookat: Point3,
|
lookat: Point3,
|
||||||
vup: Vec3,
|
vup: Vec3,
|
||||||
vfov: f64, // vertical field of view in degrees
|
vfov: f64, // vertical field of view in degrees
|
||||||
aspect_ratio: f64,
|
aspect_ratio: f64,
|
||||||
aperture: f64,
|
aperture: f64,
|
||||||
focus_dist: f64,
|
focus_dist: f64,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let theta = vfov.to_radians();
|
let theta = vfov.to_radians();
|
||||||
let h = (theta/2.0).tan();
|
let h = (theta / 2.0).tan();
|
||||||
let viewport_height = 2.0*h;
|
let viewport_height = 2.0 * h;
|
||||||
let viewport_width = aspect_ratio * viewport_height;
|
let viewport_width = aspect_ratio * viewport_height;
|
||||||
|
|
||||||
let w = Vec3::unit_vector(lookfrom - lookat);
|
let w = Vec3::unit_vector(lookfrom - lookat);
|
||||||
|
@ -34,9 +33,9 @@ impl Camera {
|
||||||
let origin = lookfrom;
|
let origin = lookfrom;
|
||||||
let horizontal = focus_dist * viewport_width * u;
|
let horizontal = focus_dist * viewport_width * u;
|
||||||
let vertical = focus_dist * viewport_height * v;
|
let vertical = focus_dist * viewport_height * v;
|
||||||
let lower_left_corner = origin - horizontal/2.0 - vertical/2.0 - focus_dist*w;
|
let lower_left_corner = origin - horizontal / 2.0 - vertical / 2.0 - focus_dist * w;
|
||||||
|
|
||||||
let lens_radius = aperture / 2.0;
|
let lens_radius = aperture / 2.0;
|
||||||
|
|
||||||
return Camera {
|
return Camera {
|
||||||
origin,
|
origin,
|
||||||
|
@ -51,13 +50,12 @@ impl Camera {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ray(&self, u: f64, v: f64) -> Ray {
|
pub fn get_ray(&self, u: f64, v: f64) -> Ray {
|
||||||
|
|
||||||
let rd = self.lens_radius * Vec3::random_in_unit_disk();
|
let rd = self.lens_radius * Vec3::random_in_unit_disk();
|
||||||
let offset = rd.x() * self.u + rd.y() * self.v;
|
let offset = rd.x() * self.u + rd.y() * self.v;
|
||||||
|
|
||||||
return Ray::new(
|
return Ray::new(
|
||||||
self.origin + offset,
|
self.origin + offset,
|
||||||
self.lower_left_corner + u * self.horizontal + v * self.vertical - self.origin - offset,
|
self.lower_left_corner + u * self.horizontal + v * self.vertical - self.origin - offset,
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,4 @@
|
||||||
use super::{
|
use super::{Arc, Color, Material, Metal, Point3, Ray, Vec3};
|
||||||
Point3,
|
|
||||||
Vec3,
|
|
||||||
Color,
|
|
||||||
Ray,
|
|
||||||
Material,
|
|
||||||
Arc,
|
|
||||||
Metal
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct HitRecord {
|
pub struct HitRecord {
|
||||||
pub p: Point3,
|
pub p: Point3,
|
||||||
|
|
126
src/main.rs
126
src/main.rs
|
@ -4,22 +4,22 @@ mod camera;
|
||||||
mod color;
|
mod color;
|
||||||
mod hittable;
|
mod hittable;
|
||||||
mod hittable_list;
|
mod hittable_list;
|
||||||
|
mod material;
|
||||||
mod ray;
|
mod ray;
|
||||||
mod utility;
|
mod utility;
|
||||||
mod vec3;
|
mod vec3;
|
||||||
mod material;
|
|
||||||
|
|
||||||
use camera::Camera;
|
use camera::Camera;
|
||||||
use hittable::{HitRecord, Hittable, Sphere};
|
use hittable::{HitRecord, Hittable, Sphere};
|
||||||
use hittable_list::HittableList;
|
use hittable_list::HittableList;
|
||||||
use image::{Rgb, RgbImage};
|
use image::{Rgb, RgbImage};
|
||||||
|
use material::{Dielectric, Lambertian, Material, Metal};
|
||||||
use ray::Ray;
|
use ray::Ray;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::sync::atomic::{AtomicU32, Ordering};
|
use std::sync::atomic::{AtomicU32, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use vec3::{Color, Point3, Vec3};
|
use vec3::{Color, Point3, Vec3};
|
||||||
use material::{Material, Lambertian, Metal, Dielectric};
|
|
||||||
|
|
||||||
fn ray_color(r: &Ray, world: &HittableList, depth: u32) -> Color {
|
fn ray_color(r: &Ray, world: &HittableList, depth: u32) -> Color {
|
||||||
let mut rec = HitRecord::empty();
|
let mut rec = HitRecord::empty();
|
||||||
|
@ -31,11 +31,14 @@ fn ray_color(r: &Ray, world: &HittableList, depth: u32) -> Color {
|
||||||
if world.hit(r, 0.001, f64::INFINITY, &mut rec) {
|
if world.hit(r, 0.001, f64::INFINITY, &mut rec) {
|
||||||
let mut scattered = Ray::new(Point3::null(), Vec3::null());
|
let mut scattered = Ray::new(Point3::null(), Vec3::null());
|
||||||
let mut attenuation = Color::null();
|
let mut attenuation = Color::null();
|
||||||
if rec.mat_ptr.scatter(r, &rec, &mut attenuation, &mut scattered) {
|
if rec
|
||||||
return attenuation * ray_color(&scattered, world, depth-1);
|
.mat_ptr
|
||||||
|
.scatter(r, &rec, &mut attenuation, &mut scattered)
|
||||||
|
{
|
||||||
|
return attenuation * ray_color(&scattered, world, depth - 1);
|
||||||
}
|
}
|
||||||
return Color::null();
|
return Color::null();
|
||||||
|
|
||||||
//let target = rec.p + rec.normal + Vec3::random_unit_vector(); // rec.p + rec.normal.random_in_hemisphere();
|
//let target = rec.p + rec.normal + Vec3::random_unit_vector(); // rec.p + rec.normal.random_in_hemisphere();
|
||||||
//return 0.5 * ray_color(&Ray::new(rec.p, target - rec.p), world, depth - 1);
|
//return 0.5 * ray_color(&Ray::new(rec.p, target - rec.p), world, depth - 1);
|
||||||
}
|
}
|
||||||
|
@ -47,62 +50,63 @@ fn ray_color(r: &Ray, world: &HittableList, depth: u32) -> Color {
|
||||||
fn random_world() -> HittableList {
|
fn random_world() -> HittableList {
|
||||||
let mut world = HittableList::new();
|
let mut world = HittableList::new();
|
||||||
|
|
||||||
let material_ground = Arc::new(Lambertian::new(&Color::new(0.1, 0.1, 0.1)));
|
let material_ground = Arc::new(Lambertian::new(&Color::new(0.01, 0.01, 0.01)));
|
||||||
|
|
||||||
//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), 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));
|
|
||||||
//let material_light = Arc::new(Lambertian::new(&Color::new(2.0, 1.0, 0.0)));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
world.add(Box::<Sphere>::new(Sphere::new(
|
world.add(Box::<Sphere>::new(Sphere::new(
|
||||||
Point3::new(0.0, -1000.0, 0.0),
|
Point3::new(0.0, -50000.0, 0.0),
|
||||||
1000.0,
|
50000.0,
|
||||||
material_ground.clone(),
|
material_ground.clone(),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
(-6..5).into_iter().for_each(|a| {
|
(-6..5).into_iter().for_each(|a| {
|
||||||
(-6..5).into_iter().for_each(|b| {
|
(-6..5).into_iter().for_each(|b| {
|
||||||
let choose_mat = utility::random_f64();
|
let choose_mat = utility::random_f64();
|
||||||
let center = Point3::new(a as f64 + 0.9 * utility::random_f64(), 0.2, b as f64 + 0.9 * utility::random_f64());
|
let center = Point3::new(
|
||||||
|
1.5 * a as f64 + 1.3 * utility::random_f64(),
|
||||||
|
0.2,
|
||||||
|
1.5 * b as f64 + 1.3 * utility::random_f64(),
|
||||||
|
);
|
||||||
if (center - Point3::new(4.0, 0.2, 0.0)).length() > 0.9 {
|
if (center - Point3::new(4.0, 0.2, 0.0)).length() > 0.9 {
|
||||||
if choose_mat < 0.8 { // diffuse
|
if choose_mat < 0.8 {
|
||||||
let sphere_material = Arc::new(Lambertian::new(&(Color::random_f64() * Color::random_f64())));
|
// diffuse
|
||||||
|
let sphere_material = Arc::new(Lambertian::new(
|
||||||
|
&(Color::random_f64() * Color::random_f64()),
|
||||||
|
));
|
||||||
world.add(Box::<Sphere>::new(Sphere::new(
|
world.add(Box::<Sphere>::new(Sphere::new(
|
||||||
center,
|
center,
|
||||||
0.2,
|
0.2,
|
||||||
sphere_material.clone()
|
sphere_material.clone(),
|
||||||
)));
|
)));
|
||||||
} else if choose_mat < 0.95 { // metal
|
} else if choose_mat < 0.95 {
|
||||||
let sphere_material = Arc::new(Metal::new(&Color::random_rng(0.5, 1.0), utility::random_rng(0.0, 0.5)));
|
// metal
|
||||||
|
let sphere_material = Arc::new(Metal::new(
|
||||||
|
&Color::random_rng(0.5, 1.0),
|
||||||
|
utility::random_rng(0.0, 0.5),
|
||||||
|
));
|
||||||
world.add(Box::<Sphere>::new(Sphere::new(
|
world.add(Box::<Sphere>::new(Sphere::new(
|
||||||
center,
|
center,
|
||||||
0.2,
|
0.2,
|
||||||
sphere_material.clone()
|
sphere_material.clone(),
|
||||||
)));
|
)));
|
||||||
} else { // glass
|
} else {
|
||||||
|
// glass
|
||||||
let sphere_material = Arc::new(Dielectric::new(1.5));
|
let sphere_material = Arc::new(Dielectric::new(1.5));
|
||||||
world.add(Box::<Sphere>::new(Sphere::new(
|
world.add(Box::<Sphere>::new(Sphere::new(
|
||||||
center,
|
center,
|
||||||
0.2,
|
0.2,
|
||||||
sphere_material.clone()
|
sphere_material.clone(),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let material1 = Arc::new(Dielectric::new(1.5));
|
let material1 = Arc::new(Dielectric::new(1.5));
|
||||||
let material3 = Arc::new(Metal::new(&Color::new(0.7, 0.6, 0.5), 0.0));
|
|
||||||
let material2 = Arc::new(Lambertian::new(&Color::new(0.4, 0.2, 0.1)));
|
let material2 = Arc::new(Lambertian::new(&Color::new(0.4, 0.2, 0.1)));
|
||||||
|
let material3 = Arc::new(Metal::new(&Color::new(0.7, 0.6, 0.5), 0.0));
|
||||||
|
let material4 = Arc::new(Dielectric::new(2.0));
|
||||||
|
let material5 = Arc::new(Metal::new(&Color::new(0.9, 0.9, 0.7), 0.0));
|
||||||
|
|
||||||
world.add(Box::<Sphere>::new(Sphere::new(
|
world.add(Box::<Sphere>::new(Sphere::new(
|
||||||
Point3::new(0.0, 1.0, 0.0),
|
Point3::new(0.0, 1.0, 0.0),
|
||||||
1.0,
|
1.0,
|
||||||
|
@ -121,41 +125,17 @@ fn random_world() -> HittableList {
|
||||||
material3.clone(),
|
material3.clone(),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
/*
|
|
||||||
world.add(Box::<Sphere>::new(Sphere::new(
|
world.add(Box::<Sphere>::new(Sphere::new(
|
||||||
Point3::new(-2.0*r, 0.1, -2.0),
|
Point3::new(-2.0, 2.0, -5.0),
|
||||||
r,
|
2.0,
|
||||||
material_dielectric.clone(),
|
material4.clone(),
|
||||||
)));
|
)));
|
||||||
world.add(Box::<Sphere>::new(Sphere::new(
|
|
||||||
Point3::new(r, 0.0, -1.0),
|
|
||||||
r,
|
|
||||||
material_dielectric.clone(),
|
|
||||||
)));
|
|
||||||
world.add(Box::<Sphere>::new(Sphere::new(
|
|
||||||
Point3::new(-1.5, 1.3, -1.7),
|
|
||||||
0.4,
|
|
||||||
material_mirror.clone(),
|
|
||||||
)));
|
|
||||||
world.add(Box::<Sphere>::new(Sphere::new(
|
|
||||||
Point3::new(-0.5, 0.5, 1.0),
|
|
||||||
0.4,
|
|
||||||
material_blue.clone(),
|
|
||||||
)));
|
|
||||||
world.add(Box::<Sphere>::new(Sphere::new(
|
|
||||||
Point3::new(0.5, 1.0, 0.3),
|
|
||||||
0.3,
|
|
||||||
material_light.clone(),
|
|
||||||
)));
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
world.add(Box::<Sphere>::new(Sphere::new(
|
||||||
for i in -15..15 {
|
Point3::new(-3.6, 2.0, -2.0),
|
||||||
for j in -15..15 {
|
0.6,
|
||||||
world.add(Box::<Sphere>::new(Sphere::new(Point3::new(j as f64/5.0 as f64, i as f64/5.0 as f64, -1.5), 0.08)));
|
material5.clone(),
|
||||||
}
|
)));
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
|
@ -166,23 +146,31 @@ fn main() {
|
||||||
|
|
||||||
// Image
|
// Image
|
||||||
let aspect_ratio = 16.0 / 9.0;
|
let aspect_ratio = 16.0 / 9.0;
|
||||||
let image_width = 1920;
|
let image_width = 1000;
|
||||||
let image_height = (image_width as f64 / aspect_ratio) as u32;
|
let image_height = (image_width as f64 / aspect_ratio) as u32;
|
||||||
let samples_per_pixel = 100_u32;
|
let samples_per_pixel = 100_u32;
|
||||||
let max_depth = 50;
|
let max_depth = 50;
|
||||||
|
|
||||||
let vfov = 20.0;
|
let vfov = 25.0;
|
||||||
let lookfrom = Point3::new(10.0, 10.0, 13.0);
|
let lookfrom = Point3::new(10.0, 4.0, 13.0);
|
||||||
let lookat = Point3::new(0.0, 0.0, 0.0);
|
let lookat = Point3::new(0.0, 0.0, 0.0);
|
||||||
let vup = Vec3::new(0.0, 1.0, 0.0);
|
let vup = Vec3::new(0.0, 1.0, 0.0);
|
||||||
let dist_to_focus = 15.0;
|
let dist_to_focus = 17.0;
|
||||||
let aperture = 0.1;
|
let aperture = 0.1;
|
||||||
|
|
||||||
// World
|
// World
|
||||||
let world = random_world();
|
let world = random_world();
|
||||||
|
|
||||||
// Camera
|
// Camera
|
||||||
let cam = Camera::new(lookfrom, lookat, vup, vfov, aspect_ratio, aperture, dist_to_focus);
|
let cam = Camera::new(
|
||||||
|
lookfrom,
|
||||||
|
lookat,
|
||||||
|
vup,
|
||||||
|
vfov,
|
||||||
|
aspect_ratio,
|
||||||
|
aperture,
|
||||||
|
dist_to_focus,
|
||||||
|
);
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
|
|
|
@ -1,10 +1,4 @@
|
||||||
use super::{
|
use super::{utility, Color, HitRecord, Ray, Vec3};
|
||||||
Ray,
|
|
||||||
HitRecord,
|
|
||||||
Color,
|
|
||||||
Vec3,
|
|
||||||
utility,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct Lambertian {
|
pub struct Lambertian {
|
||||||
albedo: Color,
|
albedo: Color,
|
||||||
|
@ -23,27 +17,36 @@ pub struct Dielectric {
|
||||||
ir: f64,
|
ir: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub trait Material: Sync + Send {
|
pub trait Material: Sync + Send {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Lambertian {
|
impl Lambertian {
|
||||||
pub fn new(a: &Color) -> Self {
|
pub fn new(a: &Color) -> Self {
|
||||||
Lambertian {
|
Lambertian { albedo: a.clone() }
|
||||||
albedo: a.clone(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Material for 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 + Vec3::random_unit_vector();
|
let mut scatter_direction = rec.normal + Vec3::random_unit_vector();
|
||||||
|
|
||||||
if scatter_direction.near_zero() {
|
if scatter_direction.near_zero() {
|
||||||
scatter_direction = rec.normal;
|
scatter_direction = rec.normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
*scattered = Ray::new(rec.p, scatter_direction);
|
*scattered = Ray::new(rec.p, scatter_direction);
|
||||||
*attenuation = self.albedo.clone();
|
*attenuation = self.albedo.clone();
|
||||||
return true;
|
return true;
|
||||||
|
@ -60,10 +63,16 @@ impl Metal {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Material for 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 = Vec3::reflect(&Vec3::unit_vector(r_in.direction()), &rec.normal);
|
let reflected = Vec3::reflect(&Vec3::unit_vector(r_in.direction()), &rec.normal);
|
||||||
|
|
||||||
*scattered = Ray::new(rec.p, reflected + self.fuzz*Vec3::random_in_unit_sphere());
|
*scattered = Ray::new(rec.p, reflected + self.fuzz * Vec3::random_in_unit_sphere());
|
||||||
*attenuation = self.albedo.clone();
|
*attenuation = self.albedo.clone();
|
||||||
|
|
||||||
return Vec3::dot(scattered.direction(), rec.normal) > 0.0;
|
return Vec3::dot(scattered.direction(), rec.normal) > 0.0;
|
||||||
|
@ -72,22 +81,27 @@ impl Material for Metal {
|
||||||
|
|
||||||
impl Mirror {
|
impl Mirror {
|
||||||
pub fn new(a: &Color) -> Self {
|
pub fn new(a: &Color) -> Self {
|
||||||
Mirror {
|
Mirror { albedo: *a }
|
||||||
albedo: *a,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Material for Mirror {
|
impl Material for Mirror {
|
||||||
fn scatter(&self, r_in: &Ray, rec: &HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool {
|
fn scatter(
|
||||||
if utility::random_f64() > 0.8 { // Reflektiert
|
&self,
|
||||||
|
r_in: &Ray,
|
||||||
|
rec: &HitRecord,
|
||||||
|
attenuation: &mut Color,
|
||||||
|
scattered: &mut Ray,
|
||||||
|
) -> bool {
|
||||||
|
if utility::random_f64() > 0.8 {
|
||||||
|
// Reflektiert
|
||||||
let reflected = Vec3::reflect(&Vec3::unit_vector(r_in.direction()), &rec.normal);
|
let reflected = Vec3::reflect(&Vec3::unit_vector(r_in.direction()), &rec.normal);
|
||||||
*scattered = Ray::new(rec.p, reflected);
|
*scattered = Ray::new(rec.p, reflected);
|
||||||
*attenuation = self.albedo.clone();
|
*attenuation = self.albedo.clone();
|
||||||
|
|
||||||
return Vec3::dot(scattered.direction(), rec.normal) > 0.0;
|
return Vec3::dot(scattered.direction(), rec.normal) > 0.0;
|
||||||
|
} else {
|
||||||
} else { // Geht geradeaus durch
|
// Geht geradeaus durch
|
||||||
let reflected = r_in.direction().clone();
|
let reflected = r_in.direction().clone();
|
||||||
*scattered = Ray::new(rec.p, reflected);
|
*scattered = Ray::new(rec.p, reflected);
|
||||||
|
|
||||||
|
@ -106,27 +120,40 @@ impl Dielectric {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reflectance(cosine: f64, ref_idx: f64) -> f64 {
|
fn reflectance(cosine: f64, ref_idx: f64) -> f64 {
|
||||||
let r0 = ((1.0-ref_idx) / (1.0+ref_idx)).powi(2);
|
let r0 = ((1.0 - ref_idx) / (1.0 + ref_idx)).powi(2);
|
||||||
return r0 + (1.0-r0)*(1.0 - cosine).powi(5);
|
return r0 + (1.0 - r0) * (1.0 - cosine).powi(5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Material for Dielectric {
|
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);
|
*attenuation = Color::new(1.0, 1.0, 1.0);
|
||||||
let refraction_ratio = if rec.front_face { 1.0 / self.ir } else { self.ir };
|
let refraction_ratio = if rec.front_face {
|
||||||
|
1.0 / self.ir
|
||||||
|
} else {
|
||||||
|
self.ir
|
||||||
|
};
|
||||||
|
|
||||||
let unit_direction = Vec3::unit_vector(r_in.direction());
|
let unit_direction = Vec3::unit_vector(r_in.direction());
|
||||||
let cos_theta = Vec3::dot(-1.0 * unit_direction, rec.normal).min(1.0);
|
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 sin_theta = (1.0 - cos_theta * cos_theta).sqrt();
|
||||||
|
|
||||||
let mut direction = Vec3::refract(&unit_direction, &rec.normal, refraction_ratio); // can reflect
|
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
|
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);
|
direction = Vec3::reflect(&unit_direction, &rec.normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
*scattered = Ray::new(rec.p, direction);
|
*scattered = Ray::new(rec.p, direction);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,4 +22,4 @@ pub fn clamp(x: f64, min: f64, max: f64) -> f64 {
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
10
src/vec3.rs
10
src/vec3.rs
|
@ -47,7 +47,7 @@ impl Vec3 {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reflect(v: &Self, n: &Self) -> Self {
|
pub fn reflect(v: &Self, n: &Self) -> Self {
|
||||||
*v - 2.0*Self::dot(*v, *n) * *(n)
|
*v - 2.0 * Self::dot(*v, *n) * *(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn refract(uv: &Self, n: &Self, etai_over_etat: f64) -> Self {
|
pub fn refract(uv: &Self, n: &Self, etai_over_etat: f64) -> Self {
|
||||||
|
@ -90,7 +90,11 @@ impl Vec3 {
|
||||||
|
|
||||||
pub fn random_in_unit_disk() -> Self {
|
pub fn random_in_unit_disk() -> Self {
|
||||||
loop {
|
loop {
|
||||||
let p = Vec3::new(utility::random_rng(-1.0, 1.0), utility::random_rng(-1.0, 1.0), 0.0);
|
let p = Vec3::new(
|
||||||
|
utility::random_rng(-1.0, 1.0),
|
||||||
|
utility::random_rng(-1.0, 1.0),
|
||||||
|
0.0,
|
||||||
|
);
|
||||||
if p.length_squared() >= 1.0 {
|
if p.length_squared() >= 1.0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -166,7 +170,7 @@ impl Mul<Self> for Vec3 {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn mul(self, rhs: Self) -> Self {
|
fn mul(self, rhs: Self) -> Self {
|
||||||
Self::new(self.x()*rhs.x(), self.y()*rhs.y(), self.z()*rhs.z())
|
Self::new(self.x() * rhs.x(), self.y() * rhs.y(), self.z() * rhs.z())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue