Closed taotao54321 closed 4 years ago
Thank you for the report!
This seems to only happen specifically when drawing at (or very close to) .5
of a pixel - if you change the Y position to 39.49
or 39.51
, the issue disappears. It also only seems to happen on some devices - someone on Discord said that your example works fine for them as is on an AMD graphics card.
I'm not 100% sure why this is happening, but it doesn't seem to be a Tetra-specific issue - I'm able to replicate it in Love2D as well, so it's probably something to do with OpenGL. My hunch is that it's due to floating point error in the texture sampling, but I don't know for sure.
In general, though, rendering at non-integer co-ordinates can cause artifacts in OpenGL, even without this weird platform-specific behaviour. Quoting the Love2D docs:
Quads 'bleed' when scaled, rotated or drawn at non-integer coordinates, even within SpriteBatches, to compensate for this, use 1px borders around the textures inside the texture atlas (preferably with the same colors as the actual border)
So if rendering at non-integer co-ordinates is something you need to do, that would probably be the best fix. Otherwise, just draw at integer co-ordinates and you shouldn't see these issues.
Other things that could be helpful:
Canvas
or a ScreenScaler
you don't seem to get these artifacts like this either, so that could be another option.Thank you! I didn't know much about OpenGL and studied a good thing this time.
I fixed my drawing code to call Vec2::floor()
, and it works all fine for my purpose.
Just FYI: actually my code was drawing also on Canvas
, and still I had the same problem. So, this behavior also seems graphics-card dependent (I'm using GeForce GTX 650).
Ah, the Canvas
thing might have been a fix for a different issue, then - might have to dig deeper into that.
While I don't think this is a 'bug', so to speak, there is definitely a documentation gap here, so I will leave this issue open to track improvements on that front.
This is what it looks like when the camera position is a non-integer . Landscape and player graphics are from a single spritesheet. Flooring the camera position will fix it.
Aha, yeah, that demonstrates the problem really well - this definitely needs documenting better. Where would you expect to find a warning about this - on the clip
parameter of DrawParams
? Or is there a better place for it...
As an aside, those tiles/sprites are extremely cute 😄
hmm... good question... Shouldn't this be handled internally?
There are several places where it is hidden and only if you know the problem you know that you have to floor the position to avoid the problem.
places
The only place you will definitely see is if you create a DrawParams with clip.
The problem I have with trying to handle this internally is that, as far as I know, there's not a one-size-fits-all approach - while flooring positions is probably the best/easiest way to handle this in a pixel art game, there's other approaches you might want to take if you were doing something more high resolution (for example, extending the edges of the texture out by 1 pixel and switching to FilterMode::Linear
). I'm wary of taking that choice away from the user unless I know I'm making the right choice.
For context, most other frameworks seem to leave this up to the user as well (XNA, Love2D, LibGDX).
I've added a note to the docs:
I've also changed Texture
to use CLAMP_TO_EDGE
wrapping, so you should at least not see issues with stuff bleeding from one side of a texture atlas to the other.
Does this seem sufficient?
I think this doc is helpful to newbies like me. Thank you!
Cool! I'll leave this issue open until 0.4.2 is published, at which point the new docs should be available on docs.rs.
0.4.2 is released! Docs should update in the next few minutes, depending on how busy the docs.rs queue is.
Summary: I'm managing my sprites with spritesheets. I slice sprites from sheets with
DrawParams::clip()
, and draw them on a position withDrawParams::position()
. But, when I let the sprites move around, I noticed that they sometimes displays off by 1 pixel.Steps to reproduce: I wrote a minimal case, and here is the screenshot:
I found this seems to be caused by passing
DrawParams::position()
some real numbers.Expected behavior: I expected
position()
does not affect sprite clipping, but actually it seems do. Is it a intended feature? If so, how can I ensure that the sprites are clipped pixel-perfectly?Additional info: system info: Debian testing, nvidia-driver 440.100-2