Skip to content

Commit

Permalink
fix: random direction generation on unit sphere, not inside it
Browse files Browse the repository at this point in the history
  • Loading branch information
Walther committed Oct 17, 2023
1 parent 6231979 commit 45a6867
Show file tree
Hide file tree
Showing 6 changed files with 15 additions and 22 deletions.
4 changes: 2 additions & 2 deletions clovers/benches/random.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
let mut rng = SmallRng::from_entropy();

c.bench_function("random in unit sphere", |b| {
b.iter(|| random_in_unit_sphere(black_box(&mut rng)))
b.iter(|| random_unit_vector(black_box(&mut rng)))
});

c.bench_function("random in unit disk", |b| {
Expand All @@ -25,7 +25,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {

let normal = Vec3::new(1.0, 0.0, 0.0);
c.bench_function("random in hemisphere", |b| {
b.iter(|| random_in_hemisphere(normal, black_box(&mut rng)))
b.iter(|| random_on_hemisphere(normal, black_box(&mut rng)))
});
}

Expand Down
4 changes: 2 additions & 2 deletions clovers/src/materials/gltf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use rand::rngs::SmallRng;
use crate::{
hitable::HitRecord,
pdf::{ZeroPDF, PDF},
random::random_in_unit_sphere,
random::random_unit_vector,
ray::Ray,
Float, Vec2, Vec3, Vec4, PI,
};
Expand Down Expand Up @@ -97,7 +97,7 @@ impl<'scene> MaterialTrait for GLTFMaterial<'scene> {
if metalness > 0.0 {
// TODO: borrowed from metal, should this be different?
let reflected: Vec3 = reflect(ray.direction.normalize(), normal);
let direction = reflected + roughness * random_in_unit_sphere(rng);
let direction = reflected + roughness * random_unit_vector(rng);

Some(ScatterRecord {
specular_ray: Some(Ray {
Expand Down
4 changes: 2 additions & 2 deletions clovers/src/materials/metal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use super::{reflect, MaterialTrait, MaterialType, ScatterRecord};
use crate::{
hitable::HitRecord,
pdf::{ZeroPDF, PDF},
random::random_in_unit_sphere,
random::random_unit_vector,
ray::Ray,
textures::{Texture, TextureTrait},
Float, Vec3,
Expand Down Expand Up @@ -34,7 +34,7 @@ impl MaterialTrait for Metal {
Some(ScatterRecord {
specular_ray: Some(Ray {
origin: hit_record.position,
direction: reflected + self.fuzz * random_in_unit_sphere(rng),
direction: reflected + self.fuzz * random_unit_vector(rng),
time: ray.time,
wavelength: ray.wavelength,
}),
Expand Down
4 changes: 2 additions & 2 deletions clovers/src/objects/moving_sphere.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
colors::Wavelength,
hitable::{HitRecord, HitableTrait},
materials::{Material, MaterialInit},
random::random_in_unit_sphere,
random::random_unit_vector,
ray::Ray,
Float, Vec3, PI,
};
Expand Down Expand Up @@ -174,6 +174,6 @@ impl<'scene> HitableTrait for MovingSphere<'scene> {
}

fn random(&self, _origin: Vec3, rng: &mut SmallRng) -> Vec3 {
random_in_unit_sphere(rng)
random_unit_vector(rng)
}
}
6 changes: 3 additions & 3 deletions clovers/src/pdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
colors::Wavelength,
hitable::{Hitable, HitableTrait},
onb::ONB,
random::{random_cosine_direction, random_in_unit_sphere},
random::{random_cosine_direction, random_unit_vector},
Box, Float, Vec3, PI,
};
use enum_dispatch::enum_dispatch;
Expand Down Expand Up @@ -171,7 +171,7 @@ impl PDFTrait for SpherePDF {

#[must_use]
fn generate(&self, rng: &mut SmallRng) -> Vec3 {
random_in_unit_sphere(rng)
random_unit_vector(rng)
}
}

Expand Down Expand Up @@ -200,7 +200,7 @@ impl PDFTrait for ZeroPDF {

#[must_use]
fn generate(&self, rng: &mut SmallRng) -> Vec3 {
random_in_unit_sphere(rng)
random_unit_vector(rng)
}
}

Expand Down
15 changes: 4 additions & 11 deletions clovers/src/random.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,9 @@
use crate::{Float, Vec3, PI};
use rand::rngs::SmallRng;
use rand::Rng;
use rand_distr::{Distribution, UnitBall, UnitDisc, UnitSphere};
use rand_distr::{Distribution, UnitDisc, UnitSphere};

/// Internal helper. Originally used for lambertian reflection with flaws
#[must_use]
#[inline]
pub fn random_in_unit_sphere(rng: &mut SmallRng) -> Vec3 {
UnitBall.sample(rng).into()
}

/// Internal helper. Use this for the more correct "True Lambertian" reflection
/// Internal helper.
#[must_use]
pub fn random_unit_vector(rng: &mut SmallRng) -> Vec3 {
UnitSphere.sample(rng).into()
Expand Down Expand Up @@ -42,8 +35,8 @@ pub fn random_cosine_direction(rng: &mut SmallRng) -> Vec3 {

/// Internal helper.
#[must_use]
pub fn random_in_hemisphere(normal: Vec3, rng: &mut SmallRng) -> Vec3 {
let in_unit_sphere: Vec3 = random_in_unit_sphere(rng);
pub fn random_on_hemisphere(normal: Vec3, rng: &mut SmallRng) -> Vec3 {
let in_unit_sphere: Vec3 = random_unit_vector(rng);
if in_unit_sphere.dot(&normal) > 0.0 {
// In the same hemisphere as the normal
in_unit_sphere
Expand Down

0 comments on commit 45a6867

Please sign in to comment.