faiface / pixel

A hand-crafted 2D game library in Go
MIT License
4.46k stars 245 forks source link

Flickering canvas/edges #144

Open Lallassu opened 6 years ago

Lallassu commented 6 years ago

After upgrade to latest Pixel it seems to be some issues with flickering lines between canvases. My map in the image below consists of multiple canvases side-by-side without any space between. When moving around the window flickers by showing up lines between each canvas as seen in the image below.

This only happens when moving the camera around. This happens like every 200 frame when moving constantly, so it's not every frame. Any idea why?

faiface commented 6 years ago

Does this really only happen since the last time you updated? Doesn't it happen with all versions of Pixel?

Lallassu commented 6 years ago

I haven't notice it before. I will do some testing with older versions. I updated pixel to latest version during the same time as upgrading OSX to Mojave, so that might also be a cause.

But since you ask, are you aware of these kind of issues before?

Lallassu commented 6 years ago

@faiface I've tested with older versions and as you insinuated it was the same issue with older versions as well. Do you have any idea for a workaround or fix? Or perhaps if I do something wrong that makes it flicker like this?

Lallassu commented 6 years ago

I found that smoothing seems to play a role here. With smoothing it seems to become borders between each canvas and no borders without smoothing (but flickering instead).

Smoothing TRUE:

Smoothing FALSE:

Lallassu commented 5 years ago

Another clue. Drawing the imdraw to a batch instead of a canvas makes the lines disappear.

faiface commented 5 years ago

Oh, that's an interesting observation. So, when you stop using many canvases the lines disappear, right? Okay, my theory is that the lines happen because of floating point inaccuracies. Now, why don't these inaccuracies happen when drawing everything to a single canvas? I'm not sure, but it might be because OpenGL perhaps does some checking on the triangles to see which ones are touching and draws them nicely, without a gap, but doesn't do such a checking when drawing whole canvases.

Lallassu commented 5 years ago

Yes exactly, drawing to a batch using custom TriangleData works fine.

elliotmr commented 5 years ago

I was running into the same issue with a tmx map renderer. Every once and a while I would hit some weird zoom/translation combination that would cause some unexpected lines to show up.

After searching around for a bit, I am pretty sure this has nothing to do with pixel, it is a common problem with using texture atlases and OpenGL.

https://stackoverflow.com/questions/19611745/opengl-black-lines-in-between-tiles https://gamedev.stackexchange.com/questions/148247/prevent-tile-layout-gaps

Both of these pages make reference to using GL_NEAREST rather than GL_LINEAR which is exactly the change that the Canvas.smooth makes. It looks like common practice is to "extrude" the textures in the atlas so that there is repeated pixel around the texture that you are selecting.

hamogor commented 5 years ago

Yes exactly, drawing to a batch using custom TriangleData works fine.

I'm drawing to a batch and still experiencing this.

`func Render(ap *ap) {

ap.Batch.Clear()
ap.Window.Clear(colornames.Black)
ap.CamPos = pixel.Lerp(ap.CamPos, ap.Player.Position, 1-math.Pow(1.0/128, ap.Dt))
cam := pixel.IM.Moved(ap.CamPos.Scaled(-1))
wallPic := pixel.NewSprite(ap.Spritesheet, ap.Assets[8])
floorPic := pixel.NewSprite(ap.Spritesheet, ap.Assets[17])
for x := 0; x < ap.Dungeon.Width; x++ {
    for y := 0; y < ap.Dungeon.Height; y++ {
        if ap.Dungeon.Cells[x][y].T == 1 {
            wallPic.Draw(ap.Batch, CalculateRenderPos(x, y, ap))
        } else {
            floorPic.Draw(ap.Batch, CalculateRenderPos(x, y, ap))
        }
    }
}
ap.Player.Sprite.Draw(ap.Batch, pixel.IM.Moved(ap.Player.Position))
ap.Window.SetMatrix(pixel.IM.Scaled(pixel.ZV,
    math.Min(
        ap.Window.Bounds().W()/ap.Canvas.Bounds().W()*3,
        ap.Window.Bounds().H()/ap.Canvas.Bounds().H()*3,
    ),
).Moved(ap.Window.Bounds().Center()))
ap.Batch.SetMatrix(cam)
ap.Batch.Draw(ap.Window)
ap.Window.Update()

}`

mstfymrtc commented 4 years ago

Flickering also happens to me when i work with multi-windows. It appears only in the bottom of the screens. (It can be seen on blue areas below. Also don't know why it's blue, although it should be black as the rest of the tiles)

Screen Recording 2020-06-10 at 06 46 42

Seb-C commented 2 years ago

I have the same problem (even with batches).

Interestingly, with the smooth flag, the visual gap between tiles is smaller, but the issue becomes systematic.

As a workaround, I adjusted the size of my textures with something like .Scaled(pixel.ZV, 1.01), and it seems to have solved the issue.

(BTW, thank you so much for this awesome package!)