godotengine / godot-docs

Godot Engine official documentation
https://docs.godotengine.org
Other
3.91k stars 3.2k forks source link

Document Camera2D avoid Jitter in pixel perfect games #7774

Open WhalesState opened 1 year ago

WhalesState commented 1 year ago

Godot version

3.x and 4.x

System information

Windows 10

Issue description

I have found many opened issues about camera 2D jitter in pixel perfect games when enabling smoothing so I'm opening this to link all of them to get closed when this is fixed.

Fixing this may close: https://github.com/godotengine/godot/issues/73347 https://github.com/godotengine/godot/issues/71074 https://github.com/godotengine/godot/issues/54974 https://github.com/godotengine/godot/issues/48200 https://github.com/godotengine/godot/issues/46681 https://github.com/godotengine/godot/issues/26291 https://github.com/godotengine/godot/issues/64747 https://github.com/godotengine/godot/issues/48130

ways to fix this issue:

1- enable snapping options in project settings rendering/2d/snap/snap_2d_transforms_to_pixel later enables rendering/2d/snap/snap_2d_vertices_to_pixel if the first option doesn't solve the issue.

2- set a small drag margin in Camera2D to avoid jitter, it happens only when the Camera2d is about to reach it's desired location, for example moving from Vector2(0, 0) to Vector2(1, 0) with smoothing enabled will result in a jitter because the camera's x position will be a float between 0 and 1 while having a small drag margin will make you avoid this issue.

dalexeev commented 1 year ago

I have found many opened issues about camera 2D jitter in pixel perfect games when enabling smoothing

Note that the "smoothness" (uniformity) of movement depends on the movement speed of the character (and the camera, since it moves at the speed of the character). For example, if the speed is 100 pixels per second, then at FPS 60 the character will move on average 1.67 pixels per frame. But due to grid snapping, the character will move either by 1 pixel, or by 2, Which our eyes notice well. This is what creates the jittery movement. If you choose a different speed that is a divisor or multiple of FPS (e.g. 15, 30, 60, 120, 180), then the movement will look uniform as the character is constantly moving the same number of pixels per frame (multiple) or moving one pixel takes the same number of frames (divisor).

Camera smoothing is also subject to this principle. When accelerating or decelerating the camera, you may experience jittery movement when the speed is not a divisor or multiple of FPS. This is especially important for pixel perfect games due to the low resolution and large pixel grid. I believe that the problem is not so much in the specific camera implementation in Godot, but in the laws of nature (the mathematics of discrete processes and the physiology of human vision).

WhalesState commented 1 year ago

also because of the linear interpolation function used for camera smoothing, it appears to be fast when it starts to move to a far distance and slows down when it starts to reach it's target location because the distance keeps updating over time, that's why the jitter happens because the lerp distance becomes shorter over time and camera drag margins will make you avoid having linear interpolation when a and b are close to each others.

Calinou commented 1 year ago

I believe that the problem is not so much in the specific camera implementation in Godot, but in the laws of nature (the mathematics of discrete processes and the physiology of human vision).

This is something I noticed a lot (not just in Godot). If you make a pixel art game, you should be conservative on how much smoothing you use on the camera (and even the player movement itself). Otherwise, quantization artifacts will become obvious. Ease-out camera smoothing is good for HD games, but it's rarely a good idea for pixel art games for this reason.

If you look at most 90s pixel art games, very few of them use camera smoothing to such an extent as you see in modern games – and it's not for performance reasons. A lot of them mostly rely on linear camera movements, like this.

liloso123 commented 1 year ago

the only fix for it i found is to make sure that both rendering/2d/snap/snap_2d_transforms_to_pixel and rendering/2d/snap/snap_2d_vertices_to_pixel are turned off, that removes the jitter/stutter as it say on them that it makes the camera2d smoothing worse

ps. as i see it the problem is that those 2 options make the camera snap to the pixels and i cant see a reason why someone would ever want to snap the camera to the closest pixel

WhalesState commented 1 year ago

The limitation here is clear, we need everything in the game to snap to pixels except the Camera2D, maybe turning this option to a CanvasItem's property same as the Texture filter is better. But when the Camera2D snaps to pixels it makes you avoid Jitter, consider increasing the smooth value to 10 and use drag margins to see what happens.