-
-
Notifications
You must be signed in to change notification settings - Fork 21.1k
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
Flickering sprite bleed on top row of moving sprite2ds and animatedsprites in Godot V4 (does not appear in V3) #67164
Comments
I ran the MRP but was unable to reproduce the issue with default settings. I could however reproduce the issue by setting the texture filtering mode to "linear". Did you verify that all the settings are the same between the MRP and your Godot 3 project? Importantly repear and filtering are now properties of Node2Ds rather than import settings on the sprite, so you need to ensure that they are the same. Especially if you were relying on the "pixel art 2D" texture preset |
Running the MRP on my computer consistently produces this behavior. I just re-downloaded the zip and opened it in v4.0.beta2.official [f8745f2] and am still seeing it, even with the settings on 'nearest'. video doesn't capture all the flickers but it gets one right at the beginning. sprite_frames_v4b2.DEBUG.2022-10-12.22-23-17.mp4I first noticed this behavior porting a more complicated project from V3, but the MRP itself is V4 native. |
In your Godot 3.x project are you have the |
Not that I know of. Here's a fresh godot3 project I made, recreating the minimal godot 4 project. It works without flicker. (It also has the godot icon in frame, so screenshots can be differentiated). I'd attach a video, but a video of the sprites moving up and down without flickering isn't that interesting. |
Just as an update, I've tested this with Beta 4 and it still happens. SpritebleedG3_UpdateToBeta4.zip |
Still happening in the 4.0 release version. |
I can confirm this on 4.0.rc 8208060 (Linux, GeForce RTX 4090 with NVIDIA 525.89.02): simplescreenrecorder-2023-03-01_19.10.45.mp4This occurs with both Forward+ and Compatibility rendering methods. However, I'm not convinced this is a bug. The atlas sprite has a white background, which is bound to create issues whenever a texture is not perfectly aligned with the camera: If you replace white with transparency, the issue goes away entirely. PS: Even if you don't replace white with transparency, enabling Snap 2D Transforms To Pixel and Snap 2D Vertices To Pixel seems to fix the issue too. (Enabling either of those may work too, but I've only tested each combination for a minute or so.) |
It absolutely is a bug. Godot is being asked to render some specific pixels and it's putting the wrong ones on screen. Sprite bleed might be a common problem to encounter when developing an engine (I spent several weeks wrangling a bug to get Pixi rendering in JS to avoid bleeding while resizing), but it's by no means impossible to avoid (after all, Godot 3 didn't have these sprite bleed issues). Putting a 1 pixel border around every edge of every sprite in an atlas as a workaround is a bad idea - it makes everything involving tiles and spritesheets WAY harder to work with, especially when editing them in an image program. Because of that (and to minimize file size), most assets packs and tilesets which are available for game use are designed with the assumption that the engine will display pixels correctly. If godot is going to be dev-friendly, it shouldn't require developers to go into all their assets and do additional processing by hand to work around an engine bug. If adding 2-pixel-wide gutters around every frame is necessary for the engine, that should be done programmatically by the engine itself - but since godot 3 doesn't have this issue, it's probably just a bug that can be fixed more elegantly. EDIT: Anyway, I went back to v4 alpha 1 and it's present there, so that narrows down what changes were responsible a little bit. Gonna try titrating versions a bit further. |
sprite_frames_v4b2.zip It appears that at this zoom level and location, sprite2d and animatedsprite objects at y= 76 show the sprite bleed, regardless of x coordinate. Zooming out makes the bleed disappear, returning to this zoom restore the bleed. Resizing the window or going fullscreen have the bleed persist as well. moving the window around, it's possible to get different objects to bleed, and even to get bleed on the left-hand side Hopefully that will make it easier to diagnose |
Tested with v4.2.dev5.official [e3e2528]. I added green lines to the left and bottom edge. So if everything would work as expected, you would never see white lines and always green lines at left and botton edges. This happens when the sprites are positioned at *.5 pixels. The sprites don't need to move. Left and top edges start to bleed and bottom edge is cut. If the position is e.g. *.1, this doesn't happen. As Calinou said, setting either "Snap 2d Transforms to Pixel" or "Snap 2D Vertices to Pixel" on seems to fix this. It's actually very easy to stumble upon this bug:
extends Sprite2D
func _process(delta: float) -> void:
position += Vector2(5, 5) * delta The icon moves smoothly except for the flickering edges. Editing the svg file and adding empty space around the icon removes the flickering. It is unfortunate that this is probably one of the most common first Godot programs new Godot users create. |
This is possibly a related issue to #81998 where it seems to be bleeding part of the spritesheet itself despite being imported as individual frames. |
As described in #81998, an AtlasTexture can be used to fix this issue without requiring modifying the spritesheet itself. If intended, it's not super intuitive and should be documented better, especially for anyone porting from v3. |
In the latest version vertex snapping is a workaround, but given that this is basic behavior for the Sprite2D node, I feel like the default behavior out of the box should be correct. Perhaps sprites should always be vertex snapped? |
Update since more rendering tweaks have been done, it appears that the getting-depreciated snap-to-vertex isn't 100% consistent, but is still way more reliable than snap-to-transform. I grabbed a build of this PR here: I tried to get it to bleed by moving sprites around with snap-to-vertex enabled instead, and it's considerably more difficult but still possible |
As someone who got hit by this bug in a game I was helping to work on, I wanted to try to find the root cause of this bug. I did find one of the possible causes but it's weirder than I anticipated. I would have assumed that if you were rendering a triangle in OpenGL (or any other 3D graphics library), any interpolated values passed between shaders would be within the range of the values being interpolated. In other words, I would have assumed that if a triangle's vertices had texture coordinates of (0, 0), (1, 0), and (1, 1), then every fragment's coordinates would all be in the range [0, 1]. Based on some StackOverflow posts (Example: https://stackoverflow.com/questions/63893458/msaa-and-vertex-interpolation-cause-out-of-range-values), it seems like there's a "centroid" qualifier that exists to hopefully guarantee things like this even when multisampling is enabled. However, with a very simple OpenGL test program I set up on my machine, on a 512x512 viewport, rendering a single triangle with vertex coordinates at (-0.5, -0.5019531), (0.5, -0.5019531), (0.5, 0.0) and texture coordinates (0, 0), (1, 0), (1, 1), a vertex shader of #version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTex;
out vec2 vTex;
void main()
{
vTex = aTex;
gl_Position = vec4(aPos, 0.0, 1.0);
} and a fragment shader of #version 330 core
out vec4 fragColor;
in vec2 vTex;
void main()
{
if (vTex.y == -0.000000059364538) { // Exact value found with a lot of trial and error
fragColor = vec4(1, 0, 0, 1);
}
else {
fragColor = vec4(0, 0, 0, 1);
}
} I get a triangle with a red seam at the the bottom, showing that The exact behavior seems to depend heavily on the setup, as I wasn't able to reproduce the same issue with the same setup in WebGL on the same machine, nor was I able to reproduce it on a different machine (with integrated graphics). Due to this sensitivity, I'll mention that i ran these tests on a "NVIDIA GeForce GTX 980 Ti" with a driver provided by NVIDIA with driver version 31.0.15.3623 (June 8 2023). I'm not that familiar with OpenGL/Vulkan/etc. specs, so I don't know whether this is a driver bug or whether it's acceptable according to the specs. Regardless, it seems like the only way to prevent a bug like this for sure without adding any fudge factors to the part of the texture being sampled would be to prevent the edges of any quads produced by this Sprite2D renderer from getting too close to the center of a pixel. When scaling and rotation is involved, this seems infeasible. Based on my experiments with a 512x512 viewport, the bug occurs every time a sprite is within about 0.002 units of a half-pixel. In other words, if a sprite is rendered at a random location, there would be a 1/250 chance for it to be close enough to the half-way point between pixels for this bug to occur. In my own opinion, the fix for this would probably be to bake Freedomax's suggestion (#67164 (comment)) into the engine. I'm hopeful that the (default) fudge factor can be very small, on the order of 1e-5 pixels, to the point where it would be unnoticeable. EDIT: It should be possible to fix this without a fudge factor by clamping the texture UV in the fragment shader. This seems to be done already when |
Personally I just exported my sprites and added a 1px transparent border. It's not ideal as it messes with autodetecting the sprite size/collisions but it seems to be the simplest resolution. |
I have a tentative fix for this issue! If you are able to build locally, please test #97260 and confirm if it fixes the issue for you. I was only able to reproduce the problem using the newest MRPs from Proggle here #67164 (comment), but testing with those I can confirm the issue goes away entirely when |
Godot version
v4.0.beta2.official [f8745f2]
and
v4.0.beta4.official [e675154]
System information
Windows 10
Issue description
Godot 4 has introduced additional sprite bleed that wasn't present in V3. Example: the white line appearing above these sprites.
The one on the left is an animatedSprite, the one on the right is a Sprite2D
sprite_frames_v4b2.DEBUG.2022-10-09.18-46-16.mp4
This appears regardless of whether or not the 'fix alpha border' checkmark is enabled, and appears at seemingly random times. However, it happens on both sprites simultaneously.
It also seems to only bleed above the sprites, and not in the other 3 directions. Since it only appears for 1 frame, my video isn't capturing every appearance - it happens both when they are moving upwards and moving downwards.
Steps to reproduce
Move a sprite around, eventually you will notice flickering bleed.
Minimal reproduction project
sprite_bleed.zip
The text was updated successfully, but these errors were encountered: