Added command-line argument to render an image cropped.
This commit is contained in:
parent
59555f67f9
commit
71c320d87c
30
src/main.rs
30
src/main.rs
|
@ -114,6 +114,21 @@ fn main() {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("crop")
|
||||||
|
.long("crop")
|
||||||
|
.value_name("X1 Y1 X2 Y2")
|
||||||
|
.help("Only render the image between pixel coordinates (X1, Y1) and (X2, Y2). Coordinates are zero-indexed and inclusive.")
|
||||||
|
.takes_value(true)
|
||||||
|
.number_of_values(4)
|
||||||
|
.validator(
|
||||||
|
|s| {
|
||||||
|
usize::from_str(&s)
|
||||||
|
.and(Ok(()))
|
||||||
|
.or(Err("must be four integers".to_string()))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("threads")
|
Arg::with_name("threads")
|
||||||
.short("t")
|
.short("t")
|
||||||
|
@ -170,6 +185,20 @@ fn main() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let crop = args.values_of("crop")
|
||||||
|
.map(
|
||||||
|
|mut vals| {
|
||||||
|
let coords = (u32::from_str(vals.next().unwrap()).unwrap(), u32::from_str(vals.next().unwrap()).unwrap(), u32::from_str(vals.next().unwrap()).unwrap(), u32::from_str(vals.next().unwrap()).unwrap());
|
||||||
|
if coords.0 > coords.2 {
|
||||||
|
panic!("Argument '--crop': X1 must be less than or equal to X2");
|
||||||
|
}
|
||||||
|
if coords.1 > coords.3 {
|
||||||
|
panic!("Argument '--crop': Y1 must be less than or equal to Y2");
|
||||||
|
}
|
||||||
|
coords
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// Parse data tree of scene file
|
// Parse data tree of scene file
|
||||||
println!(
|
println!(
|
||||||
"Parsing scene file...",
|
"Parsing scene file...",
|
||||||
|
@ -254,6 +283,7 @@ fn main() {
|
||||||
println!("Rendering scene with {} threads...", thread_count);
|
println!("Rendering scene with {} threads...", thread_count);
|
||||||
let (mut image, rstats) = r.render(
|
let (mut image, rstats) = r.render(
|
||||||
max_samples_per_bucket,
|
max_samples_per_bucket,
|
||||||
|
crop,
|
||||||
thread_count,
|
thread_count,
|
||||||
args.is_present("blender_output"),
|
args.is_present("blender_output"),
|
||||||
);
|
);
|
||||||
|
|
|
@ -68,7 +68,7 @@ impl RenderStats {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Renderer<'a> {
|
impl<'a> Renderer<'a> {
|
||||||
pub fn render(&self, max_samples_per_bucket: u32, thread_count: u32, do_blender_output: bool) -> (Image, RenderStats) {
|
pub fn render(&self, max_samples_per_bucket: u32, crop: Option<(u32, u32, u32, u32)>, thread_count: u32, do_blender_output: bool) -> (Image, RenderStats) {
|
||||||
let mut tpool = Pool::new(thread_count);
|
let mut tpool = Pool::new(thread_count);
|
||||||
|
|
||||||
let image = Image::new(self.resolution.0, self.resolution.1);
|
let image = Image::new(self.resolution.0, self.resolution.1);
|
||||||
|
@ -84,6 +84,18 @@ impl<'a> Renderer<'a> {
|
||||||
// For printing render progress
|
// For printing render progress
|
||||||
let pixels_rendered = Mutex::new(Cell::new(0));
|
let pixels_rendered = Mutex::new(Cell::new(0));
|
||||||
|
|
||||||
|
// Calculate dimensions and coordinates of what we're rendering. This
|
||||||
|
// accounts for cropping.
|
||||||
|
let (width, height, start_x, start_y) = if let Some((x1, y1, x2, y2)) = crop {
|
||||||
|
let x1 = min(x1 as usize, img_width - 1);
|
||||||
|
let y1 = min(y1 as usize, img_height - 1);
|
||||||
|
let x2 = min(x2 as usize, img_width - 1);
|
||||||
|
let y2 = min(y2 as usize, img_height - 1);
|
||||||
|
(x2 - x1 + 1, y2 - y1 + 1, x1, y1)
|
||||||
|
} else {
|
||||||
|
(img_width, img_height, 0, 0)
|
||||||
|
};
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
tpool.scoped(
|
tpool.scoped(
|
||||||
|scope| {
|
|scope| {
|
||||||
|
@ -92,9 +104,21 @@ impl<'a> Renderer<'a> {
|
||||||
let jq = &job_queue;
|
let jq = &job_queue;
|
||||||
let ajq = &all_jobs_queued;
|
let ajq = &all_jobs_queued;
|
||||||
let img = ℑ
|
let img = ℑ
|
||||||
let cstats = &collective_stats;
|
|
||||||
let pixrenref = &pixels_rendered;
|
let pixrenref = &pixels_rendered;
|
||||||
scope.execute(move || self.render_job(jq, ajq, img, cstats, pixrenref, do_blender_output));
|
let cstats = &collective_stats;
|
||||||
|
scope.execute(
|
||||||
|
move || {
|
||||||
|
self.render_job(
|
||||||
|
jq,
|
||||||
|
ajq,
|
||||||
|
img,
|
||||||
|
width * height,
|
||||||
|
pixrenref,
|
||||||
|
cstats,
|
||||||
|
do_blender_output,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print initial 0.00% progress
|
// Print initial 0.00% progress
|
||||||
|
@ -116,8 +140,8 @@ impl<'a> Renderer<'a> {
|
||||||
|
|
||||||
// Populate job queue
|
// Populate job queue
|
||||||
let bucket_n = {
|
let bucket_n = {
|
||||||
let bucket_count_x = ((img_width / bucket_w) + 1) as u32;
|
let bucket_count_x = ((width / bucket_w) + 1) as u32;
|
||||||
let bucket_count_y = ((img_height / bucket_h) + 1) as u32;
|
let bucket_count_y = ((height / bucket_h) + 1) as u32;
|
||||||
let larger = cmp::max(bucket_count_x, bucket_count_y);
|
let larger = cmp::max(bucket_count_x, bucket_count_y);
|
||||||
let pow2 = upper_power_of_two(larger);
|
let pow2 = upper_power_of_two(larger);
|
||||||
pow2 * pow2
|
pow2 * pow2
|
||||||
|
@ -127,21 +151,21 @@ impl<'a> Renderer<'a> {
|
||||||
|
|
||||||
let x = bx as usize * bucket_w;
|
let x = bx as usize * bucket_w;
|
||||||
let y = by as usize * bucket_h;
|
let y = by as usize * bucket_h;
|
||||||
let w = if img_width >= x {
|
let w = if width >= x {
|
||||||
min(bucket_w, img_width - x)
|
min(bucket_w, width - x)
|
||||||
} else {
|
} else {
|
||||||
bucket_w
|
bucket_w
|
||||||
};
|
};
|
||||||
let h = if img_height >= y {
|
let h = if height >= y {
|
||||||
min(bucket_h, img_height - y)
|
min(bucket_h, height - y)
|
||||||
} else {
|
} else {
|
||||||
bucket_h
|
bucket_h
|
||||||
};
|
};
|
||||||
if x < img_width && y < img_height && w > 0 && h > 0 {
|
if x < width && y < height && w > 0 && h > 0 {
|
||||||
job_queue.push(
|
job_queue.push(
|
||||||
BucketJob {
|
BucketJob {
|
||||||
x: x as u32,
|
x: (start_x + x) as u32,
|
||||||
y: y as u32,
|
y: (start_y + y) as u32,
|
||||||
w: w as u32,
|
w: w as u32,
|
||||||
h: h as u32,
|
h: h as u32,
|
||||||
}
|
}
|
||||||
|
@ -164,7 +188,7 @@ impl<'a> Renderer<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Waits for buckets in the job queue to render and renders them when available.
|
/// Waits for buckets in the job queue to render and renders them when available.
|
||||||
fn render_job(&self, job_queue: &MsQueue<BucketJob>, all_jobs_queued: &RwLock<bool>, image: &Image, collected_stats: &RwLock<RenderStats>, pixels_rendered: &Mutex<Cell<usize>>, do_blender_output: bool) {
|
fn render_job(&self, job_queue: &MsQueue<BucketJob>, all_jobs_queued: &RwLock<bool>, image: &Image, total_pixels: usize, pixels_rendered: &Mutex<Cell<usize>>, collected_stats: &RwLock<RenderStats>, do_blender_output: bool) {
|
||||||
let mut stats = RenderStats::new();
|
let mut stats = RenderStats::new();
|
||||||
let mut timer = Timer::new();
|
let mut timer = Timer::new();
|
||||||
let mut total_timer = Timer::new();
|
let mut total_timer = Timer::new();
|
||||||
|
@ -183,7 +207,6 @@ impl<'a> Renderer<'a> {
|
||||||
let max_y = self.resolution.1 as f32 / self.resolution.0 as f32;
|
let max_y = self.resolution.1 as f32 / self.resolution.0 as f32;
|
||||||
let x_extent = max_x - min_x;
|
let x_extent = max_x - min_x;
|
||||||
let y_extent = max_y - min_y;
|
let y_extent = max_y - min_y;
|
||||||
let total_pixels = self.resolution.0 * self.resolution.1;
|
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
'render_loop: loop {
|
'render_loop: loop {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user