Page 1 of 2

Image Filter artefacts when zoomed

Posted: Sat Jan 18, 2014 10:34 am
by DrDaveDeath
Hi there -

I'm currently prototyping a game out, I have a bunch of tiles in a quad and I'm drawing them based on a grid. The problem I am having, after scaling upwards (using gamera, not sure if that's relevant or not), I am seeing artefacts when moving. I've taken some screenshots:

Image
This one is fine

Image
Notice the white lines. They sort of flicker, not always visible.

I have love.graphics.setDefaultFilter('nearest', 'nearest') set.

The tileset I'm using:
Image

Think I am loading the quads in a normal fashion:

Code: Select all

 	
Quads = {
		love.graphics.newQuad(0, 0, tileW, tileH, tilesetW, tilesetH),
		love.graphics.newQuad(0, 64, tileW, tileH, tilesetW, tilesetH),
		love.graphics.newQuad(0, 128, tileW, tileH, tilesetW, tilesetH),
		love.graphics.newQuad(0, 192, tileW, tileH, tilesetW, tilesetH),
		love.graphics.newQuad(0, 256, tileW, tileH, tilesetW, tilesetH)
}
Any ideas?

Edit: Probably worth noting that I have

Code: Select all

for rowIndex=1, #dungeon do
		local row = dungeon[rowIndex]
		for columnIndex=1, #row do
			local number = row[columnIndex]
			love.graphics.draw(tileSet, Quads[number], (columnIndex-1)*tileW, (rowIndex-1)*tileH)
		end
	end
in my love.draw.

Re: Image Filter artefacts when zoomed

Posted: Sat Jan 18, 2014 11:23 am
by Jasoco
Use math.floor() for the image draw coordinates. You're drawing them at decimal positions.

Also remember that you're going to have this problem if you scale to anything that's not a whole number.

An alternative advanced method is to draw to a canvas at 100% and scale that.

Also, a better way of creating the quads:

Code: Select all

Quads = {}
for i = 1, (tilesetH / tileH)
  Quads[i] = love.graphics.newQuad(0, (i-1) * tileH, tileW, tileH, tilesetW, tilesetH)
end

Re: Image Filter artefacts when zoomed

Posted: Sat Jan 18, 2014 11:29 am
by slime
If you 'expand' the border pixels of each sub-image in your tileset by 1px on each side (and account for the new padding when making your Quads), the problem should go away.

You can do this programmatically with ImageData functions if you want.

Re: Image Filter artefacts when zoomed

Posted: Sat Jan 18, 2014 11:33 am
by Jasoco
The problem being demonstrated here will be fixed by simply flooring the coordinates. And making sure to only scale at whole numbers.

Re: Image Filter artefacts when zoomed

Posted: Sat Jan 18, 2014 11:35 am
by slime
Jasoco wrote:The problem being demonstrated here will be fixed by simply flooring the coordinates. And making sure to only scale at whole numbers.
That's a workaround - and it won't work very well when other types of graphics transformations are applied.

Here is what another website says:
Starling wiki wrote: Tiling images on the GPU involve some gotchas. If your images aren't drawn to whole pixels or they are scaled, the textures may bleed a bit and cause unsightly lines or empty gaps between images. During animations, flickering may happen where textures meet as these gaps quickly appear and disappear. It can help to always ensure that your display objects aren't placed on fractional pixels, but that can be an exercise in frustration, especially on a deep display list.

The popular Texture Packer software, used to create texture atlases, offers a useful feature named “Extrude”. When you enable this feature, the pixels around the edges of your sub-textures will be duplicated, but it won't change the size of your sub-textures. The duplicated pixels appear just outside the sub-texture's bounds. When texture bleeding happens, the same color that appears on the edge of the sub-texture will bleed into the bounds instead of a transparent pixel or another color.

When tiling images, extruding is always recommended.
[It takes just a bit of time to duplicate the extrusion behaviour of Texture Packer programmatically in LÖVE or somewhere else.]

Re: Image Filter artefacts when zoomed

Posted: Sat Jan 18, 2014 1:41 pm
by DrDaveDeath
Many thanks for the replies guys. Really fast. What a great community.

I manually extruded my tiles for now and that fixed the issue. Will look into an app that sorts that out for me later :)

Thanks again!

Re: Image Filter artefacts when zoomed

Posted: Tue Jan 21, 2014 10:52 pm
by DrDaveDeath
Jasoco wrote:Use math.floor() for the image draw coordinates. You're drawing them at decimal positions.

Also remember that you're going to have this problem if you scale to anything that's not a whole number.

An alternative advanced method is to draw to a canvas at 100% and scale that.

Also, a better way of creating the quads:

Code: Select all

Quads = {}
for i = 1, (tilesetH / tileH)
  Quads[i] = love.graphics.newQuad(0, (i-1) * tileH, tileW, tileH, tilesetW, tilesetH)
end
I've been playing around with this method of creating the Quads, although I am presuming the limitation here is that if I am padding each quad by 1, I can't use this method? Or am I just being dense?

Re: Image Filter artefacts when zoomed

Posted: Tue Jan 21, 2014 11:44 pm
by Jasoco
I don't believe in the extrusion method myself. (It's not required at all if you're only scaling to whole numbers and just floor the x and y when drawing) But just make the quad size the same as the extruded tile. Easy as pie.

Re: Image Filter artefacts when zoomed

Posted: Wed Jan 22, 2014 2:44 am
by verilog
The best solution, as Slime pointed out, is padding each tile with a 1 pixel border with the color of the neighbouring pixel, this will get rid of the issue under all possible image transformations. I believe this issue has to do with how OpenGL uses the neighbouring pixel color (that falls outside of your tile) while drawing at non-integer coordinates. The direct workaround, as Jasoco suggested, is drawing at integer positions (using math.floor). However, there could be other transformations (e.g. rotation) that would still be rendered incorrectly.

Re: Image Filter artefacts when zoomed

Posted: Wed Jan 22, 2014 9:04 pm
by DrDaveDeath
DrDaveDeath wrote:
Jasoco wrote:Use math.floor() for the image draw coordinates. You're drawing them at decimal positions.

Also remember that you're going to have this problem if you scale to anything that's not a whole number.

An alternative advanced method is to draw to a canvas at 100% and scale that.

Also, a better way of creating the quads:

Code: Select all

Quads = {}
for i = 1, (tilesetH / tileH)
  Quads[i] = love.graphics.newQuad(0, (i-1) * tileH, tileW, tileH, tilesetW, tilesetH)
end
I've been playing around with this method of creating the Quads, although I am presuming the limitation here is that if I am padding each quad by 1, I can't use this method? Or am I just being dense?
FYI for those interested, to get around the padding I did:

Code: Select all

Quads[i] = love.graphics.newQuad(1, (i-1) * 66, tileH, tileY, tilesetW, tilesetH)
66 being 64 + 2 padding cells.