Scaling accuracy and spritebatches

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
soulmata
Prole
Posts: 31
Joined: Sat Jan 26, 2013 8:14 am
Contact:

Scaling accuracy and spritebatches

Post by soulmata »

Short and sweet: I've noticed when using scaling, even scaling with powers of 2, images drawn from quads will "bleed" in to adjacent quads, usually by 1 or 2 pixels. Is this normal behavior, and if so, what are some workarounds?"

Long and lovely: In this scenario, I have a tile set composed of 32x32 tiles in a 192x128 image. I generate 24 squads from this as such:

Code: Select all

  local tile_id = 0
  for x=0, 5 do -- tileset is currently 6x4
    for y=0, 3 do
      tile_id = tile_id + 1
      global.tiles.bunker_gray[tile_id] = love.graphics.newQuad(x*global.tilesize, y*global.tilesize, global.tilesize, global.tilesize, global.tilesetwidth, global.tilesetheight)
    end
  end
... where global.tilesize = 32.

I then render these quads via spritebatching as such:

Code: Select all

  for x=1, xMax do
    for y=1, yMax do
      if map_data[z][x][y]['tiletype'] then
        global.spritebatch.bunker_gray:addq( global.tiles.bunker_gray[ map_data[z][x][y]['tiletype'] ], x*global.tilesize, y*global.tilesize)
      end
    end
  end

  love.graphics.draw(global.spritebatch.bunker_gray,0,0)
... where global.tiles.bunker_gray are the quads in question, and map_data is my map data, obviously. Now, this works out great and is fairly performant. I can draw huge amounts of tiles easily, and it looks just fine. Until I start messing with scale. At scaling 1, it looks perfect and seamless. As soon as scaling goes above 1, in-between tiles I start to see bleeding from adjacent tiles in the set. It comes and goes, presumably due to rounding differences as you scale up or down. The only real troubling part of this is when I'm scaling at powers 2 of. My very first 32x32 tile, for instance, when rendered as 32x32, looks perfect. When rendered at a scaling factor of 2 (so 64x64), the right-most column is a blend of the last column in the first tile and the first column in the second tile.

I can reliably reproduce this when I try to scale. I tried some weird ways around it, like telling it to draw only 31 pixels in, et cetera, but to no avail.

Suggestions? Or is this just the way it is with SDL scaling? If the latter, I suppose I can always make my tiles 64x64 to begin with and just not scale, but I was really hoping to have nifty zoom features.
Endless Dark: An existential horror game written in LOVE in which you are tasked with keeping a sleeper colony ship intact.
User avatar
Jasoco
Inner party member
Posts: 3726
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: Scaling accuracy and spritebatches

Post by Jasoco »

This happens in everything when you don't scale to a whole number. That's the main workaround. To make sure you only scale at whole numbers.

Next make sure to FLOOR the X and Y drawing positions. This will reduce blurring and offset caused by decimal offsets.
User avatar
soulmata
Prole
Posts: 31
Joined: Sat Jan 26, 2013 8:14 am
Contact:

Re: Scaling accuracy and spritebatches

Post by soulmata »

Yeah, I was afraid of that. Unfortunately, if I want to support free scaling and rotation with multiple windows present(which I do, using gamera), enforcing whole number scaling is very difficult. I tried many methods of adjusting drawing positions and scaling to nearest whole or quarter numbers but somewhere the translation always broke somewhere - I'd get one region OK only to break another.

But, I ended up finding a solution I'm not.. "happy" with, but one which appears to work regardless of how much I scale and rotate: I turned my 32x32 tiles into 34x34 tiles, with a 1px border around them that matched the color of the nearest inward adjacent pixel. Kind of hokey, I know, but free scaling and rotation is just too cool, and the performance of spritebatching is critical.

Thanks for confirming my suspicions.
Endless Dark: An existential horror game written in LOVE in which you are tasked with keeping a sleeper colony ship intact.
User avatar
Boolsheet
Inner party member
Posts: 780
Joined: Wed Dec 29, 2010 4:57 am
Location: Switzerland

