Update camera to implement defocused blur.
Removed tracer programs that no longer compile with new Camera API.
This commit is contained in:
parent
5ba579a374
commit
f2c5cf48ad
@ -29,20 +29,93 @@ fn color(r: Ray, world: &Hit, depth: usize) -> Vec3 {
|
||||
Vec3::new(1., 1., 1.) * (1. - t) + Vec3::new(0.5, 0.7, 1.) * t
|
||||
}
|
||||
|
||||
fn random_scene() -> Vec<Box<Hit>> {
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut objects: Vec<Box<Hit>> = vec![Box::new(Sphere::new(
|
||||
Vec3::new(0., -1000., 0.),
|
||||
1000.,
|
||||
Box::new(Lambertian::new(Vec3::new(0.5, 0.5, 0.5))),
|
||||
))];
|
||||
let mut random = || rng.gen_range::<f32>(0., 1.);
|
||||
|
||||
for a in -11..11 {
|
||||
for b in -11..11 {
|
||||
let choose_mat = random();
|
||||
let center = Vec3::new(a as f32 + 0.9 * random(), 0.2, b as f32 + 0.9 * random());
|
||||
if (center - Vec3::new(4., 0.2, 0.)).length() > 0.9 {
|
||||
let sphere = if choose_mat < 0.8 {
|
||||
// diffuse
|
||||
Box::new(Sphere::new(
|
||||
center,
|
||||
0.2,
|
||||
Box::new(Lambertian::new(Vec3::new(
|
||||
random() * random(),
|
||||
random() * random(),
|
||||
random() * random(),
|
||||
))),
|
||||
))
|
||||
} else if choose_mat < 0.95 {
|
||||
// metal
|
||||
Box::new(Sphere::new(
|
||||
center,
|
||||
0.2,
|
||||
Box::new(Metal::new(
|
||||
Vec3::new(
|
||||
0.5 * (1. + random()),
|
||||
0.5 * (1. + random()),
|
||||
0.5 * (1. + random()),
|
||||
),
|
||||
0.5 * random(),
|
||||
)),
|
||||
))
|
||||
} else {
|
||||
// glass
|
||||
Box::new(Sphere::new(center, 0.2, Box::new(Dielectric::new(1.5))))
|
||||
};
|
||||
objects.push(sphere);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let more: Vec<Box<Hit>> = vec![
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(0., 1., 0.),
|
||||
1.0,
|
||||
Box::new(Dielectric::new(1.5)),
|
||||
)),
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(-4., 1., 0.),
|
||||
1.0,
|
||||
Box::new(Lambertian::new(Vec3::new(0.4, 0.2, 0.1))),
|
||||
)),
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(4., 1., 0.),
|
||||
1.0,
|
||||
Box::new(Metal::new(Vec3::new(0.7, 0.6, 0.5), 0.0)),
|
||||
)),
|
||||
];
|
||||
objects.extend(more);
|
||||
objects
|
||||
}
|
||||
|
||||
fn main() -> Result<(), std::io::Error> {
|
||||
let mut rng = rand::thread_rng();
|
||||
let nx = 200;
|
||||
let ny = 100;
|
||||
let ns = 100;
|
||||
println!("P3\n{} {}\n255", nx, ny);
|
||||
let cam = Camera::new_lookfrom_vfov(
|
||||
Vec3::new(-2., 2., 1.),
|
||||
Vec3::new(0., 0., -1.),
|
||||
let lookfrom = Vec3::new(3., 3., 2.);
|
||||
let lookat = Vec3::new(0., 0., -1.);
|
||||
let dist_to_focus = (lookfrom - lookat).length();
|
||||
let aperture = 2.;
|
||||
let cam = Camera::new(
|
||||
lookfrom,
|
||||
lookat,
|
||||
Vec3::new(0., 1., 0.),
|
||||
45.,
|
||||
20.,
|
||||
nx as f32 / ny as f32,
|
||||
aperture,
|
||||
dist_to_focus,
|
||||
);
|
||||
// TODO(wathiede): Box this instead of using references.
|
||||
let world = HitableList::new(vec![
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(0., 0., -1.),
|
||||
@ -70,6 +143,8 @@ fn main() -> Result<(), std::io::Error> {
|
||||
Box::new(Dielectric::new(1.5)),
|
||||
)),
|
||||
]);
|
||||
//let world = HitableList::new(random_scene());
|
||||
println!("P3\n{} {}\n255", nx, ny);
|
||||
for j in (0..ny).rev() {
|
||||
for i in 0..nx {
|
||||
let mut col: Vec3 = Default::default();
|
||||
|
||||
@ -1,86 +0,0 @@
|
||||
extern crate rand;
|
||||
extern crate rtiow;
|
||||
|
||||
use rand::Rng;
|
||||
|
||||
use rtiow::camera::Camera;
|
||||
use rtiow::hitable::Hit;
|
||||
use rtiow::hitable_list::HitableList;
|
||||
use rtiow::material::Dielectric;
|
||||
use rtiow::material::Lambertian;
|
||||
use rtiow::material::Metal;
|
||||
use rtiow::ray::Ray;
|
||||
use rtiow::sphere::Sphere;
|
||||
use rtiow::vec3::Vec3;
|
||||
|
||||
fn color(r: Ray, world: &Hit, depth: usize) -> Vec3 {
|
||||
if let Some(rec) = world.hit(r, 0.001, std::f32::MAX) {
|
||||
let scatter_response = rec.material.scatter(&r, &rec);
|
||||
if depth < 50 && scatter_response.reflected {
|
||||
return scatter_response.attenutation
|
||||
* color(scatter_response.scattered, world, depth + 1);
|
||||
}
|
||||
return Default::default();
|
||||
}
|
||||
|
||||
// No hit, choose color from background.
|
||||
let unit_direction = r.direction().unit_vector();
|
||||
let t = 0.5 * (unit_direction.y + 1.);
|
||||
Vec3::new(1., 1., 1.) * (1. - t) + Vec3::new(0.5, 0.7, 1.) * t
|
||||
}
|
||||
|
||||
fn main() -> Result<(), std::io::Error> {
|
||||
let mut rng = rand::thread_rng();
|
||||
let nx = 200;
|
||||
let ny = 100;
|
||||
let ns = 100;
|
||||
println!("P3\n{} {}\n255", nx, ny);
|
||||
let world = HitableList::new(vec![
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(0., 0., -1.),
|
||||
0.5,
|
||||
Box::new(Lambertian::new(Vec3::new(0.1, 0.2, 0.5))),
|
||||
)),
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(0., -100.5, -1.),
|
||||
100.,
|
||||
Box::new(Lambertian::new(Vec3::new(0.8, 0.8, 0.))),
|
||||
)),
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(1., 0., -1.),
|
||||
0.5,
|
||||
Box::new(Metal::new(Vec3::new(0.8, 0.6, 0.2), 0.2)),
|
||||
)),
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(-1., 0., -1.),
|
||||
0.5,
|
||||
Box::new(Dielectric::new(1.5)),
|
||||
)),
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(-1., 0., -1.),
|
||||
-0.45,
|
||||
Box::new(Dielectric::new(1.5)),
|
||||
)),
|
||||
]);
|
||||
let cam = Camera::new2x1();
|
||||
for j in (0..ny).rev() {
|
||||
for i in 0..nx {
|
||||
let mut col: Vec3 = Default::default();
|
||||
for _ in 0..ns {
|
||||
let u = (rng.gen_range::<f32>(0., 1.) + i as f32) / nx as f32;
|
||||
let v = (rng.gen_range::<f32>(0., 1.) + j as f32) / ny as f32;
|
||||
let r = cam.get_ray(u, v);
|
||||
col = col + color(r, &world, 0);
|
||||
}
|
||||
col = col / ns as f32;
|
||||
// Gamma correct, use gamma 2 correction, which is 1/gamma where gamma=2 which is 1/2
|
||||
// or sqrt.
|
||||
col = Vec3::new(col[0].sqrt(), col[1].sqrt(), col[2].sqrt());
|
||||
let ir = (255.99 * col[0]) as u32;
|
||||
let ig = (255.99 * col[1]) as u32;
|
||||
let ib = (255.99 * col[2]) as u32;
|
||||
println!("{} {} {}", ir, ig, ib);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -1,80 +0,0 @@
|
||||
extern crate rand;
|
||||
extern crate rtiow;
|
||||
|
||||
use rand::Rng;
|
||||
|
||||
use rtiow::camera::Camera;
|
||||
use rtiow::hitable::Hit;
|
||||
use rtiow::hitable_list::HitableList;
|
||||
use rtiow::material::Lambertian;
|
||||
use rtiow::material::Metal;
|
||||
use rtiow::ray::Ray;
|
||||
use rtiow::sphere::Sphere;
|
||||
use rtiow::vec3::Vec3;
|
||||
|
||||
fn color(r: Ray, world: &Hit, depth: usize) -> Vec3 {
|
||||
if let Some(rec) = world.hit(r, 0.001, std::f32::MAX) {
|
||||
let scatter_response = rec.material.scatter(&r, &rec);
|
||||
if depth < 50 && scatter_response.reflected {
|
||||
return scatter_response.attenutation
|
||||
* color(scatter_response.scattered, world, depth + 1);
|
||||
}
|
||||
return Default::default();
|
||||
}
|
||||
|
||||
// No hit, choose color from background.
|
||||
let unit_direction = r.direction().unit_vector();
|
||||
let t = 0.5 * (unit_direction.y + 1.);
|
||||
Vec3::new(1., 1., 1.) * (1. - t) + Vec3::new(0.5, 0.7, 1.) * t
|
||||
}
|
||||
|
||||
fn main() -> Result<(), std::io::Error> {
|
||||
let mut rng = rand::thread_rng();
|
||||
let nx = 200;
|
||||
let ny = 100;
|
||||
let ns = 100;
|
||||
println!("P3\n{} {}\n255", nx, ny);
|
||||
let world = HitableList::new(vec![
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(0., 0., -1.),
|
||||
0.5,
|
||||
Box::new(Lambertian::new(Vec3::new(0.8, 0.3, 0.3))),
|
||||
)),
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(0., -100.5, -1.),
|
||||
100.,
|
||||
Box::new(Lambertian::new(Vec3::new(0.8, 0.8, 0.))),
|
||||
)),
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(1., 0., -1.),
|
||||
0.5,
|
||||
Box::new(Metal::new(Vec3::new(0.8, 0.6, 0.2), 0.2)),
|
||||
)),
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(-1., 0., -1.),
|
||||
0.5,
|
||||
Box::new(Metal::new(Vec3::new(0.8, 0.8, 0.8), 0.8)),
|
||||
)),
|
||||
]);
|
||||
let cam = Camera::new2x1();
|
||||
for j in (0..ny).rev() {
|
||||
for i in 0..nx {
|
||||
let mut col: Vec3 = Default::default();
|
||||
for _ in 0..ns {
|
||||
let u = (rng.gen_range::<f32>(0., 1.) + i as f32) / nx as f32;
|
||||
let v = (rng.gen_range::<f32>(0., 1.) + j as f32) / ny as f32;
|
||||
let r = cam.get_ray(u, v);
|
||||
col = col + color(r, &world, 0);
|
||||
}
|
||||
col = col / ns as f32;
|
||||
// Gamma correct, use gamma 2 correction, which is 1/gamma where gamma=2 which is 1/2
|
||||
// or sqrt.
|
||||
col = Vec3::new(col[0].sqrt(), col[1].sqrt(), col[2].sqrt());
|
||||
let ir = (255.99 * col[0]) as u32;
|
||||
let ig = (255.99 * col[1]) as u32;
|
||||
let ib = (255.99 * col[2]) as u32;
|
||||
println!("{} {} {}", ir, ig, ib);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -1,92 +0,0 @@
|
||||
extern crate rand;
|
||||
extern crate rtiow;
|
||||
|
||||
use rand::Rng;
|
||||
|
||||
use rtiow::camera::Camera;
|
||||
use rtiow::hitable::Hit;
|
||||
use rtiow::hitable_list::HitableList;
|
||||
use rtiow::material::Dielectric;
|
||||
use rtiow::material::Lambertian;
|
||||
use rtiow::material::Metal;
|
||||
use rtiow::ray::Ray;
|
||||
use rtiow::sphere::Sphere;
|
||||
use rtiow::vec3::Vec3;
|
||||
|
||||
fn color(r: Ray, world: &Hit, depth: usize) -> Vec3 {
|
||||
if let Some(rec) = world.hit(r, 0.001, std::f32::MAX) {
|
||||
let scatter_response = rec.material.scatter(&r, &rec);
|
||||
if depth < 50 && scatter_response.reflected {
|
||||
return scatter_response.attenutation
|
||||
* color(scatter_response.scattered, world, depth + 1);
|
||||
}
|
||||
return Default::default();
|
||||
}
|
||||
|
||||
// No hit, choose color from background.
|
||||
let unit_direction = r.direction().unit_vector();
|
||||
let t = 0.5 * (unit_direction.y + 1.);
|
||||
Vec3::new(1., 1., 1.) * (1. - t) + Vec3::new(0.5, 0.7, 1.) * t
|
||||
}
|
||||
|
||||
fn main() -> Result<(), std::io::Error> {
|
||||
let mut rng = rand::thread_rng();
|
||||
let nx = 200;
|
||||
let ny = 100;
|
||||
let ns = 100;
|
||||
println!("P3\n{} {}\n255", nx, ny);
|
||||
let world = HitableList::new(vec![
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(0., 0., -1.),
|
||||
0.5,
|
||||
Box::new(Lambertian::new(Vec3::new(0.1, 0.2, 0.5))),
|
||||
)),
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(0., -100.5, -1.),
|
||||
100.,
|
||||
Box::new(Lambertian::new(Vec3::new(0.8, 0.8, 0.))),
|
||||
)),
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(1., 0., -1.),
|
||||
0.5,
|
||||
Box::new(Metal::new(Vec3::new(0.8, 0.6, 0.2), 0.2)),
|
||||
)),
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(-1., 0., -1.),
|
||||
0.5,
|
||||
Box::new(Dielectric::new(1.5)),
|
||||
)),
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(-1., 0., -1.),
|
||||
-0.45,
|
||||
Box::new(Dielectric::new(1.5)),
|
||||
)),
|
||||
]);
|
||||
let cam = Camera::new_lookfrom_vfov(
|
||||
Vec3::new(-2., 2., 1.),
|
||||
Vec3::new(0., 0., -1.),
|
||||
Vec3::new(0., 1., 0.),
|
||||
90.,
|
||||
nx as f32 / ny as f32,
|
||||
);
|
||||
for j in (0..ny).rev() {
|
||||
for i in 0..nx {
|
||||
let mut col: Vec3 = Default::default();
|
||||
for _ in 0..ns {
|
||||
let u = (rng.gen_range::<f32>(0., 1.) + i as f32) / nx as f32;
|
||||
let v = (rng.gen_range::<f32>(0., 1.) + j as f32) / ny as f32;
|
||||
let r = cam.get_ray(u, v);
|
||||
col = col + color(r, &world, 0);
|
||||
}
|
||||
col = col / ns as f32;
|
||||
// Gamma correct, use gamma 2 correction, which is 1/gamma where gamma=2 which is 1/2
|
||||
// or sqrt.
|
||||
col = Vec3::new(col[0].sqrt(), col[1].sqrt(), col[2].sqrt());
|
||||
let ir = (255.99 * col[0]) as u32;
|
||||
let ig = (255.99 * col[1]) as u32;
|
||||
let ib = (255.99 * col[2]) as u32;
|
||||
println!("{} {} {}", ir, ig, ib);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -1,33 +1,48 @@
|
||||
extern crate rand;
|
||||
use std::f32::consts::PI;
|
||||
|
||||
use self::rand::Rng;
|
||||
|
||||
use ray::Ray;
|
||||
use vec3::cross;
|
||||
use vec3::Vec3;
|
||||
|
||||
fn random_in_unit_disk() -> Vec3 {
|
||||
let mut rng = rand::thread_rng();
|
||||
let v = Vec3::new(1., 1., 0.);
|
||||
loop {
|
||||
let p = 2. * Vec3::new(
|
||||
rng.gen_range::<f32>(0., 1.),
|
||||
rng.gen_range::<f32>(0., 1.),
|
||||
0.,
|
||||
) - v;
|
||||
if p.squared_length() < 1. {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Camera {
|
||||
origin: Vec3,
|
||||
lower_left_corner: Vec3,
|
||||
horizontal: Vec3,
|
||||
vertical: Vec3,
|
||||
u: Vec3,
|
||||
v: Vec3,
|
||||
w: Vec3,
|
||||
lens_radius: f32,
|
||||
}
|
||||
|
||||
impl Camera {
|
||||
pub fn new2x1() -> Camera {
|
||||
Camera {
|
||||
lower_left_corner: Vec3::new(-2., -1., -1.),
|
||||
horizontal: Vec3::new(4., 0., 0.),
|
||||
vertical: Vec3::new(0., 2., 0.),
|
||||
origin: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
// vfov is top to bottom in degrees
|
||||
pub fn new_lookfrom_vfov(
|
||||
pub fn new(
|
||||
lookfrom: Vec3,
|
||||
lookat: Vec3,
|
||||
vup: Vec3,
|
||||
vfov: f32,
|
||||
aspect: f32,
|
||||
aperture: f32,
|
||||
focus_dist: f32,
|
||||
) -> Camera {
|
||||
let theta = vfov * PI / 180.;
|
||||
let half_height = (theta / 2.).tan();
|
||||
@ -37,30 +52,26 @@ impl Camera {
|
||||
let u = cross(vup, w).unit_vector();
|
||||
let v = cross(w, u);
|
||||
Camera {
|
||||
lower_left_corner: origin - half_width * u - half_height * v - w,
|
||||
horizontal: 2. * half_width * u,
|
||||
vertical: 2. * half_height * v,
|
||||
lower_left_corner: origin
|
||||
- half_width * focus_dist * u
|
||||
- half_height * focus_dist * v
|
||||
- focus_dist * w,
|
||||
horizontal: 2. * half_width * focus_dist * u,
|
||||
vertical: 2. * half_height * focus_dist * v,
|
||||
origin,
|
||||
}
|
||||
}
|
||||
|
||||
// vfov is top to bottom in degrees
|
||||
pub fn new_vfov(vfov: f32, aspect: f32) -> Camera {
|
||||
let theta = vfov * PI / 180.;
|
||||
let half_height = (theta / 2.).tan();
|
||||
let half_width = aspect * half_height;
|
||||
Camera {
|
||||
lower_left_corner: Vec3::new(-half_width, -half_height, -1.),
|
||||
horizontal: Vec3::new(2. * half_width, 0., 0.),
|
||||
vertical: Vec3::new(0., 2. * half_height, 0.),
|
||||
origin: Default::default(),
|
||||
w: (lookfrom - lookat).unit_vector(),
|
||||
u: cross(vup, w).unit_vector(),
|
||||
v: cross(w, u),
|
||||
lens_radius: aperture / 2.,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_ray(&self, u: f32, v: f32) -> Ray {
|
||||
let rd = self.lens_radius * random_in_unit_disk();
|
||||
let offset = self.u * rd.x + self.v * rd.y;
|
||||
Ray::new(
|
||||
self.origin,
|
||||
self.lower_left_corner + self.horizontal * u + self.vertical * v - self.origin,
|
||||
self.origin + offset,
|
||||
self.lower_left_corner + self.horizontal * u + self.vertical * v - self.origin - offset,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user