-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathvector_parallel.rs
65 lines (59 loc) · 2.18 KB
/
vector_parallel.rs
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
//! SIMD parallel aobench
use ambient_occlusion;
use geometry::{Ray, V3D};
use intersection::{Intersect, Isect};
use rayon::prelude::*;
use scene::Scene;
pub fn ao<S: Scene>(_: &mut S, nsubsamples: usize, img: &mut ::Image) {
let (w, h) = img.size();
let image = &mut img.fdata;
let image_ptr = image.as_mut_ptr() as usize;
let image_len = image.len();
let ns = nsubsamples;
(0..h).into_par_iter().for_each(|y| {
let image = unsafe {
::std::slice::from_raw_parts_mut(image_ptr as *mut f32, image_len)
};
let mut scene = S::new();
for x in 0..w {
let offset = 3 * (y * w + x);
for u in 0..ns {
for v in 0..ns {
let (x, y, u, v, h, w, ns) = (
x as f32, y as f32, u as f32, v as f32, h as f32,
w as f32, ns as f32,
);
let dir: V3D = V3D {
x: (x + u / ns - w / 2.) / (w / 2.) * w / h,
y: -(y + v / ns - h / 2.) / (h / 2.),
z: -1.,
};
let dir = dir.normalized();
let ray = Ray {
origin: V3D::new(),
dir,
};
let mut isect = Isect::new();
for s in scene.spheres() {
isect = ray.intersect(s, isect);
}
isect = ray.intersect(scene.plane(), isect);
let ret = if isect.hit {
ambient_occlusion::vector(&mut scene, &isect)
} else {
0.
};
// Update image for AO for this ray
image[offset + 0] += ret;
image[offset + 1] += ret;
image[offset + 2] += ret;
}
}
// Normalize image pixels by number of samples taken per pixel
let ns = (ns * ns) as f32;
image[offset + 0] /= ns;
image[offset + 1] /= ns;
image[offset + 2] /= ns;
}
});
}