Re: Scaling accuracy and spritebatches

Post by Boolsheet »

soulmata wrote:a 1px border around them that matched the color of the nearest inward adjacent pixel.
That is the correct way to get the behaviour that you want. It's just how OpenGL works.
Shallow indentations.
hasen
Party member
Posts: 157
Joined: Sat Jan 20, 2018 2:01 pm

Re: Scaling accuracy and spritebatches

Post by hasen »

I have this exact same problem, using Gamera and spritebatches. I'm scaling by a decimal to resolve screen size differences on mobile and I'm seeing the same bleed although only across the x axis even though love.graphics.scale Y scale is also a decimal.

Is there any way to floor the result of love.graphics.scale ? I tried :setFilter on the problem image since setting it as a blanket default solved the problem but caused a new flickering problem with other images. Also using :setFilter("nearest", "nearest") with the player solved the pixel bleed on the x axis but strangely not on the y axis.

Any way to solve these problems?
Last edited by hasen on Thu Mar 01, 2018 7:57 am, edited 2 times in total.
hasen
Party member
Posts: 157
Joined: Sat Jan 20, 2018 2:01 pm

Re: Scaling accuracy and spritebatches

Post by hasen »

Boolsheet wrote: Tue Jan 29, 2013 9:32 am
soulmata wrote:a 1px border around them that matched the color of the nearest inward adjacent pixel.
That is the correct way to get the behaviour that you want. It's just how OpenGL works.
I've never seen tiles made like this in tutorials or available to download like that though?
User avatar
raidho36
Party member
Posts: 2063
Joined: Mon Jun 17, 2013 12:00 pm

Re: Scaling accuracy and spritebatches

Post by raidho36 »

Yeah it's odd that tutorials never mention this technical quirk. But it's like this on 100% of GPU hardware out there. Most software designed to make tiles has an option to add a padding. Virtually any sprite-atlas generator has this option and it's usuall on by default, too.
hasen
Party member
Posts: 157
Joined: Sat Jan 20, 2018 2:01 pm

Re: Scaling accuracy and spritebatches

Post by hasen »

raidho36 wrote: Thu Mar 01, 2018 6:53 am Yeah it's odd that tutorials never mention this technical quirk. But it's like this on 100% of GPU hardware out there. Most software designed to make tiles has an option to add a padding. Virtually any sprite-atlas generator has this option and it's usuall on by default, too.
But the padding is normally transparent or one single colour (usually white), not the same colour as the tile...since the tiles are gonna be all different colours while the padding is all the same colour.. Are you sure that would still solve the problem? If so I could try that.
grump
Party member
Posts: 947
Joined: Sat Jul 22, 2017 7:43 pm

Re: Scaling accuracy and spritebatches

Post by grump »

hasen wrote: Thu Mar 01, 2018 7:17 am But the padding is normally transparent or one single colour (usually white), not the same colour as the tile...since the tiles are gonna be all different colours while the padding is all the same colour
Making the border around each tile the same colors as the actual tile edges (i.e. repeating the outermost rows/columns once) takes care of that.
User avatar
zorg
Party member
Posts: 3465
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Scaling accuracy and spritebatches

Post by zorg »

If i'm not mistaken, transparent and single-colour padding doesn't help, since if/when the gpu will try to sample beyond the defined region of the sprite itself (usually due to UV coordinate sampling happening at texture edges, and not centers, therefore the GPU interpolating between two pixel colors), it needs to find the same colors that the tile's respective edges have, otherwise you'll still see issues, like pixels being more white (if that's your padding color) or the pixel colors from "below" showing through somewhat (if your padding is transparent); this also means that you do need to "extrude" those tiles in all four directions, meaning that in most places, there will be not 1, but 2 pixels of padding between them (anywhere except the edges of the atlas itself)

Then again, i might be wrong, and the padding may only need to match the right and bottom edges of each tile, giving back a 1-pixel padding.

(Also, just a minor complaint to nobody in particular, but it would be so nice if google search wasn't saturated with answers only pertaining to Unity)
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Semrush [Bot] and 6 guests