-
-
Notifications
You must be signed in to change notification settings - Fork 21.3k
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 Sprite "jittering", very noticeable when using camera smoothing #35606
Comments
Seems to me like the camera itself isn't respecting the pixel snap setting. |
The issue happens regardless of whether Pixel Snap is enabled or not. |
The tilemap is one cohesive unit so it does jitter, but individual tiles within might not. I tried this right now with multiple tilemap layers, background and foreground, and that way you can really see them jitter too. Since pixel snap doesn't seem to affect the camera, it's position.x can be something like 10.375940 and relative to this position one object that's pixel snapped might get it's position rounded up to the nearest pixel, while another one's gets rounded down. At least that's my interpretation of what's happening. |
I tried looking at the edge of the screen during scrolling, and I was not able to spot any jittering on the background itself relative to the edge. Shouldn't it be possible to see it jitter if comparing it to the edge? In my example project the background and foreground actually are two separate tilemaps (although they use the same tileset), and I've never been able to spot any jittering between them. Maybe pixel snap works differently than I thought, but I would have thought that if this was caused by pixel snapping, it would stop happening when Pixel Snap was turned off?
My first thought was also that it was caused by some sort of weird inconsistent rounding of pixel coordinates. Basically, some sort of rounding being applied somewhere that's either RNG or just inconsistent in that sometimes higher values get rounded down instead of up. I couldn't find anything obvious when poking around in the source code though. |
Not saying pixel snap is the cause, rather it doesn't really do anything. I messed with the 2D isometric demo a bit, you can really see the jitter between walls and pillars and the floor tiles in this. |
Ah, yes. There's definitely some jittering going on there. I wonder why I'm only seeing it with the sprites in my game. |
I've not done any 2D stuff with Godot but it looks like the problem is something like this : your character sprite position is not snapped relative to your background. i.e. if snapping is every 1.0 in units, and your background is at position 4.0, and your sprite is at 6.7: At camera position 2.0(assuming we are using a floor function to snap, but same will happen with round) at camera position 1.6background = 4.0 - 1.6 = 2.4 = 2 Thus as the camera moves you are getting relative movement between the two by 1 pixel. The solution is to snap the background and the sprite positions relative to each other. |
Pixel snap should be handling this, shouldn't it? If for example you put this in the camera's _process function: |
I tried manually .floor()-ing the positions of the camera and sprite in various gdscript handlers yesterday, and so far I haven't found anything that actually fixes the jitter. Maybe I could try implementing a custom camera that just sets the underlying render position directly (pretty sure I saw some way to do that somewhere, but I forget what it's called) and .floor()s it. Will definitely try that later. If that fixes it, this kinda seems like something that should just be done automatically by default. I can't think of any reason you'd ever actually want objects arbitrarily jittering relative to each other during scrolling. |
Did you try without camera smoothing enabled? Otherwise the smoothing happens after your script and turns the camera position into a float again. my scene tree is ordered like this:
This way the camera gets the player position after the player moved.
This should work. |
Ok I downloaded your demo project and got it working:
to
Obviously you'll want to tweak it a bit but the general idea is this .. to separate the physics representation (kinematic) from the visual representation. The physics rep can have float coordinates, but the visual representation should be floored or rounded to whole numbers. With this working, there will always be an integer relative relationship between the background and the sprites, and you won't get this jitter. |
I don't remember if I tried rounding the camera position with smoothing turned off, but the jitter is present without smoothing. It's just more noticeable when smoothing is enabled.
I'll try that when I have the opportunity, although I'll probably still have to either implement a custom camera or just implement custom smoothing on the existing one.
I'll try this as well when I have the opportunity, but wouldn't rounding the position set to the viewport's canvas_transform (I believe this is what Camera2D sets internally?) also fix the issue? |
I'm not sure exactly what you mean, but it may be possible to achieve the same math effect via a slightly different mechanism (again, I am not familiar with 2D). But once you have a moving camera, snapping positions to pixels on the screen no longer works because you will get this jiggling, you need to snap relative to the SCENE. |
I don't use Camera smoothing with pixelart for that reason. Which is a shame, because if it wasn't for this issue, there would be no reason not to use smoothing. |
I can confirm that this fixes the jitter, although it makes the built-in smoothing unusable, so I'll have to reimplement that manually.
This does fix the jitter for the player, but would have to be implemented separately for every sprite, making it rather impractical. Ultimately, this is the solution (or workaround) I arrived at:
It's a combination of Seel's suggestion with a custom reimplementation of camera smoothing based on one I created in a MonoGame-based engine years ago. This completely fixes the issue for all sprites without having to do anything specific in each sprite, while still having a nice smooth camera. This still seems like something Camera2D should be doing internally by default though, as I can't imagine the current behavior ever being desirable. |
It seems Camera2D currently doesn't have specific code to handle the Use Pixel Snap project setting. It makes sense to also snap the camera's coordinates when that setting is enabled. Someone should try to modify |
Agree, the simple camera snapping may be good enough in this case 👍. The snapping per sprite works with the more general case, because it allows things like variable size pixel blocks (e.g. 1 sprite pixel is 4x4 on screen), and zooming, non-snapped camera etc. But it may be overkill in this situation, and could of course be custom implemented in a game that needed this. |
I made a pull request that rounds the Camera2D origin to nearest pixel before setting the canvas transform. This fixes the jittering without any special camera script. Not sure if it's implemented in the most idiomatic way possible, but it seems to work at least. |
The reason that smoothing and custom camera scripts seem to increase jitter is because camera parent node will always be aligned to camera perfectly, if smoothing is disabled. Camera parent is usually player node, so player and background will draw fine, if smoothing is disabled. Other nodes with non-rounded positions will still jitter. If pixel snap in editor is used for backgrounds / non-moving sprites, you will only see jitter for moving sprites. @forbjok commit seems to fix the issue for all cases. Very clever indeed! I was using a gdscript workaround hack for this. |
One fix for this that worked for me, when pixel snap and such did not, was setting the Camera's update mode in the inspector from Idle to Physics. Completely removed the jitter |
I figured out a way to fix the jitter completely from gdscript, by coding a custom camera. I do this as a final step on my camera transform:
To port this to the default camera, the position should be Snapped by the zoom value, instead of Vector2(1.0, 1.0) / rounding! Simple as that. |
is this the same bug? https://godotengine.org/qa/78937/remove-render-jitter-artifacts-from-moving-camera The strategies laid out in this issue didn't work for me. |
I am also having trouble with this... unfortunately the workarounds mentioned here didn't do it for me. There is still jittering. When I implement the code solution above my player character starts vibrating, jittering in very quick succession. Any other ideas? |
Hi, how you fix that problem I have the same when player stop it jitting, I dont know how to fix it at this time. v3.2.3 |
@SyliawDeV It'll be corrected when you download the next Godot version including the pull request that fixes the bug :-) |
oh maybe v3.2.4 stable, I check beta version everyday but not seem it fix or not. But hear u say that I can wait for new version. :) |
@SyliawDeV #41535 hasn't been merged yet, so it won't be in 3.2.4 if it's not merged by the time 3.2.4 is released. |
Hm, dont know how other people do with that. |
@Calinou @SyliawDeV I'll try to add the required project setting and test it this weekend so it can be merged in the next revision. |
You just warm me from freeze. 🤩 |
-Rename pixel_snap to snap_2d_to_vertices -Added snap_2d_to_transforms which is more useful Fixes godotengine#41814 Solves proposal godotengine/godot-proposals#1666 Supersedes godotengine#35606, supersedes godotengine#41535, supersedes godotengine#41534
Many users have problems with camera2D lag in Godot. I spent a lot of time on project settings. Used all camera setup options. Tried to fix the delays with code. It was all unsuccessful. Godot has long had problems with this, and they are not corrected. The only thought I came up with was to use Unity. It's a pity, but until this problem is solved, it makes no sense to use the Godot engine. |
@Grizzly-pride Before my fix was pulled there was one 3.x version released including it. You could always give it a try to see if that would fix your problems; it certainly did for me. I'm willing to give this a try again at some point because it's a deal-breaker for too many people, myself included. I've already seen people remake projects in Unity because the customers didn't like the objects and the maps not being in sync, and that's a pity because if someone spends time to learn Godot and has to switch to Unity it's going to be difficult to convince them to take the step back because of fear of having to spend the time again for nothing. This is by far the worst issue Godot has. |
An alternative solution for now is to avoid relying on built-in Camera2D smoothing (or only use it to a minimal amount). The kind of smoothing Camera2D performs (asymptotic smoothing) is not something that was used in 90s pixel art games anyway – assuming you're going for that kind of aesthetic 🙂 Using the I'm not trying to discourage anyone from resolving this issue, but I wanted to state again that workarounds do exist. |
I think I ran into this in v3.4.4 on Linux. The Pixel Snap setting seemed to fix it but I don't completely understand what causes this and I'd like a bit more information if anyone can provide it. Strangely enough it only happened with very specific sprites. I tried all of the following:
It does not seem to be relat4ed to the order that sprites are added to the scene, or any pattern I was able to find. |
Maybe try comparing Sprites with odd and even number of texture side length. If that's the cause, try disabling the "centered" property of the Sprite. |
Can't remember the exact conditions right now but if memory serves me well this bug manifests when sprites are not in exact integer positions, i.e. try setting one sprite at X = 10.1 other at X = 25.2 other at X = 40.3... Then move the camera slowly in X and you can start crying. I think camera zoom affected this, too. One 3.x version was released with my PR but unfortunately some other bugs manifested (IMHO latent bugs that were brought to light when the sprites stopped jittering) and in the end the PR was pulled. I'm still willing to try to integrate the PR again but right now I can't devote the time required to find the other bugs that manifested. I think it would be a good idea to add an option and let the user decide. Sprites just can't jitter, and, again IMHO, this issue gives Godot a very bad image. I still think this is by far the worst issue this engine has right now. |
I found this problem still exist at the v4.2.1.stable version. Test.DEBUG.2024-03-08.19-32-30.mp4 |
For future reference, this occurs because the project isn't using physics interpolation. This means the player sprite is moving at a different frequency than the screen is being rendered at, which will cause visible jitter. To resolve this, you need physics interpolation. 2D physics interpolation will be available in 4.3: #88424 Until 4.3 is released, you can use https://github.com/lawnjelly/smoothing-addon (also for 3D). Regarding the original issue, this was improved a lot in 4.3 too: #87297 |
I'm using a custom build with Physics Interpolation available. I have it switched on, and it is still jittering exactly as it is described in the opening post. |
Please open a new issue with a minimal reproduction project attached. Also, make sure the stretch scale mode is set to |
Godot version:
3.1.2 stable, GitHub master (3.2), Vulkan branch (4.0)
OS/device including version:
Windows 10 x64 v1909
Issue description:
Pretty much as soon as I made my test level larger than a single screen, I noticed something was off. After a bit of testing, I've found out what it is. It seems like any time the camera moves, there is some sort of inconsistency in the positions sprites are being rendered at, causing them to "jitter" back and forth by one pixel even though the camera is only moving in one direction.
Example gifs showing the issue:
How noticeable it is depends on circumstances. Generally, from what I've found, it's most noticeable if you have camera smoothing turned on and the smoothing speed set to a very low value, but the problem isn't related to the camera smoothing. It's also present with camera smoothing turned off, just harder to notice.
In case it was a bug that had already been fixed, I tried compiling Godot myself from both the master (presumably what will become 3.2) and vulkan (4.0?) branches to try them out, but unfortunately the problem still seems to be present in both of those. It looks a bit different in the Vulkan branch, due to what I assume is some sort of smoothing/blur filter being applied (there may be a way to turn that off, but I couldn't find it) to the background, but it is definitely still there.
Steps to reproduce:
Minimal reproduction project:
godot-jitter-repro-project.zip
The text was updated successfully, but these errors were encountered: