godotengine / godotengine/godot

"Snap Controls to Pixel" only partially works

Open
#101,562 7 comments 0 reactions 0 assignees View on GitHub
bug topic:2d topic:editor
Dominant language
C++
Stars
117k
Forks
26.8k
PR merge metrics
PR metrics pending

Description

### Tested versions

v4.4.dev7.mono.official [46c8f8c5c]

### System information

Godot v4.4.dev7.mono - Windows 11 (build 22631) - Multi-window, 2 monitors - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 4070 Ti SUPER (NVIDIA; 32.0.15.6614) - 13th Gen Intel(R) Core(TM) i9-13900K (32 threads)

### Issue description

Snapping controls to pixels only works consistently for the position of the control, not its size.

I pasted a screenshot into Aseprite and zoomed to 25% (my game is scaled by 4x). It should look perfectly scaled, but the TextEdit and OptionButton nodes are blurry due to non-integer sizes:
![Image](https://github.com/user-attachments/assets/48fba4a4-5029-40c9-a1e1-f62788a0391f)

![Image](https://github.com/user-attachments/assets/4941a03f-97ee-4137-bf2c-dbcc03d1e71b)

Note that I had stretch mode set to CanvasItems for this screenshot (so the issue would be visible in Aseprite). Using Viewport stretching obviously renders at the correct pixel resolution, but causes other issues like the bottom row of pixels of some control nodes to occasionally be cut off.

In this screenshot, the first two control nodes have a height of 18.5, causing the bottom edge to blur. The first OptionButton has its text blurred due to the size, but the TextEdit at the top does not have this issue. The second OptionButton has a height of 19, which causes its text to render at a non-integer Y-position (9.5 offset from the top). The Position property of each node is snapped to an integer, but their sizes and internal nodes seem to ignore this.

### Steps to reproduce

In Project Settings:
- gui/common/snap_controls_to_pixels = On
- display/window/size/viewport_width = 640
- display/window/size/viewport_height = 360
- display/window/size/mode = Exclusive Fullscreen
- display/window/stretch/mode = viewport (for native pixel resolution, causes issues with rows of pixels being lost) or canvas_items (to test blurring when downscaling to viewport size)
- display/window/stretch/aspect = expand
- display/window/stretch/scale_mode = integer

### Minimal reproduction project (MRP)

N/A

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the issue with gui/common/snap_controls_to_pixels enabled and the listed viewport or canvas_items stretch settings. Search the implementation of that project setting and trace how Control sizes and internal content are positioned. Done means Control sizes and their rendered text or edges remain aligned to integer pixels without regressing the viewport-stretch behavior described.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, godot
Domain
game-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.