A year later, I still don’t get Godot’s scaling… Why does it do this?
I’ve kind of just been ignoring this while working on other aspects of my game, but even a year later I STILL don’t understand why Godot has this weird scaling issue ONLY when the viewport X and/or Y is anodd number. When it’s an even number it’s fine, but when it’s odd, you get doubled or missing pixels, even at 1x zoom. Often there is a diagonal shearing too.
Why does it do that?
(The built-in integer scaling on the project settings page doesn’t have this problem, but then Godot will do bland black letterboxing instead of expanding to show the pretty border I placed around the camera.)
SOLVED! I fixed it myself after realizing it was because the camera is in the middle of a pixel on odd-numbered dimensions. I fixed it by checking for odd dimensions every time the window is resized and offsetting the camera by 0.5 pixels for that dimension. No more doubled or invisible pixels!
update 1: Actually, rather than 0.5, use 1 divided by the current integer scaling level (1, 2, 3, etc.), otherwise it won’t work for odd numbered dimensions after integer scaling once.
update 2: Oops, more like offset by 1/(n+1), where n is the current integer scale, but you get the idea.
update 3: Actually, just simply offsetting by 0.1 seems to always work for now. The 1/(n+1) incidentally works too, but is the result of me messing around and quickly posting a working solution because I was excited to finally fix it.
update 4: Okay this is weird, I tried running my un-fixed code on my brother’s computer, and even without off-setting the camera, and it just… works? Without any issue whatsoever. I have no idea why it is giving me doubled pixels on odd-numbered dimensions and not my brother, maybe was a problem with my GPU the whole time or something (I have an AMD GPU, and he has NVIDIA)?
After messing around with some visual aids in GIMP and doing some math, it seems like the perfect offset is 1/(2 x n), where n is the current integer scale (x1, x2, x3, etc.). The reason an offset of 0.5 doesn’t work at 2x scale is because you’re just ending up in the middle of a pixel again since we’re not account for the fact that each “logical” pixel is 2x2 “real” pixels. The offset needs to be 0.25, which 1/(2 x 2) gives you. For 3x scale, you get 0.166… and so on. At least, I think I have that right. It works for me in any case.