From 7a0e08129f43cb7d9fc86f1ad5ad21154bac03f7 Mon Sep 17 00:00:00 2001 From: ramox81 <184937705+ramox81@users.noreply.github.com> Date: Mon, 12 Oct 2026 12:04:52 +0300 Subject: [PATCH] Draw a centred image background at its pixel size An image background not fitted to the screen keeps its own pixel size (times its scale), centred on the viewport and moved by its offset, as the reference draws it; tiling repeats it from there. Co-Authored-By: Claude Opus 5.5 --- src/scene/view/render.rs | 6 ++++-- src/shaders/background.wgsl | 8 ++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/scene/view/render.rs b/src/scene/view/render.rs index e2e4d301b..c1e80b531 100644 --- a/src/scene/view/render.rs +++ b/src/scene/view/render.rs @@ -3009,11 +3009,13 @@ impl Scene { background.use_tiling as u8 as f32, image.width as f32 / image.height.max(1) as f32, ]; + // Offset, then the image's size in pixels at its scale: + // an image not fitted to the screen keeps its pixel size. result.image_transform = [ background.offset.x as f32, background.offset.y as f32, - background.scale.x as f32, - background.scale.y as f32, + background.scale.x as f32 * image.width as f32, + background.scale.y as f32 * image.height as f32, ]; result.params[0] = 4.0; result.image = Some(image); diff --git a/src/shaders/background.wgsl b/src/shaders/background.wgsl index c99da6201..25a004c50 100644 --- a/src/shaders/background.wgsl +++ b/src/shaders/background.wgsl @@ -81,8 +81,12 @@ fn equirect_uv(ndc: vec2, rotation: f32) -> vec2 { fn image_uv(source_uv: vec2) -> vec2 { var uv = source_uv; if u.background_image_params.x < 0.5 { - uv = (source_uv - u.background_image_transform.xy) - / max(abs(u.background_image_transform.zw), vec2(1e-6)); + // Not fitted: the image at its own pixel size (times its scale), + // centred on the viewport and moved by its offset. + let pixel = (source_uv - vec2(0.5)) * max(u.viewport_size, vec2(1.0)); + uv = pixel / max(abs(u.background_image_transform.zw), vec2(1e-6)) + + vec2(0.5) - u.background_image_transform.xy; + return select(uv, fract(uv), u.background_image_params.z > 0.5); } if u.background_image_params.y > 0.5 { let image_aspect = max(u.background_image_params.w, 1e-6);