1. extern crate time;
  2. extern crate green;
  3. use green::{SchedPool, PoolConfig, GreenTaskBuilder};
  4. use std::cmp;
  5. use std::f64;
  6. use std::fmt;
  7. use std::io::File;
  8. use std::iter;
  9. use std::mem;
  10. use std::rand::Rng;
  11. use std::rand;
  12. use std::raw;
  13. use std::sync::Arc;
  14. use std::task::TaskBuilder;
  15. use time::precise_time_s;
  16. type Rfloat = f64;
  17. const RESOLUTION : uint = 128;
  18. const RAY_BIAS : Rfloat = 0.0005;
  19. const SPP : uint = 16*16; // samples per pixel
  20. const MAX_BOUNCES : uint = 8;
  21. const MIN_BOUNCES : uint = 4;
  22. const NUM_AA : uint = 4;
  23. const INV_AA : Rfloat = 1.0 / (NUM_AA as Rfloat);
  24. struct Vector
  25. {
  26. x : Rfloat,
  27. y : Rfloat,
  28. z : Rfloat,
  29. }
  30. enum MaterialType
  31. {
  32. DIFFUSE,
  33. GLOSSY,
  34. MIRROR
  35. }
  36. struct Material
  37. {
  38. material_type : MaterialType,
  39. diffuse : Vector,
  40. emissive : Vector,
  41. specular : Vector,
  42. exp : Rfloat,
  43. }
  44. impl Material
  45. {
  46. fn default() -> Material
  47. {
  48. Material { material_type : DIFFUSE, diffuse : Vector::zero(), emissive : Vector::zero(), specular : Vector::zero(), exp : 0.0 }
  49. }
  50. }
  51. struct Sphere
  52. {
  53. radius : Rfloat,
  54. center : Vector,
  55. material : Box<Material>,
  56. radius_sqr : Rfloat,
  57. }
  58. impl Sphere
  59. {
  60. fn new(radius : Rfloat, center : Vector, material : Box<Material>) -> Sphere
  61. {
  62. Sphere { radius : radius, center : center, material : material, radius_sqr : radius*radius }
  63. }
  64. fn intersects(&self, ray : &Ray) -> Rfloat
  65. {
  66. let op = self.center - ray.origin;
  67. let b = dot(&op, &ray.dir);
  68. let mut d = b * b - dot(&op, &op) + self.radius_sqr;
  69. if d < 0.0
  70. {
  71. return 0.0
  72. }
  73. d = d.sqrt();
  74. let mut t = b - d;
  75. if t > RAY_BIAS
  76. {
  77. return t
  78. }
  79. t = b + d;
  80. if t > RAY_BIAS
  81. {
  82. return t
  83. }
  84. return 0.0
  85. }
  86. fn is_light(&self) -> bool
  87. {
  88. (dot(&self.material.emissive, &self.material.emissive) > 0.0)
  89. }
  90. }
  91. struct Ray
  92. {
  93. origin : Vector,
  94. dir : Vector,
  95. }
  96. impl Ray
  97. {
  98. fn calc_intersection_point(&self, t : Rfloat) -> Vector
  99. {
  100. return self.origin + self.dir * t;
  101. }
  102. }
  103. fn dot(a : &Vector, b : &Vector) -> Rfloat
  104. {
  105. a.x * b.x + a.y * b.y + a.z * b.z
  106. }
  107. fn cross(a : &Vector, b : &Vector) -> Vector
  108. {
  109. Vector { x : a.y*b.z - a.z*b.y, y : a.z*b.x - a.x*b.z, z : a.x*b.y - a.y*b.x }
  110. }
  111. fn clamp(x : Rfloat, min : Rfloat, max : Rfloat) -> Rfloat
  112. {
  113. if x < min
  114. {
  115. return min;
  116. }
  117. if x > max
  118. {
  119. return max;
  120. }
  121. return x;
  122. }
  123. fn max(x : Rfloat, y : Rfloat) -> Rfloat
  124. {
  125. if x > y
  126. {
  127. return x;
  128. }
  129. else
  130. {
  131. return y;
  132. }
  133. }
  134. impl Vector
  135. {
  136. fn new(vx : Rfloat, vy : Rfloat, vz : Rfloat) -> Vector
  137. {
  138. Vector { x : vx, y : vy, z : vz }
  139. }
  140. fn new_normal(mut vx : Rfloat, mut vy : Rfloat, mut vz : Rfloat) -> Vector
  141. {
  142. let len_sqr = vx*vx + vy*vy + vz * vz;
  143. if len_sqr > f64::EPSILON
  144. {
  145. let len = len_sqr.sqrt();
  146. vx /= len;
  147. vy /= len;
  148. vz /= len;
  149. }
  150. Vector { x : vx, y : vy, z : vz }
  151. }
  152. fn zero() -> Vector
  153. {
  154. Vector { x : 0.0, y : 0.0, z : 0.0 }
  155. }
  156. fn normalize(&mut self)
  157. {
  158. let len_sqr = dot(self, self);
  159. if len_sqr > f64::EPSILON
  160. {
  161. let oo_len = 1.0 / len_sqr.sqrt();
  162. self.x *= oo_len;
  163. self.y *= oo_len;
  164. self.z *= oo_len;
  165. }
  166. }
  167. fn clamp01(&mut self)
  168. {
  169. self.x = clamp(self.x, 0.0, 1.0);
  170. self.y = clamp(self.y, 0.0, 1.0);
  171. self.z = clamp(self.z, 0.0, 1.0);
  172. }
  173. fn get_color(&self) -> (u32, u32, u32)
  174. {
  175. let mut color = *self;
  176. color.clamp01();
  177. let r = (color.x.powf(0.45) * 255.0 + 0.5) as u32;
  178. let g = (color.y.powf(0.45) * 255.0 + 0.5) as u32;
  179. let b = (color.z.powf(0.45) * 255.0 + 0.5) as u32;
  180. (r, g, b)
  181. }
  182. fn vecmul(&self, other : &Vector) -> Vector
  183. {
  184. Vector { x : self.x * other.x, y : self.y * other.y, z : self.z * other.z }
  185. }
  186. fn set(&mut self, x : Rfloat, y : Rfloat, z : Rfloat)
  187. {
  188. self.x = x;
  189. self.y = y;
  190. self.z = z;
  191. }
  192. fn max_component(&self) -> Rfloat
  193. {
  194. max(max(self.x, self.y), self.z)
  195. }
  196. fn negate(&mut self)
  197. {
  198. self.x = -self.x;
  199. self.y = -self.y;
  200. self.z = -self.z;
  201. }
  202. }
  203. impl Sub<Vector, Vector> for Vector
  204. {
  205. fn sub(&self, other: &Vector) -> Vector
  206. {
  207. Vector { x : self.x - other.x, y : self.y - other.y, z : self.z - other. z}
  208. }
  209. }
  210. impl Add<Vector, Vector> for Vector
  211. {
  212. fn add(&self, other : &Vector) -> Vector
  213. {
  214. Vector { x : self.x + other.x, y : self.y + other.y, z : self.z + other.z }
  215. }
  216. }
  217. impl Mul<Rfloat, Vector> for Vector
  218. {
  219. fn mul(&self, s : &Rfloat) -> Vector
  220. {
  221. Vector { x : self.x * *s, y : self.y * *s, z : self.z * *s }
  222. }
  223. }
  224. impl fmt::Show for Vector {
  225. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  226. write!(f, "({}, {}, {})", self.x, self.y, self.z)
  227. }
  228. }
  229. struct Camera
  230. {
  231. forward : Vector,
  232. fov_scale : Rfloat,
  233. }
  234. struct Scene
  235. {
  236. objects : Vec<Sphere>,
  237. lights : Vec<uint>,
  238. camera : Box<Camera>,
  239. }
  240. impl Scene
  241. {
  242. fn intersect(&self, ray : &Ray) -> Option<(Rfloat, &Sphere)>
  243. {
  244. let mut result = None;
  245. let mut min_t = f64::MAX_VALUE;
  246. for sphere in self.objects.iter()
  247. {
  248. let t = sphere.intersects(ray);
  249. if t > 0.0 && t < min_t
  250. {
  251. min_t = t;
  252. result = Some((min_t, sphere));
  253. }
  254. }
  255. (result)
  256. }
  257. fn collect_lights(&mut self)
  258. {
  259. for (index, object) in self.objects.iter().enumerate()
  260. {
  261. if object.is_light()
  262. {
  263. self.lights.push(index);
  264. }
  265. }
  266. }
  267. }
  268. struct Context
  269. {
  270. scene : Box<Scene>,
  271. samples : [Rfloat, ..SPP * 2]
  272. }
  273. fn rand01<T:Rng>(rng : &mut T) -> Rfloat
  274. {
  275. (rng.gen::<Rfloat>())
  276. }
  277. // Given 1 axis, returns other 2
  278. fn build_basis(v1 : &Vector) -> (Vector, Vector)
  279. {
  280. let mut v2 = Vector::zero();
  281. if v1.x.abs() > v1.y.abs()
  282. {
  283. let oo_len = 1.0 / (v1.x * v1.x + v1.z * v1.z).sqrt();
  284. v2.set(-v1.z*oo_len, 0.0, v1.x*oo_len);
  285. }
  286. else
  287. {
  288. let oo_len = 1.0 / (v1.y * v1.y + v1.z * v1.z).sqrt();
  289. v2.set(0.0, v1.z*oo_len, -v1.y*oo_len);
  290. }
  291. (v2, cross(v1, &v2))
  292. }
  293. fn transform_to_basis(vin : &Vector, vx : &Vector, vy : &Vector, vz : &Vector) -> Vector
  294. {
  295. Vector
  296. {
  297. x : vx.x*vin.x + vy.x*vin.y + vz.x*vin.z,
  298. y : vx.y*vin.x + vy.y*vin.y + vz.y*vin.z,
  299. z : vx.z*vin.x + vy.z*vin.y + vz.z*vin.z
  300. }
  301. }
  302. fn reflect(dir : &Vector, n : &Vector) -> Vector
  303. {
  304. let h = *n * (dot(dir, n) * 2.0);
  305. return h - *dir;
  306. }
  307. fn initialize_samples<T:Rng>(samples : &mut [Rfloat, ..SPP * 2], rng : &mut T)
  308. {
  309. let xstrata = (SPP as Rfloat).sqrt();
  310. let ystrata = (SPP as Rfloat) / xstrata;
  311. let mut is = 0;
  312. for ystep in range(0u, ystrata as uint)
  313. {
  314. for xstep in range(0u, xstrata as uint)
  315. {
  316. let fx = ((xstep as Rfloat) + rand01(rng)) / xstrata;
  317. let fy = ((ystep as Rfloat) + rand01(rng)) / ystrata;
  318. samples[is] = fx;
  319. samples[is + 1] = fy;
  320. is += 2;
  321. }
  322. }
  323. }
  324. impl Context
  325. {
  326. fn initialize_samples(&mut self)
  327. {
  328. let mut rng = rand::task_rng();
  329. initialize_samples(&mut self.samples, &mut rng);
  330. }
  331. }
  332. fn sample_hemisphere_cosine(u1 : Rfloat, u2 : Rfloat) -> Vector
  333. {
  334. let phi = 2.0 * f64::consts::PI * u1;
  335. let r = u2.sqrt();
  336. let sx = phi.cos() * r;
  337. let sy = phi.sin() * r;
  338. (Vector{x : sx, y : sy, z : (1.0 - sx*sx - sy*sy).sqrt()})
  339. }
  340. fn sample_hemisphere_specular(u1 : Rfloat, u2 : Rfloat, exp : Rfloat) -> Vector
  341. {
  342. let phi = 2.0 * f64::consts::PI * u1;
  343. let cos_theta = (1.0 - u2).powf(1.0 / (exp + 1.0));
  344. let sin_theta = (1.0 - cos_theta*cos_theta).sqrt();
  345. Vector { x : phi.cos() * sin_theta, y: phi.sin() * sin_theta, z : cos_theta }
  346. }
  347. fn interreflect_diffuse(normal : &Vector, intersection_point : &Vector, u1 : Rfloat, u2 : Rfloat) -> Ray
  348. {
  349. let (v2, v3) = build_basis(normal);
  350. let sampled_dir = sample_hemisphere_cosine(u1, u2);
  351. let new_ray = Ray { origin : *intersection_point,
  352. dir : transform_to_basis(&sampled_dir, &v2, &v3, normal) };
  353. return new_ray;
  354. }
  355. fn interreflect_specular(normal : &Vector, intersection_point : &Vector, u1 : Rfloat, u2 : Rfloat, exp : Rfloat,
  356. new_ray : &mut Ray)
  357. {
  358. let view = new_ray.dir * -1.0;
  359. let mut reflected = reflect(&view, normal);
  360. reflected.normalize();
  361. let (v2, v3) = build_basis(&reflected);
  362. let sampled_dir = sample_hemisphere_specular(u1, u2, exp);
  363. new_ray.origin = *intersection_point;
  364. new_ray.dir = transform_to_basis(&sampled_dir, &v2, &v3, &reflected);
  365. }
  366. fn sample_lights(scene : &Box<Scene>, intersection : &Vector, normal : &Vector, ray_dir : &Vector, material : &Box<Material>) -> Vector
  367. {
  368. let mut color = Vector::zero();
  369. for light_index in scene.lights.iter()
  370. {
  371. let ref light = scene.objects[*light_index];
  372. let mut l = light.center - *intersection;
  373. let light_dist_sqr = dot(&l, &l);
  374. l.normalize();
  375. let mut d = dot(normal, &l);
  376. if d < 0.0
  377. {
  378. d = 0.0
  379. }
  380. let shadow_ray = Ray { origin : *intersection, dir : l };
  381. match scene.intersect(&shadow_ray)
  382. {
  383. None => {}
  384. Some((t, object)) =>
  385. {
  386. if object as *const Sphere == light as *const Sphere
  387. {
  388. let sin_alpha_max_sqr = light.radius_sqr / light_dist_sqr;
  389. let cos_alpha_max = (1.0 - sin_alpha_max_sqr).sqrt();
  390. let omega = 2.0 * (1.0 - cos_alpha_max);
  391. d *= omega;
  392. let c = material.diffuse.vecmul(&light.material.emissive);
  393. color = color + c * d;
  394. // Specular part
  395. match material.material_type
  396. {
  397. DIFFUSE => {}
  398. GLOSSY | MIRROR =>
  399. {
  400. let reflected = reflect(&l, normal);
  401. d = -dot(&reflected, ray_dir);
  402. if d < 0.0
  403. {
  404. d = 0.0;
  405. }
  406. let smul = d.powf(material.exp);
  407. let spec_color = material.specular * smul;
  408. color = color + spec_color;
  409. }
  410. }
  411. }
  412. }
  413. }
  414. }
  415. (color)
  416. }
  417. fn trace<T:Rng>(ray : &mut Ray, scene : &Box<Scene>, samples : &[Rfloat, ..SPP * 2], mut u1 : Rfloat, mut u2 : Rfloat, rng : &mut T) -> Vector
  418. {
  419. let mut result = Vector::zero();
  420. let mut rr_scale = Vector { x : 1.0, y : 1.0, z : 1.0 };
  421. let mut direct = true;
  422. for bounce in range(0, MAX_BOUNCES)
  423. {
  424. match scene.intersect(ray)
  425. {
  426. None => break,
  427. Some((t, object)) =>
  428. {
  429. let ref material = object.material;
  430. if direct
  431. {
  432. result = result + material.emissive.vecmul(&rr_scale);
  433. }
  434. let mut diffuse = material.diffuse;
  435. let max_diffuse = diffuse.max_component();
  436. if bounce > MIN_BOUNCES || max_diffuse < f64::EPSILON
  437. {
  438. if rand01(rng) > max_diffuse
  439. {
  440. break;
  441. }
  442. diffuse = diffuse * (1.0 / max_diffuse);
  443. }
  444. let intersection_point = ray.calc_intersection_point(t);
  445. let mut normal = (intersection_point - object.center) * (1.0 / object.radius);
  446. if dot(&normal, &ray.dir) >= 0.0
  447. {
  448. normal.negate();
  449. }
  450. match material.material_type
  451. {
  452. DIFFUSE =>
  453. {
  454. direct = false;
  455. let direct_light = rr_scale.vecmul(&sample_lights(scene, &intersection_point, &normal, &ray.dir, material));
  456. result = result + direct_light;
  457. *ray = interreflect_diffuse(&normal, &intersection_point, u1, u2);
  458. rr_scale = rr_scale.vecmul(&diffuse);
  459. }
  460. GLOSSY =>
  461. {
  462. direct = false;
  463. let direct_light = rr_scale.vecmul(&sample_lights(scene, &intersection_point, &normal, &ray.dir, material));
  464. result = result + direct_light;
  465. // Specular/diffuse Russian roulette
  466. let max_spec = material.specular.max_component();
  467. let p = max_spec / (max_spec + max_diffuse);
  468. let smult = 1.0 / p;
  469. if rand01(rng) > p // diffuse
  470. {
  471. *ray = interreflect_diffuse(&normal, &intersection_point, u1, u2);
  472. let color = diffuse * (1.0 / (1.0 - 1.0/smult));
  473. rr_scale = rr_scale.vecmul(&color);
  474. }
  475. else
  476. {
  477. interreflect_specular(&normal, &intersection_point, u1, u2, material.exp, ray);
  478. let color = material.specular * smult;
  479. rr_scale = rr_scale.vecmul(&color);
  480. }
  481. }
  482. MIRROR =>
  483. {
  484. let view = ray.dir * -1.0;
  485. let mut reflected = reflect(&view, &normal);
  486. reflected.normalize();
  487. ray.origin = intersection_point;
  488. ray.dir = reflected;
  489. rr_scale = rr_scale.vecmul(&diffuse);
  490. }
  491. }
  492. let sample_index = rng.gen_range(0u, SPP);
  493. u1 = samples[sample_index*2];
  494. u2 = samples[sample_index*2+1];
  495. }
  496. }
  497. }
  498. (result)
  499. }
  500. fn apply_tent_filter(samples : &mut [Rfloat, ..SPP * 2])
  501. {
  502. for i in range(0, SPP)
  503. {
  504. let x = samples[i*2+0];
  505. let y = samples[i*2+1];
  506. samples[i * 2] = match x {
  507. x if x < 0.5 => (2.0 * x).sqrt() - 1.0,
  508. _ => 1.0 - (2.0 - 2.0 * x).sqrt()
  509. };
  510. samples[i * 2 + 1] = match y {
  511. y if y < 0.5 => (2.0 * y).sqrt() - 1.0,
  512. _ => 1.0 - (2.0 - 2.0 * y).sqrt()
  513. };
  514. }
  515. }
  516. fn process_chunk(context : &Context, buffer : &mut [u8], offset : uint, chunk_size : uint)
  517. {
  518. let res = RESOLUTION as Rfloat;
  519. let camera = &context.scene.camera;
  520. let cx = Vector { x : camera.fov_scale, y : 0.0, z : 0.0 };
  521. let mut cy = cross(&cx, &camera.forward);
  522. cy.normalize();
  523. cy = cy * camera.fov_scale;
  524. let ray_origin = Vector { x : 50.0, y : 52.0, z : 295.6 };
  525. let mut chunk_samples = [0.0, ..SPP*2];
  526. let mut sphere_samples = [0.0, ..SPP*2];
  527. let mut rng = rand::task_rng();
  528. initialize_samples(&mut chunk_samples, &mut rng);
  529. apply_tent_filter(&mut chunk_samples);
  530. let inv_spp = 1.0 / SPP as Rfloat;
  531. let start_x = offset % RESOLUTION;
  532. let start_y = offset / RESOLUTION;
  533. let mut y = start_y;
  534. let mut x = start_x;
  535. let end_offset = chunk_size * 4;
  536. for pixel_offset in iter::range_step(0, end_offset, 4)
  537. {
  538. initialize_samples(&mut sphere_samples, &mut rng);
  539. let mut cr = Vector::zero();
  540. for aa in range(0u, NUM_AA)
  541. {
  542. let mut pr = Vector::zero();
  543. let aax = (aa & 0x1) as Rfloat;
  544. let aay = (aa >> 1) as Rfloat;
  545. for s in range(0, SPP)
  546. {
  547. let dx = chunk_samples[s * 2];
  548. let dy = chunk_samples[s * 2 + 1];
  549. let px = (((aax + 0.5 + dx) / 2.0) + (x as Rfloat)) / res - 0.5;
  550. let py = -((((aay + 0.5 + dy) / 2.0) + y as Rfloat) / res - 0.5);
  551. let ccx = cx * px;
  552. let ccy = cy * py;
  553. let mut ray_dir = ccx + ccy + camera.forward;
  554. ray_dir.normalize();
  555. let mut ray = Ray{ origin : ray_origin + ray_dir * 136.0, dir : ray_dir};
  556. let u1 = sphere_samples[s*2];
  557. let u2 = sphere_samples[s*2+1];
  558. let r = trace(&mut ray, &context.scene, &context.samples, u1, u2, &mut rng);
  559. pr = pr + (r * inv_spp);
  560. }
  561. cr = cr + (pr * INV_AA);
  562. }
  563. let (r, g, b) = cr.get_color();
  564. buffer[pixel_offset + 3] = 0xFF;
  565. buffer[pixel_offset + 0] = b as u8;
  566. buffer[pixel_offset + 1] = g as u8;
  567. buffer[pixel_offset + 2] = r as u8;
  568. x = x + 1;
  569. if x == RESOLUTION
  570. {
  571. x = 0;
  572. y = y + 1;
  573. }
  574. }
  575. }
  576. fn put16(buffer : &mut [u8], index : uint, v : u16)
  577. {
  578. buffer[index + 0] = (v & 0xFF) as u8;
  579. buffer[index + 1] = (v >> 8) as u8;
  580. }
  581. fn write_tga_header(f : &mut File, width : uint, height : uint)
  582. {
  583. let mut header : [u8, ..18] = [0, ..18];
  584. header[2] = 2; // 32-bit
  585. put16(header, 12, width as u16);
  586. put16(header, 14, height as u16);
  587. header[16] = 32; // BPP
  588. header[17] = 0x20; // top down, non interlaced
  589. f.write(header);
  590. }
  591. fn write_tga(fname : &Path, pixels : &[u8], width : uint, height : uint)
  592. {
  593. let mut file = match File::create(fname) {
  594. Ok(f) => f,
  595. Err(e) => panic!("file error: {}", e),
  596. };
  597. write_tga_header(&mut file, width, height);
  598. file.write(pixels);
  599. }
  600. fn main()
  601. {
  602. let fov_scale = (55.0 * f64::consts::PI / 180.0 * 0.5).tan();
  603. let camera = Camera{ forward : Vector::new_normal(0.0, -0.042612, -1.0), fov_scale: fov_scale };
  604. let diffuse_grey = Material{ material_type : DIFFUSE, diffuse : Vector::new(0.75, 0.75, 0.75), ..Material::default() };
  605. let diffuse_red = Material{ material_type: DIFFUSE, diffuse: Vector::new(0.95, 0.15, 0.15), ..Material::default() };
  606. let diffuse_blue = Material{ material_type: DIFFUSE, diffuse: Vector::new(0.25, 0.25, 0.7), ..Material::default() };
  607. let diffuse_black = Material{ material_type: DIFFUSE, ..Material::default() };
  608. let diffuse_green = Material{ material_type: DIFFUSE, diffuse: Vector::new(0.0, 0.55, 14.0/255.0), ..Material::default() };
  609. let diffuse_white = Material{ material_type: DIFFUSE, diffuse: Vector::new(0.99, 0.99, 0.99), ..Material::default() };
  610. let glossy_white = Material{ material_type: GLOSSY, diffuse: Vector::new(0.3, 0.05, 0.05),
  611. specular: Vector::new(0.69, 0.69, 0.69), exp: 45.0, emissive: Vector::zero() };
  612. let white_light = Material{ material_type: DIFFUSE, emissive: Vector::new(400.0, 400.0, 400.0), ..Material::default() };
  613. let mirror = Material{material_type: MIRROR, diffuse: Vector::new(0.999, 0.999, 0.999), ..Material::default() };
  614. let mut scene = Scene
  615. {
  616. objects: vec!{
  617. Sphere::new(1e5, Vector::new(1e5 + 1.0, 40.8, 81.6), box diffuse_red),
  618. Sphere::new(1e5, Vector::new(-1e5 + 99.0, 40.8, 81.6), box diffuse_blue),
  619. Sphere::new(1e5, Vector::new(50.0, 40.8, 1e5), box diffuse_grey),
  620. Sphere::new(1e5, Vector::new(50.0, 40.8, -1e5 + 170.0), box diffuse_black),
  621. Sphere::new(1e5, Vector::new(50.0, 1e5, 81.6), box diffuse_grey),
  622. Sphere::new(1e5, Vector::new(50.0, -1e5 + 81.6, 81.6), box diffuse_grey),
  623. Sphere::new(16.5, Vector::new(27.0, 16.5, 57.0), box mirror),
  624. Sphere::new(10.5, Vector::new(17.0, 10.5, 97.0), box diffuse_green),
  625. Sphere::new(16.5, Vector::new(76.0, 16.5, 78.0), box glossy_white),
  626. Sphere::new(8.5, Vector::new(82.0, 8.5, 108.0), box diffuse_white),
  627. Sphere::new(1.5, Vector::new(50.0, 81.6 - 16.5, 81.6), box white_light)
  628. },
  629. lights: vec!{},
  630. camera : box camera
  631. };
  632. scene.collect_lights();
  633. let start_time = precise_time_s();
  634. let mut context = Context { scene : box scene, samples : [0.0, ..SPP*2] };
  635. context.initialize_samples();
  636. // in pixels
  637. let chunk_size = 16u;
  638. let num_tasks = (RESOLUTION * RESOLUTION) / chunk_size;
  639. println!("Num tasks = {}", num_tasks);
  640. let granularity = chunk_size * 4;
  641. let mut framebuffer:Vec<u8> = Vec::from_elem(RESOLUTION * RESOLUTION * 4, 0);
  642. let mut pool = SchedPool::new(PoolConfig::new());
  643. let raw::Slice { data, len } = unsafe { mem::transmute::<_, raw::Slice<u8>>(framebuffer.as_mut_slice()) };
  644. let context_arc = Arc::new(context);
  645. println!("granularity: {}", granularity);
  646. let futures = iter::range_step(0, len, granularity).map(|offset|
  647. {
  648. let local_arc = context_arc.clone();
  649. TaskBuilder::new().green(&mut pool).try_future(proc()
  650. {
  651. let slice = raw::Slice {
  652. data: unsafe { data.offset(offset as int) },
  653. len: cmp::min(granularity, len - offset)
  654. };
  655. let data = unsafe { mem::transmute::<_, &mut [u8]>(slice) };
  656. let local_context = local_arc.deref();
  657. process_chunk(local_context, data, offset >> 2, chunk_size);
  658. })
  659. }).collect::<Vec<_>>();
  660. for f in futures.into_iter()
  661. {
  662. if f.unwrap().is_err()
  663. {
  664. panic!();
  665. }
  666. }
  667. let time_taken = precise_time_s() - start_time;
  668. println!("Tracing took {} seconds", time_taken);
  669. pool.shutdown();
  670. write_tga(&Path::new("trace.tga"), framebuffer.as_slice(), RESOLUTION, RESOLUTION);
  671. }