fix: Corrected the distributions
I had been carrying the distributions around with the SmallRng object so that I can provide whatever bounds needed. It turns out that the book only takes advantage of this a couple of times. The functions accepting a Uniform struct no longer do. They instead construct their own temporary one -- hopefully the optimizer can see through the loops and construct it just once. :l The change exposed all the uses of the distributions (duh!) and now they are correct. The effect is most pronounced on the dielectric spheres.
This commit is contained in:
@@ -15,14 +15,13 @@ use crate::ray::Ray;
|
|||||||
use crate::degrees_to_radians;
|
use crate::degrees_to_radians;
|
||||||
|
|
||||||
use rand::rngs::SmallRng;
|
use rand::rngs::SmallRng;
|
||||||
use rand::distributions::Uniform;
|
|
||||||
|
|
||||||
pub struct Camera {
|
pub struct Camera {
|
||||||
origin: Vec3,
|
origin: Vec3,
|
||||||
lower_left_corner: Vec3,
|
lower_left_corner: Vec3,
|
||||||
horizontal: Vec3,
|
horizontal: Vec3,
|
||||||
vertical: Vec3,
|
vertical: Vec3,
|
||||||
u: Vec3, v: Vec3, w: Vec3,
|
u: Vec3, v: Vec3, /*w: Vec3,*/
|
||||||
lens_radius: f32,
|
lens_radius: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,13 +54,13 @@ impl Camera {
|
|||||||
lower_left_corner,
|
lower_left_corner,
|
||||||
horizontal: horiz,
|
horizontal: horiz,
|
||||||
vertical: verti,
|
vertical: verti,
|
||||||
u, v, w,
|
u, v, /* w,*/
|
||||||
lens_radius: aperture / 2.0,
|
lens_radius: aperture / 2.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ray(&self, s: f32, t: f32, srng: &mut SmallRng, distrib: Uniform<f32>) -> Ray {
|
pub fn get_ray(&self, s: f32, t: f32, srng: &mut SmallRng) -> Ray {
|
||||||
let rd = Vec3::rand_in_unit_disk(srng, distrib) * self.lens_radius;
|
let rd = Vec3::rand_in_unit_disk(srng) * self.lens_radius;
|
||||||
let offset = self.u * rd.x + self.v * rd.y;
|
let offset = self.u * rd.x + self.v * rd.y;
|
||||||
|
|
||||||
let dir = self.lower_left_corner
|
let dir = self.lower_left_corner
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ impl HittableList{
|
|||||||
pub fn add(&mut self, hittable: Box<dyn Hittable> ) -> () {
|
pub fn add(&mut self, hittable: Box<dyn Hittable> ) -> () {
|
||||||
self.hittables.push(hittable);
|
self.hittables.push(hittable);
|
||||||
}
|
}
|
||||||
pub fn clear(&mut self) -> () {
|
// pub fn clear(&mut self) -> () {
|
||||||
self.hittables.clear();
|
// self.hittables.clear();
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hittable for HittableList{
|
impl Hittable for HittableList{
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ fn main() {
|
|||||||
for _ in 0..samples_per_pixel {
|
for _ in 0..samples_per_pixel {
|
||||||
let u = ((x as f32) + small_rng.sample(distrib_zero_one)) / ((image.0 - 1) as f32);
|
let u = ((x as f32) + small_rng.sample(distrib_zero_one)) / ((image.0 - 1) as f32);
|
||||||
let v = ((y as f32) + small_rng.sample(distrib_zero_one)) / ((image.1 - 1) as f32);
|
let v = ((y as f32) + small_rng.sample(distrib_zero_one)) / ((image.1 - 1) as f32);
|
||||||
let ray = cam.get_ray(u, v, &mut small_rng, distrib_plusminus_one);
|
let ray = cam.get_ray(u, v, &mut small_rng);
|
||||||
color+= ray_color(ray, &world, max_depth, &mut small_rng, distrib_plusminus_one);
|
color+= ray_color(ray, &world, max_depth, &mut small_rng, distrib_plusminus_one);
|
||||||
}
|
}
|
||||||
println!("{}", color.print_ppm(samples_per_pixel));
|
println!("{}", color.print_ppm(samples_per_pixel));
|
||||||
@@ -88,7 +88,7 @@ fn ray_color(r: Ray, world: &dyn Hittable, depth: u32, srng: &mut SmallRng, dist
|
|||||||
let mut attenuation = Vec3::zero();
|
let mut attenuation = Vec3::zero();
|
||||||
match rec.material {
|
match rec.material {
|
||||||
Some(mat) => {
|
Some(mat) => {
|
||||||
if mat.scatter(r, rec, &mut attenuation, &mut scattered, srng, distrib) {
|
if mat.scatter(r, rec, &mut attenuation, &mut scattered, srng) {
|
||||||
return attenuation * ray_color(scattered, world, depth-1, srng, distrib);
|
return attenuation * ray_color(scattered, world, depth-1, srng, distrib);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -108,8 +108,6 @@ fn random_scene(srng: &mut SmallRng) -> HittableList {
|
|||||||
world.add( Box::new( Sphere::new(0.0, -1000.0, 0.0, 1000.0, Some(mat_ground) )));
|
world.add( Box::new( Sphere::new(0.0, -1000.0, 0.0, 1000.0, Some(mat_ground) )));
|
||||||
|
|
||||||
let distrib_zero_one = Uniform::new(0.0, 1.0);
|
let distrib_zero_one = Uniform::new(0.0, 1.0);
|
||||||
let distrib_plusminus_one = Uniform::new(-1.0, 1.0);
|
|
||||||
|
|
||||||
for a in -11..11 {
|
for a in -11..11 {
|
||||||
for b in -11..11 {
|
for b in -11..11 {
|
||||||
let choose_mat = srng.sample(distrib_zero_one);
|
let choose_mat = srng.sample(distrib_zero_one);
|
||||||
|
|||||||
@@ -25,11 +25,10 @@ impl Material {
|
|||||||
attenuation: &mut Vec3,
|
attenuation: &mut Vec3,
|
||||||
scattered: &mut Ray,
|
scattered: &mut Ray,
|
||||||
srng: &mut SmallRng,
|
srng: &mut SmallRng,
|
||||||
distrib: Uniform<f32>,
|
|
||||||
) -> bool {
|
) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Material::Lambertian { albedo } => {
|
Material::Lambertian { albedo } => {
|
||||||
let scatter_dir = rec.normal + Vec3::rand_unit_vector(srng, distrib);
|
let scatter_dir = rec.normal + Vec3::rand_unit_vector(srng);
|
||||||
// The compiler might be smart enough to compute this ^^^ just once. In which case,
|
// The compiler might be smart enough to compute this ^^^ just once. In which case,
|
||||||
// I don't need to do this weird dance. Oh well. It'll work.
|
// I don't need to do this weird dance. Oh well. It'll work.
|
||||||
let scatter_dir = if scatter_dir.near_zero() { // if near zero,
|
let scatter_dir = if scatter_dir.near_zero() { // if near zero,
|
||||||
@@ -55,7 +54,7 @@ impl Material {
|
|||||||
);
|
);
|
||||||
*scattered = Ray{
|
*scattered = Ray{
|
||||||
orig: rec.p,
|
orig: rec.p,
|
||||||
dir: reflected + Vec3::rand_in_unit_sphere(srng, distrib) * *fuzz,
|
dir: reflected + Vec3::rand_in_unit_sphere(srng) * *fuzz,
|
||||||
};
|
};
|
||||||
*attenuation = *albedo;
|
*attenuation = *albedo;
|
||||||
return Vec3::dot(scattered.dir, rec.normal) > 0.0;
|
return Vec3::dot(scattered.dir, rec.normal) > 0.0;
|
||||||
@@ -69,7 +68,8 @@ impl Material {
|
|||||||
let sin_theta = (1.0 - cos_theta * cos_theta).sqrt();
|
let sin_theta = (1.0 - cos_theta * cos_theta).sqrt();
|
||||||
|
|
||||||
let cannot_refract = refraction_ratio * sin_theta > 1.0;
|
let cannot_refract = refraction_ratio * sin_theta > 1.0;
|
||||||
let direction = if cannot_refract || Material::reflectance(cos_theta, refraction_ratio) > srng.sample(distrib) {
|
let distrib_zero_one = Uniform::new(0.0, 1.0);
|
||||||
|
let direction = if cannot_refract || Material::reflectance(cos_theta, refraction_ratio) > srng.sample(distrib_zero_one) {
|
||||||
Vec3::reflect(unit_direction, rec.normal)
|
Vec3::reflect(unit_direction, rec.normal)
|
||||||
} else {
|
} else {
|
||||||
Vec3::refract(unit_direction, rec.normal, refraction_ratio)
|
Vec3::refract(unit_direction, rec.normal, refraction_ratio)
|
||||||
|
|||||||
10
src/vec3.rs
10
src/vec3.rs
@@ -53,7 +53,8 @@ impl Vec3{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rand_in_unit_sphere(srng: &mut SmallRng, distrib: Uniform<f32>) -> Vec3 {
|
pub fn rand_in_unit_sphere(srng: &mut SmallRng) -> Vec3 {
|
||||||
|
let distrib = Uniform::new(-1.0, 1.0);
|
||||||
loop {
|
loop {
|
||||||
let p = Vec3::rand(srng, distrib);
|
let p = Vec3::rand(srng, distrib);
|
||||||
if p.length_squared() >= 1.0 { continue; }
|
if p.length_squared() >= 1.0 { continue; }
|
||||||
@@ -61,7 +62,8 @@ impl Vec3{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rand_in_unit_disk(srng: &mut SmallRng, distrib: Uniform<f32>) -> Vec3 {
|
pub fn rand_in_unit_disk(srng: &mut SmallRng) -> Vec3 {
|
||||||
|
let distrib = Uniform::new(-1.0, 1.0);
|
||||||
loop {
|
loop {
|
||||||
let p = Vec3 {
|
let p = Vec3 {
|
||||||
x: srng.sample(distrib),
|
x: srng.sample(distrib),
|
||||||
@@ -73,8 +75,8 @@ impl Vec3{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rand_unit_vector(srng: &mut SmallRng, distrib: Uniform<f32>) -> Vec3 {
|
pub fn rand_unit_vector(srng: &mut SmallRng) -> Vec3 {
|
||||||
return Vec3::as_unit(Vec3::rand_in_unit_sphere(srng, distrib));
|
return Vec3::as_unit(Vec3::rand_in_unit_sphere(srng));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn length(&self) -> f32 {
|
pub fn length(&self) -> f32 {
|
||||||
|
|||||||
Reference in New Issue
Block a user