Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1c3ea7a
commit 882db14
Showing
5 changed files
with
248 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
use glam::DVec3; | ||
use raytracer::{ | ||
camera::Camera, | ||
material::Material, | ||
shapes::{ | ||
constant_medium::ConstantMedium, quad::Quad, | ||
quad_box::QuadBox, Shapes, | ||
}, | ||
textures::Texture, | ||
}; | ||
use std::{io, path::Path}; | ||
|
||
fn main() -> io::Result<()> { | ||
let mut world = vec![]; | ||
|
||
// Materials | ||
let red = Material::Lambertian { | ||
albedo: DVec3::new(0.65, 0.05, 0.05).into(), | ||
}; | ||
let white = Material::Lambertian { | ||
albedo: DVec3::new(0.73, 0.73, 0.73).into(), | ||
}; | ||
let green = Material::Lambertian { | ||
albedo: DVec3::new(0.12, 0.45, 0.15).into(), | ||
}; | ||
let light = Material::DiffuseLight( | ||
DVec3::new(7., 7., 7.).into(), | ||
); | ||
|
||
world.push(Shapes::Quad(Quad::new( | ||
DVec3::new(555., 0., 0.), | ||
DVec3::new(0., 555., 0.), | ||
DVec3::new(0., 0., 555.), | ||
green, | ||
))); | ||
world.push(Shapes::Quad(Quad::new( | ||
DVec3::new(0., 0., 0.), | ||
DVec3::new(0., 555., 0.), | ||
DVec3::new(0., 0., 555.), | ||
red, | ||
))); | ||
world.push(Shapes::Quad(Quad::new( | ||
DVec3::new(113., 554., 127.), | ||
DVec3::new(330., 0., 0.), | ||
DVec3::new(0., 0., 305.), | ||
light, | ||
))); | ||
world.push(Shapes::Quad(Quad::new( | ||
DVec3::new(0., 555., 0.), | ||
DVec3::new(555., 0., 0.), | ||
DVec3::new(0., 0., 555.), | ||
white.clone(), | ||
))); | ||
world.push(Shapes::Quad(Quad::new( | ||
DVec3::new(0., 0., 0.), | ||
DVec3::new(555., 0., 0.), | ||
DVec3::new(0., 0., 555.), | ||
white.clone(), | ||
))); | ||
world.push(Shapes::Quad(Quad::new( | ||
DVec3::new(0., 0., 555.), | ||
DVec3::new(555., 0., 0.), | ||
DVec3::new(0., 555., 0.), | ||
white.clone(), | ||
))); | ||
|
||
let box1 = Shapes::Translate { | ||
offset: DVec3::new(265., 0., 295.), | ||
object: Box::new(Shapes::new_rotate_y( | ||
15., | ||
Shapes::QuadBox(QuadBox::new( | ||
DVec3::new(0., 0., 0.), | ||
DVec3::new(165., 330., 165.), | ||
white.clone(), | ||
)), | ||
)), | ||
}; | ||
let box2 = Shapes::Translate { | ||
offset: DVec3::new(130., 0., 65.), | ||
object: Box::new(Shapes::new_rotate_y( | ||
-18., | ||
Shapes::QuadBox(QuadBox::new( | ||
DVec3::new(0., 0., 0.), | ||
DVec3::new(165., 165., 165.), | ||
white, | ||
)), | ||
)), | ||
}; | ||
|
||
world.push(Shapes::ConstantMedium( | ||
ConstantMedium::new( | ||
box1, | ||
0.01, | ||
DVec3::new(0., 0., 0.).into(), | ||
), | ||
)); | ||
world.push(Shapes::ConstantMedium( | ||
ConstantMedium::new( | ||
box2, | ||
0.01, | ||
DVec3::new(1., 1., 1.).into(), | ||
), | ||
)); | ||
|
||
let camera = Camera::init() | ||
.image_width(800) | ||
.aspect_ratio(1.) | ||
.look_from(DVec3::new(278., 278., -800.)) | ||
.look_at(DVec3::new(278., 278., 0.)) | ||
.vup(DVec3::Y) | ||
.focus_dist(10.0) | ||
.defocus_angle(0.0) | ||
.samples_per_pixel(500) | ||
.max_depth(50) | ||
.vfov(40.) | ||
.background(DVec3::ZERO) | ||
.build(); | ||
|
||
let filename = Path::new(file!()) | ||
.file_name() | ||
.and_then(|s| s.to_str()) | ||
.unwrap() | ||
.trim_end_matches(".rs"); | ||
camera.render_to_disk(filename, world)?; | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
use crate::{ | ||
hittable::{HitRecord, Hittable}, | ||
material::Material, | ||
ray::Ray, | ||
textures::Texture, | ||
}; | ||
use glam::DVec3; | ||
use rand::prelude::*; | ||
use std::{f64::consts::PI, ops::Range}; | ||
|
||
use super::Shapes; | ||
|
||
pub struct ConstantMedium { | ||
boundary: Box<Shapes>, | ||
neg_inv_density: f64, | ||
phase_function: Material, | ||
} | ||
|
||
impl ConstantMedium { | ||
pub fn new( | ||
boundary: Shapes, | ||
density: f64, | ||
texture: Texture, | ||
) -> Self { | ||
Self { | ||
boundary: Box::new(boundary), | ||
neg_inv_density: -density.recip(), | ||
phase_function: Material::Isotropic { | ||
albedo: texture, | ||
}, | ||
} | ||
} | ||
} | ||
|
||
impl Hittable for ConstantMedium { | ||
fn hit( | ||
&self, | ||
ray: &Ray, | ||
interval: Range<f64>, | ||
) -> Option<HitRecord> { | ||
let mut rng = rand::thread_rng(); | ||
|
||
let Some(mut rec1) = self | ||
.boundary | ||
.hit(ray, f64::NEG_INFINITY..f64::INFINITY) | ||
else { | ||
return None; | ||
}; | ||
let Some(mut rec2) = self | ||
.boundary | ||
.hit(ray, (rec1.t + 0.0001)..f64::INFINITY) | ||
else { | ||
return None; | ||
}; | ||
|
||
if rec1.t < interval.start { | ||
rec1.t = interval.start; | ||
} | ||
if rec2.t > interval.end { | ||
rec2.t = interval.end; | ||
} | ||
|
||
if rec1.t >= rec2.t { | ||
return None; | ||
} | ||
|
||
if rec1.t < 0. { | ||
rec1.t = 0.; | ||
} | ||
|
||
let ray_length = ray.direction.length(); | ||
let distance_inside_boundary = | ||
(rec2.t - rec1.t) * ray_length; | ||
let hit_distance = | ||
self.neg_inv_density * rng.gen::<f64>().log10(); | ||
|
||
if hit_distance > distance_inside_boundary { | ||
return None; | ||
} | ||
|
||
let t = rec1.t + hit_distance / ray_length; | ||
let point = ray.at(t); | ||
|
||
let rec = HitRecord { | ||
point, | ||
normal: DVec3::new(1., 0., 0.), // arbitrary | ||
t, | ||
front_face: true, // also arbitrary | ||
material: self.phase_function.clone(), | ||
// Arbitrary u/v? | ||
u: 0., | ||
v: 0., | ||
}; | ||
|
||
Some(rec) | ||
} | ||
} |