-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
2D Camera viewport rounding error with subpixel position of 0.5 with "Snap 2D Transforms to Pixel" enabled #93712
Comments
@alvinhochun That's good call out! Let me make the change real quick and see if it fixes your issue. Edit: Yep! Seems to fix the issue. Though maybe we should make an MRP with a scene that better shows why this is an issue. |
I'm not sure I get what you mean? The correct behaviour should be that the red and green squares always completely overlap with each other. Your screenshot is even more broken (on beta2 there is no offset at x > 80). |
Oh interesting. With your suggested change of I was saying this MRP is good for measuring the issue, but I personally would like to see an example of a scene where this is obviously problematic behavior. I think this stems more from the fact that the camera's position isn't automatically rounded as well. Up until now, I've just always just had my camera scripts have a |
Yeah, my comment over at #87297 (comment) stemmed from me checking this issue. While these two issues are linked in some way (changing the pixel snapping may affect how the camera is or should be rounded) the root causes are likely not the same. What puzzled me with this issue is how the rounding difference only exists between 0 and half viewport size on each axis. It stops appearing at x > 80 and y > 60 for the viewport size 160 x 120, and doesn't happen with any negative coordinates, which doesn't quite make sense to me yet. |
IIRC, this was planned as a two-step change, since the camera has never floored/rounded its position, but |
Hmm, looking at it I don't know how the camera should even be rounded if we want Godot to do it automatically. What happens if the camera is zoomed in/out? What if the offset is not integral? What if it is rotated? Okay, let's just say hypothetically we somehow determine the camera should snap to pixel, should it be done based on the top-left corner of the final viewport rect, or the position of the Node2D? Speaking of position, do you know that You can try this: Add a Node2D and set its X to 0.6, then add a Sprite (or a Polygon) as a child and set its X also to 0.6. It's global X position should be 1.2, which would normally round to 1, but you can see it's actually snapped to X=2. This is because each canvas item snaps to pixels relative to its parent, not globally. The parent Node2D is snapped to X=1, the child is snapped to X=1, so its global position after snapping is 1 + 1 = 2. So, to calculate the accurate camera position from a node, one needs to walk the parent chain, round the local position one by one, adjust for any transforms and accumulate the result. Oops, that was a bit random. |
After a bit more digging, I think I understand the cause of this rounding error (disregarding rounding of the camera itself). It has to do with the top-level viewport transform. Consider the case of the red square and camera being at x=0.5:
So, I believe the fix is to readd the viewport transform rounding removed in #87297, but using I don't know if we should still consider rounding the camera, since it appears to be more involved per my previous comment. Maybe we should track that in yet another separate issue? |
I don't know the exact root cause, but while I was developing a game for the GBJam, where the viewport is 160x144 and everything should be snapped to pixels, I noticed that the character sometimes jitters (but only when moving in Y direction), when walking along a drag limit. I fixed it by moving the Camera2D node outside the character node and adding: extends Camera2D
class_name TrackingCamera2D
var target:Player
func _process(delta: float) -> void:
// set the cameras position to the current player
global_position = round(target.global_position) Edit: |
Tested versions
System information
Godot v4.3.beta2 - Windows 10.0.19045
Issue description
With
rendering/2d/snap/snap_2d_transforms_to_pixel
enabled, a 2D camera following an object positioned at a subpixel value of 0.5 when position is between 0 and half viewport size.Steps to reproduce
Screenshots
Minimal reproduction project (MRP)
camera-pixel-rounding-bug.zip
The text was updated successfully, but these errors were encountered: