Skip to content
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

Vulkan: 2D Pixel Snap not working #56793

Closed
markdibarry opened this issue Jan 14, 2022 · 10 comments · Fixed by #87297
Closed

Vulkan: 2D Pixel Snap not working #56793

markdibarry opened this issue Jan 14, 2022 · 10 comments · Fixed by #87297

Comments

@markdibarry
Copy link
Contributor

Godot version

4.0dev (ce6de71)

System information

Windows 10, NVIDIA GeForce GTX 960

Issue description

I've seen other issues like this but they're all closed as fixed. I'm still having this issue. Pixels are not snapping correctly with either or both pixel snap options.
1 pixel gap in between collisions.

Steps to reproduce

Create a project with a floor and characterbody2d with basic movement functions, gravity, etc.
Set display stretch mode to viewport and keep.
Enable Snap 2d Transforms to Pixel or Snap 2d Vertices to Pixel or both.

image

Minimal reproduction project

PixelSnapBug.zip

@Calinou Calinou added this to the 4.0 milestone Jan 14, 2022
@Calinou Calinou changed the title Pixel-Snap not working Vulkan: 2D Pixel Snap not working Jan 14, 2022
@Calinou
Copy link
Member

Calinou commented Jan 25, 2022

Related to #55006.

@AttackButton
Copy link
Contributor

AttackButton commented Jan 27, 2022

Related to #55006.

Interesting enough the smooth addon https://github.com/lawnjelly/smoothing-addon was the only thing that completely fixed all these types of issues and jitterings in 3.x.

I'm having jittering issues again in 4.0 alpha 1, @lawnjelly any chance this being implemented by default on master too?

I'm working on a 2D platformer. Thanks for the work with this addon, @Calinou and @lawnjelly.

@lawnjelly
Copy link
Member

I'm having jittering issues again in 4.0 alpha 1, @lawnjelly any chance this being implemented by default on master too?

We are currently adding fixed timestep interpolation (what the addon does) to core.
See #52846 for 3D in 3.x.
My plan is once 3D is merged and any bugs worked out, I'll then do 2D, then port to 4.x.

@svendixon
Copy link

svendixon commented Mar 25, 2023

It's been a while, hopefully this is on someone's plate.

If Snap 2D Transform to Pixel or Snap 2D Vertices to Pixel or Both are set to true you will get those gaps. I'd also like to point out that if they are set to false sprites will get distorted and sprite atlases (with no padding) will also bleed as well when in motion (in the bellow example, this happens while moving in the y "jumping" since the sprite atlas has no padding at the bottom).

pp_false pp_true pp_bleed

A typical sprite atlas with no padding at the bottom
player

So unlike Godot 3.x, this means at the moment Godot 4 has no solution for pixel perfect games. Hopefully it can be resolved soon. I am including a zip of this example project.
PixelPerfect.zip

@svendixon
Copy link

I did a search for "is_snap_2d_transforms_to_pixel_enabled" and noticed that in sprite_2d.cpp it does a floor(), should this be a round() instead? For example if the value is 12.9999 you want it to be 13 not 12 no?

I don't know how this will effect collisions for anything though since these are just sprite_2d and animated_sprite_2d. But this might fix an issue I had with odd number sized sprites? I had to give all odd number sized sprites a -0.5 offset.

Line 102

if (get_viewport() && get_viewport()->is_snap_2d_transforms_to_pixel_enabled()) {
    dest_offset = dest_offset.floor();
}

Line 358

if (get_viewport() && get_viewport()->is_snap_2d_transforms_to_pixel_enabled()) {
    ofs = ofs.floor();
}

And in animated_sprite_2d.cpp.

Line 270

if (get_viewport() && get_viewport()->is_snap_2d_transforms_to_pixel_enabled()) {
    ofs = ofs.floor();
}

I'm not a programmer and I don't know the inner workings of Godot so if I'm completely off base here, feel free to ignore this.

@huedev
Copy link

huedev commented Jul 7, 2023

Are there any good workarounds to avoid this issue? With Godot 4.1 released and this issue still unresolved, it's challenging to work on pixel-perfect games right now, with seemingly no fix in sight.

Edit: I was able to implement a pretty simple workaround, kind of similar to what @svendixon observed. On the _process() function of any Sprite2D or AnimatedSprite2D nodes, I've added the following line to round the coordinates of the sprite while leaving the actual position of the parent node untouched:
global_position = get_parent().global_position.round()

This appears to resolve the issue on my end, as I'm no longer seeing sprites being offset and also no longer seeing neighboring pixels on thespritesheet bleeding through. I understand that this might not work for everyone, as it seems that this is a pretty complex issue to resolve for all use cases.

@markdibarry
Copy link
Contributor Author

markdibarry commented Dec 29, 2023

@huedev You can do as you said, however, if your movement code doesn't work with integers, until 2D Pixel Snap is actually fixed, you should do this:

var float_position = 0

func _ready():
    float_position = global_position

func _physics_process(delta):
    global_position = float_position

    #your movement code here

    float_position = global_position
    global_position = global_position.round()

Unfortunately, you'd have to add this code to anything in your game that moves, but it does work.

@huedev
Copy link

huedev commented Jan 16, 2024

@markdibarry Finally had a chance to try this out, it seems to be working well! Since I'm using type hints I had to modify the initial value of float_position from 0 to Vector2.ZERO. Thanks for playing around with this and sharing your fix!

@markdibarry
Copy link
Contributor Author

Fixed by #87297

@berarma
Copy link
Contributor

berarma commented Apr 5, 2024

I have this issue and fixed it applying the workaround in #56793 (comment). Now I've tried Godot 4.3-dev5 that I've read should fix it but the workaround is still required. Nothing has changed.

I've tried to open the test project to see how it works but it gives many errors that I'm unable to fix.

I'm also overriding _post_process_key_value as a fast way to fix the position for sprites moved with an AnimationPlayer. This workaround is also still required with the latest snapshot.

Edit: Sorry, I forgot I was using a Subviewport and had to enable "snap to pixel" there. Still, without the workarounds mentioned I have some jitter of the player (CharacterBody2D) on a moving platform (AnimatableBody2D), while with the workarounds there's no jitter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment