1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use std::f32;
use rand::StdRng;
use light_arena::Allocator;
use scene::Scene;
use linalg::{self, Ray};
use geometry::{Intersection, Emitter, Instance};
use film::Colorf;
use integrator::Integrator;
use bxdf::BxDFType;
use light::Light;
use sampler::Sampler;
#[derive(Clone, Copy, Debug)]
pub struct Whitted {
max_depth: u32,
}
impl Whitted {
pub fn new(max_depth: u32) -> Whitted { Whitted { max_depth: max_depth } }
}
impl Integrator for Whitted {
fn illumination(&self, scene: &Scene, light_list: &[&Emitter], ray: &Ray,
hit: &Intersection, sampler: &mut Sampler, rng: &mut StdRng,
alloc: &Allocator) -> Colorf {
let bsdf = hit.material.bsdf(hit, alloc);
let w_o = -ray.d;
let mut sample_2d = [(0.0, 0.0)];
sampler.get_samples_2d(&mut sample_2d[..], rng);
let mut illum = Colorf::broadcast(0.0);
if ray.depth == 0 {
if let Instance::Emitter(ref e) = *hit.instance {
let w = -ray.d;
illum = illum + e.radiance(&w, &hit.dg.p, &hit.dg.ng, ray.time);
}
}
for light in light_list {
let (li, w_i, pdf, occlusion) = light.sample_incident(&hit.dg.p, &sample_2d[0], ray.time);
let f = bsdf.eval(&w_o, &w_i, BxDFType::all());
if !li.is_black() && !f.is_black() && !occlusion.occluded(scene) {
illum = illum + f * li * f32::abs(linalg::dot(&w_i, &bsdf.n)) / pdf;
}
}
if ray.depth < self.max_depth {
illum = illum + self.specular_reflection(scene, light_list, ray, &bsdf, sampler, rng, alloc);
illum = illum + self.specular_transmission(scene, light_list, ray, &bsdf, sampler, rng, alloc);
}
illum
}
}