Pixel-sized canvases: dpiscale 1 on every framebuffer allocation - #52
Open
mresnick67 wants to merge 2 commits into
Open
Pixel-sized canvases: dpiscale 1 on every framebuffer allocation#52mresnick67 wants to merge 2 commits into
mresnick67 wants to merge 2 commits into
Conversation
newCanvas defaults a canvas's dpiscale to the display's, and every width/height handed to these eight allocations is already in PIXELS -- so on a highdpi phone (iOS and Android both run with highdpi on, see the engine's conf.lua) each framebuffer came out density times larger per axis than asked for. At a 3x display the window-sized scene canvas is NINE times the screen's pixels, rendered in full -- geometry, sun shadows, water, the lot -- and then downsampled to a ninth of that at the composite. The mirror the water reads, both tilt-shift buffers, both DOF buffers, the HUD frost and the shadow map (1024 asked, 3072x3072 stored) all paid the same multiplier. TerrainAtlas and BattlePics already pass dpiscale = 1 for exactly this reason; this brings the remaining allocations under the same rule. Nothing about coordinates changes -- every caller works in the canvas's nominal units, which are what getDimensions() reports either way -- so desktops (dpiscale 1) are bit-identical, and phones render the pixels their screens can actually show. On an iPhone 16 Pro this is the difference between the mod visibly heating the device and not. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The 1.4.1 AA pass folds its supersampled canvas down into a target sized in display pixels, allocated on the same highdpi default as the rest -- so on a phone the fold's destination was itself density x too big per axis, and the supersample multiplied on top of that. Same one-line rule as the other eight sites. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Author
|
Pushed one more site: 1.4.1's new AntiAlias pass folds its supersampled canvas into a target sized in display pixels, allocated on the same highdpi default — so on a phone the fold's destination was itself density× too big per axis, with the supersample stacking on top. Same one-line rule as the rest; PR body updated to count nine sites. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
love.graphics.newCanvas(w, h)defaults the canvas's dpiscale to the display's, and every width/height handed to the mod's framebuffer allocations is already in pixels (getPixelDimensions, or sizes taken off such a canvas). On a highdpi phone — the engine's conf.lua turns highdpi on for both iOS and Android — each buffer therefore comes out density× larger per axis than asked for.At a 3× display that means:
sunTexel = 1/resassuming 1024).TerrainAtlasandBattlePicsalready passdpiscale = 1for exactly this reason (their comments describe the trap); this PR brings the remaining nine allocation sites under the same rule — including 1.4.1's newAntiAliasfold target, which sizes its destination in display pixels on the same default, so on a phone the supersample multiplied on top of the density multiplier.Why nothing visible changes
Every caller works in the canvas's nominal units, which are what
getDimensions()reports either way — so no coordinate anywhere moves. On desktops the display dpiscale is 1 and the change is a no-op by construction. On phones the buffers land at the size the code always believed they were, and the screen can't show the discarded pixels — the composite was already throwing 8/9 of them away.Effect
Tested on an iPhone 16 Pro (device) and the iOS Simulator: pixel-identical frames, and the device goes from visibly heating within minutes of free-roam voxel mode to staying comfortable — this one change is most of that difference. Android runs the same highdpi path (density ~2.6–3), so it should see the same win; I'd welcome a confirmation from someone with a device.
I have a couple of follow-ups sketched for phone-tier tuning (an internal render-scale option, mobile-flavored defaults) but kept this PR to the pure bug fix — happy to open an issue to discuss those separately.
🤖 Generated with Claude Code