fix(highway_3d): size Butterchurn output canvas buffer to fill the highway - #820
Conversation
📝 WalkthroughWalkthroughHighway 3D sizing now applies a capped device-pixel ratio once when initializing and resizing the Butterchurn canvas, renderer, and overlays. The plugin manifest version is updated from ChangesHighway 3D sizing
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
…ghway The 3D-highway Butterchurn background set only the output canvas CSS size and called setRendererSize(), but never sized the canvas DRAWING BUFFER (canvas.width/height). Butterchurn does not size the output canvas itself (renderToScreen viewports to the reported size into the default framebuffer), so the buffer stayed at the browser default 300x150 while the viewport was the full highway. Only the bottom-left ~300x150 of the pattern was drawn, then CSS-stretched across the whole highway -- zoomed, soft, and aspect-wrong, worse the larger the panel. Add _bcApplySize(cssW, cssH): set the drawing buffer to the device-pixel render size (round(css * min(DPR, 1.5))), confine every layer (canvas, backdrop, scrim, tint) to the highway rect, and report the same device px to setRendererSize so buffer == on-screen viewport. Seed the buffer at create and switch createVisualizer to pixelRatio:1, textureRatio:1 (DPR is now folded into the reported size, so buffer == viewport == internal texsize, no double-counting). render() and resize() both route through it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: ChrisBeWithYou <christian.a.cowan@gmail.com>
Rebased onto main; #823 already shipped 3.31.4 (per-panel camera), so this Butterchurn buffer-sizing fix advances to 3.31.5. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2adb2ca to
283d535
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@plugins/highway_3d/screen.js`:
- Around line 645-648: Update the sizing check near _bcApplySize to also detect
changes in the backing canvas dimensions, not only sz.w and sz.h or the device
pixel ratio. Reapply sizing when canvas.width or canvas.height differs from the
dimensions tracked by the control state, including changes made outside
renderer.resize(), and update those tracked values after applying the size.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 8dae0f2d-6919-4a84-9111-cb1f29472ee7
📒 Files selected for processing (2)
plugins/highway_3d/plugin.jsonplugins/highway_3d/screen.js
| const sz = sizeProvider && sizeProvider(); | ||
| if (sz && sz.w > 0 && sz.h > 0 && (sz.w !== ctrl.lastW || sz.h !== ctrl.lastH)) { | ||
| ctrl.lastW = sz.w; ctrl.lastH = sz.h; | ||
| const wpx = sz.w + 'px', hpx = sz.h + 'px'; | ||
| // Confine ALL layers to exactly the highway-canvas rect so the opaque | ||
| // backdrop can't bleed over the transport bar above the highway. | ||
| [ctrl.canvas, ctrl.backdrop, ctrl.scrim, ctrl.tint].forEach((el) => { | ||
| if (el) { el.style.width = wpx; el.style.height = hpx; el.style.right = 'auto'; el.style.bottom = 'auto'; } | ||
| }); | ||
| try { ctrl.viz.setRendererSize(sz.w, sz.h); } catch (e) {} | ||
| _bcApplySize(sz.w, sz.h); | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Reapply sizing when the DPR or backing buffer changes.
Line [647] only detects CSS-size changes. If devicePixelRatio changes, or another path modifies canvas.width/canvas.height while sz.w and sz.h remain unchanged, _bcApplySize() is skipped and Butterchurn keeps stale dimensions.
Proposed fix
const sz = sizeProvider && sizeProvider();
- if (sz && sz.w > 0 && sz.h > 0 && (sz.w !== ctrl.lastW || sz.h !== ctrl.lastH)) {
- _bcApplySize(sz.w, sz.h);
+ if (sz && sz.w > 0 && sz.h > 0) {
+ const ratio = Math.min(window.devicePixelRatio || 1, 1.5);
+ const bw = Math.max(1, Math.round(sz.w * ratio));
+ const bh = Math.max(1, Math.round(sz.h * ratio));
+ if (sz.w !== ctrl.lastW || sz.h !== ctrl.lastH ||
+ canvas.width !== bw || canvas.height !== bh) {
+ _bcApplySize(sz.w, sz.h);
+ }
}As per coding guidelines, re-run applySize() when the backing-store canvas size changes because the splitscreen plugin may bypass renderer.resize().
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const sz = sizeProvider && sizeProvider(); | |
| if (sz && sz.w > 0 && sz.h > 0 && (sz.w !== ctrl.lastW || sz.h !== ctrl.lastH)) { | |
| ctrl.lastW = sz.w; ctrl.lastH = sz.h; | |
| const wpx = sz.w + 'px', hpx = sz.h + 'px'; | |
| // Confine ALL layers to exactly the highway-canvas rect so the opaque | |
| // backdrop can't bleed over the transport bar above the highway. | |
| [ctrl.canvas, ctrl.backdrop, ctrl.scrim, ctrl.tint].forEach((el) => { | |
| if (el) { el.style.width = wpx; el.style.height = hpx; el.style.right = 'auto'; el.style.bottom = 'auto'; } | |
| }); | |
| try { ctrl.viz.setRendererSize(sz.w, sz.h); } catch (e) {} | |
| _bcApplySize(sz.w, sz.h); | |
| } | |
| const sz = sizeProvider && sizeProvider(); | |
| if (sz && sz.w > 0 && sz.h > 0) { | |
| const ratio = Math.min(window.devicePixelRatio || 1, 1.5); | |
| const bw = Math.max(1, Math.round(sz.w * ratio)); | |
| const bh = Math.max(1, Math.round(sz.h * ratio)); | |
| if (sz.w !== ctrl.lastW || sz.h !== ctrl.lastH || | |
| canvas.width !== bw || canvas.height !== bh) { | |
| _bcApplySize(sz.w, sz.h); | |
| } | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@plugins/highway_3d/screen.js` around lines 645 - 648, Update the sizing check
near _bcApplySize to also detect changes in the backing canvas dimensions, not
only sz.w and sz.h or the device pixel ratio. Reapply sizing when canvas.width
or canvas.height differs from the dimensions tracked by the control state,
including changes made outside renderer.resize(), and update those tracked
values after applying the size.
Source: Coding guidelines
The 3D-highway Butterchurn background sized only the output canvas CSS size and called
setRendererSize(), but never sized the canvas drawing buffer (canvas.width/height). Butterchurn does not size the output canvas itself — its on-screen pass viewports to the reported size into the default framebuffer — so the buffer stayed at the browser default 300×150 while the viewport was the full highway. Only the bottom-left ~300×150 of the pattern was drawn, then CSS-stretched across the whole highway: zoomed, soft, aspect-wrong, and worse the larger the panel.Fix
plugins/highway_3d/screen.js:_bcApplySize(cssW, cssH): sets the drawing buffer to the device-pixel render size (round(css × min(DPR, 1.5))), confines every layer (canvas / backdrop / scrim / tint) to the highway rect, and reports the same device px tosetRendererSizeso buffer == on-screen viewport == full fill.createVisualizertopixelRatio:1, textureRatio:1— DPR is now folded into the reported size, so buffer == viewport == internal texsize (no double-counting).render()andresize()both route through_bcApplySize.plugins/highway_3d/plugin.json: version3.31.3→3.31.4.Testing
No plugin unit tests exist; validated visually on the :8000 testbed (3D Highway → background style = Butterchurn) — pattern now fills the highway at correct aspect/sharpness across panel sizes. Tint/scrim/opacity background layers unchanged (still a deliberately subdued background).
🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Chores