Skip to content

Instantly share code, notes, and snippets.

@Nyrox
Created September 27, 2018 20:36
Show Gist options
  • Save Nyrox/219079203a88cbd4dac811b73fc003d2 to your computer and use it in GitHub Desktop.
Save Nyrox/219079203a88cbd4dac811b73fc003d2 to your computer and use it in GitHub Desktop.
pub fn render_tiled(scene: Scene, settings: Settings) -> TaskHandle {
let queue = Arc::new(MsQueue::new());
let (sender, receiver) = mpsc::channel();
// Split the backbuffer into tiles and push them into the queue
{
let mut x = 0;
let mut y = 0;
'gen_tiles: loop {
let tile_min = (x, y);
let tile_max = (
(x + settings.tile_size.0).min(settings.camera_settings.backbuffer_width - 1),
(y + settings.tile_size.1).min(settings.camera_settings.backbuffer_height - 1),
);
let width = tile_max.0 - tile_min.0;
let height = tile_max.1 - tile_min.1;
queue.push(super::Tile {
sample_count: 0,
left: tile_min.0,
top: tile_min.1,
width,
height,
data: vec![Vector3::new(0.0, 0.0, 0.0); width * height],
});
y += settings.tile_size.1;
if y >= settings.camera_settings.backbuffer_height {
y = 0;
x += settings.tile_size.0;
}
if x >= settings.camera_settings.backbuffer_width {
break 'gen_tiles;
}
}
}
for _ in 0..settings.worker_count {
let queue = queue.clone();
let sender = sender.clone();
// We clone both our scene and settings
// This simplifies implementation
let context = TraceContext {
scene: scene.clone(),
settings: settings.clone(),
};
thread::spawn(move || loop {
let mut tile = queue.try_pop()?;
for y in tile.top..(tile.top + tile.height) {
for x in tile.left..(tile.left + tile.width) {
let primary = generate_primary_ray(x, y, &context.settings.camera_settings);
let sample = trace(primary, &context, 1);
// Map the global pixel indices to the local tile buffer and store the sample
tile.data[(x - tile.left) + (y - tile.top) * tile.width] += sample;
}
}
tile.sample_count += 1;
// Check if we are done
if tile.sample_count == context.settings.sample_count {
sender.send(Message::TileFinished(tile)).unwrap();
return Some(());
}
// Check if we want to send our tile down the pipe
if context.settings.samples_per_iteration != 0
&& tile.sample_count % context.settings.samples_per_iteration == 0
{
sender.send(Message::TileProgressed(tile.clone())).unwrap();
}
queue.push(tile);
});
}
return TaskHandle { receiver, settings };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment