Composition Settings: the Resolution line shows the frame size the renderer produces (#2167)

This commit is contained in:
Marco Arnulfo
2026-10-23 16:34:22 +02:00
parent c250150dbc
commit 24e61ce273
3 changed files with 15 additions and 12 deletions
+1 -3
View File
@@ -26,9 +26,7 @@ pub(crate) fn render<'g>(e: &mut Enc<'g>, r: &Renderer, comp_id: ItemId, t: Tick
return None;
}
let ctx = r.eval_ctx(comp_id, t)?;
let s = r.opts.scale;
let w = ((ctx.comp.width as f64 * s).round() as u32).max(1);
let h = ((ctx.comp.height as f64 * s).round() as u32).max(1);
let (w, h) = effectcraft_render::frame_size(ctx.comp.width, ctx.comp.height, r.opts.scale);
if r.depth() > 16 || !e.g.fits(w, h) {
return None;
}
+7 -2
View File
@@ -1000,8 +1000,7 @@ impl<'a> Renderer<'a> {
pub fn comp_frame_cpu(&self, comp_id: ItemId, t: Tick) -> Image {
let Some(comp) = self.project.comp(comp_id) else { return Image::new(1, 1) };
let s = self.opts.scale;
let w = ((comp.width as f64 * s).round() as u32).max(1);
let h = ((comp.height as f64 * s).round() as u32).max(1);
let (w, h) = frame_size(comp.width, comp.height, s);
// Region of interest on a comp with 3D layers: render the frame and crop it. A region
// reaching past the comp frame (the Extended Viewer) renders Classic 3D natively — the
// planes project through the offset camera — and Advanced 3D as the frame, padded.
@@ -2363,6 +2362,12 @@ pub fn extended_region(w: u32, h: u32, visible: [f64; 4], margin: f64) -> Option
Some([x0, y0, x1 - x0, y1 - y0])
}
/// The size of a `width` x `height` comp frame rendered at `scale` (both compositors, and the
/// frame size Composition Settings shows for a Resolution).
pub fn frame_size(width: u32, height: u32, scale: f64) -> (u32, u32) {
(((width as f64 * scale).round() as u32).max(1), ((height as f64 * scale).round() as u32).max(1))
}
pub fn render_frame(project: &Project, comp: ItemId, t: Tick, scale: f64) -> Image {
Renderer::new(project, &NoFootage, RenderOpts { scale, ..Default::default() }).comp_frame(comp, t)
}
+7 -7
View File
@@ -512,11 +512,10 @@ pub fn params(d: &CompDraft) -> serde_json::Value {
})
}
/// The frame size the comp renders at `res`: every n-th pixel, a partial one counted (Auto
/// follows the magnification, so the dialog shows the full frame for it).
/// The frame size the comp renders at `res` (Auto follows the magnification, so the dialog shows
/// the full frame for it).
pub fn frame_at(w: u32, h: u32, res: Resolution) -> (u32, u32) {
let n = u32::from(res.factor().unwrap_or(1).max(1));
(w.div_ceil(n), h.div_ceil(n))
effectcraft_render::frame_size(w, h, 1.0 / f64::from(res.factor().unwrap_or(1).max(1)))
}
#[cfg(test)]
@@ -525,9 +524,10 @@ mod tests {
#[test]
fn frame_size_follows_the_resolution() {
assert_eq!(frame_at(1920, 1081, Resolution::Half), (960, 541), "an odd side keeps its last pixel");
assert_eq!(frame_at(1920, 1080, Resolution::Third), (640, 360));
assert_eq!(frame_at(1920, 1080, Resolution::Custom(7)), (275, 155));
// The renderer's size, which rounds: 1081 / 3 = 360.33 and 1920 / 7 = 274.3.
assert_eq!(frame_at(1920, 1081, Resolution::Third), (640, 360));
assert_eq!(frame_at(1920, 1080, Resolution::Custom(7)), (274, 154));
assert_eq!(frame_at(1920, 1081, Resolution::Half), (960, 541));
assert_eq!(frame_at(1920, 1080, Resolution::Full), (1920, 1080));
assert_eq!(frame_at(1920, 1080, Resolution::Auto), (1920, 1080));
}