From 24e61ce27345101121d0ff02ffd79be01e7a9bc9 Mon Sep 17 00:00:00 2001 From: Marco Arnulfo Date: Fri, 23 Oct 2026 16:34:22 +0200 Subject: [PATCH] Composition Settings: the Resolution line shows the frame size the renderer produces (#2167) --- crates/gpu/src/walk.rs | 4 +--- crates/render/src/lib.rs | 9 +++++++-- crates/ui-egui/src/panels/comp_settings.rs | 14 +++++++------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/crates/gpu/src/walk.rs b/crates/gpu/src/walk.rs index b1209070..7b07fb42 100644 --- a/crates/gpu/src/walk.rs +++ b/crates/gpu/src/walk.rs @@ -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; } diff --git a/crates/render/src/lib.rs b/crates/render/src/lib.rs index eccaed2f..2dbbe7dc 100644 --- a/crates/render/src/lib.rs +++ b/crates/render/src/lib.rs @@ -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) } diff --git a/crates/ui-egui/src/panels/comp_settings.rs b/crates/ui-egui/src/panels/comp_settings.rs index e4e406e9..7e676bcc 100644 --- a/crates/ui-egui/src/panels/comp_settings.rs +++ b/crates/ui-egui/src/panels/comp_settings.rs @@ -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)); }