library: render: take advantage of cosine-weighted
This commit is contained in:
parent
311b7cd03b
commit
7567b93f9c
|
@ -48,7 +48,7 @@ impl BidirectionalPathtracer {
|
|||
|
||||
res.push_point(p);
|
||||
|
||||
let (new_direction, _) = sample_hemisphere(normal);
|
||||
let new_direction = sample_hemisphere(normal);
|
||||
// Calculate the incoming light along the new ray
|
||||
origin = hit_pos + new_direction.as_ref() * 0.001;
|
||||
direction = new_direction;
|
||||
|
|
|
@ -110,8 +110,7 @@ impl Pathtracer {
|
|||
let brdf = properties.diffuse;
|
||||
// Pick a new direction
|
||||
let normal = obj.shape.normal(&hit_pos);
|
||||
let (new_direction, weight) = sample_hemisphere(normal);
|
||||
let cos_new_ray = new_direction.dot(&normal);
|
||||
let new_direction = sample_hemisphere(normal);
|
||||
// Calculate the incoming light along the new ray
|
||||
let new_ray = Ray::new(hit_pos + new_direction.as_ref() * 0.001, new_direction);
|
||||
let incoming = self
|
||||
|
@ -120,7 +119,8 @@ impl Pathtracer {
|
|||
self.radiance(new_ray, t, obj, limit - 1)
|
||||
});
|
||||
// Put it all together
|
||||
properties.emitted + (brdf * incoming * cos_new_ray * weight)
|
||||
// The weight of the sample and the cosine of the new ray cancel each other out
|
||||
properties.emitted + (brdf * incoming)
|
||||
}
|
||||
|
||||
fn cast_ray(&self, ray: Ray) -> Option<(f32, &Object)> {
|
||||
|
|
|
@ -70,9 +70,9 @@ impl RefractionInfo {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns a random ray in the hemisphere described by a normal unit-vector, and the probability
|
||||
/// to have picked that direction.
|
||||
pub fn sample_hemisphere(normal: Unit<Vector>) -> (Unit<Vector>, f32) {
|
||||
/// Returns a random ray in the hemisphere described by a normal unit-vector
|
||||
/// It is cosine-sampled, which is convenient for path-tracing.
|
||||
pub fn sample_hemisphere(normal: Unit<Vector>) -> Unit<Vector> {
|
||||
let mut rng = thread_rng();
|
||||
let azimuth = rng.gen::<f32>() * std::f32::consts::PI * 2.;
|
||||
// Cosine weighted importance sampling
|
||||
|
@ -93,15 +93,13 @@ pub fn sample_hemisphere(normal: Unit<Vector>) -> (Unit<Vector>, f32) {
|
|||
let normal_b = normal.cross(&normal_t);
|
||||
|
||||
// Perform the matrix calculation by hand...
|
||||
let scattered = Unit::new_normalize(Vector::new(
|
||||
// The probability to have picked the ray is inversely proportional to cosine of the angle with
|
||||
// the normal
|
||||
Unit::new_normalize(Vector::new(
|
||||
x * normal_b.x + y * normal.x + z * normal_t.x,
|
||||
x * normal_b.y + y * normal.y + z * normal_t.y,
|
||||
x * normal_b.z + y * normal.z + z * normal_t.z,
|
||||
));
|
||||
|
||||
// The probability to have picked the ray is inversely proportional to cosine of the angle with
|
||||
// the normal
|
||||
(scattered, (1. / scattered.dot(&normal)).min(f32::MAX))
|
||||
))
|
||||
}
|
||||
|
||||
pub fn buffer_to_image(buffer: &[LinearColor], passes: u32, width: u32, height: u32) -> RgbImage {
|
||||
|
|
Loading…
Reference in a new issue