Page 1 of 1

[SOLVED] push.lua and love.graphics.newQuad problem

Posted: Thu May 16, 2024 4:56 pm
by Bondrusiek
Hello everyone!
I write this post because I have a problem with push.lua and love.graphics.newQuad. I know that here are many love2d experts and maybe someone can help me. Ok so I've done a app:

Code: Select all

push = require 'push'

virtualWidth = 33 * 16
virtualHeight = 28 * 16

windowWidth = 33 * 16
windowHeight = 28 * 16

mode = 1

function generateQuads(atlas, tilewidth, tileheight)
    local sheetWidth = atlas:getWidth() / tilewidth
    local sheetHeight = atlas:getHeight() / tileheight

    local sheetCounter = 1
    local quads = {}

    for y = 0, sheetHeight - 1 do
        for x = 0, sheetWidth - 1 do
            -- this quad represents a square cutout of our atlas that we can
            -- individually draw instead of the whole atlas
            quads[sheetCounter] =
                love.graphics.newQuad(x * tilewidth, y * tileheight, tilewidth,
                tileheight, atlas:getDimensions())
            sheetCounter = sheetCounter + 1
        end
    end

    return quads
end

function love.load()
    spriteSheets = love.graphics.newImage("tiles.png")
    tilesSprite = generateQuads(spriteSheets, 16, 16)
    love.window.setMode(33*16, 28*16)

    love.graphics.setDefaultFilter('nearest', 'nearest')
    love.window.setTitle("With push")
    -- sets up virtual screen resolution for an authentic retro feel
    if mode == 1 then 
        push:setupScreen(virtualWidth, virtualHeight, windowWidth, windowHeight, {
            fullscreen = false,
            resizable = false
        })
    end
end

-- called whenever window is resized
function love.resize(w, h)
    if mode == 1 then
        push:resize(w, h)
    end
end

function love.update(dt) 

end

function love.draw()
    if mode == 0 then
        love.graphics.clear(255, 255, 255)
        local index = 1
        for x = 1, 33 do
            for y = 1, 28 do 
                love.graphics.draw(spriteSheets, tilesSprite[index], (y - 1) * 16, (x - 1) * 16)
                index = index + 1
            end
        end
    end
    if mode == 1 then
        -- begin virtual resolution drawing
        push:apply('start')

        -- clear screen using Mario background blue
        love.graphics.clear(108, 140, 255, 255)
        local index = 1
        for x = 1, 33 do
            for y = 1, 28 do 
                love.graphics.draw(spriteSheets, tilesSprite[index], (y - 1) * 16, (x - 1) * 16)
                index = index + 1
            end
        end
        
        push:apply('end')
    end
end
Where you can use mode to control app. With mode equals 1 app runs with push otherwise without it. Result
example.png
example.png (848.16 KiB) Viewed 2532 times
As you can see, there is a 1-pixel border at the edge of the tile and I don't know how to get rid of it. This is actually the most important part of this thread. You know how to get rid of this border. You can see it better when you scale it up, but to compare it with the version without push, I used such a low resolution.
Addons:
push.lua : https://github.com/Ulydev/push/blob/master/push.lua
tiles.png:
tiles.png
tiles.png (35.55 KiB) Viewed 2532 times

Re: push.lua and love.graphics.newQuad problem

Posted: Fri May 17, 2024 4:15 pm
by pgimeno
[Edited to avoid confusion to possible future readers]

The images with push use a linear filter, while the images without push use a nearest filter. With the nearest linear filter the adjacent tiles can bleed into the current tile. Changing to linear nearest should solve it, if that's acceptable for your project. Otherwise, you'll need to fix your tileset by separating the tiles by at least one pixel.

Re: push.lua and love.graphics.newQuad problem

Posted: Sat May 18, 2024 9:48 am
by Bondrusiek
Thanks for a reply. I used a linear filter

Code: Select all

love.graphics.setDefaultFilter('linear', 'linear')
but bug still exists. Moreover I created a test tiles with 17px x 17px(1px for a gap) then I used

Code: Select all

spriteSheets = love.graphics.newImage("upgrade_tiles.png")
tilesSprite = generateQuads(spriteSheets, 17, 17)
and I draw it using:

Code: Select all

        for x = 1, 27 do
            for y = 1, 2 do 
                love.graphics.draw(spriteSheets, tilesSprite[index], (y - 1) * 16, (x - 1) * 16)
                index = index + 1
            end
        end
unfortunately the border bug still exists. Maybe the push library is broken in this area.
Tested png:
upgrade_tiles.png
upgrade_tiles.png (2.08 KiB) Viewed 2399 times

Re: push.lua and love.graphics.newQuad problem

Posted: Sat May 18, 2024 1:33 pm
by Imnotaplayer

Code: Select all

function love.load()
    spriteSheets = love.graphics.newImage("tiles.png")
    tilesSprite = generateQuads(spriteSheets, 16, 16)
    love.window.setMode(33*16, 28*16)

    love.graphics.setDefaultFilter('nearest', 'nearest')
    -- ...
end
You should call love.graphics.setDefaultFilter() before creating any images. It does not retroactively apply to images that have already been created. I would think "nearest" would work fine here and that "linear" is what's causing what you see. (In the images you provided, they can still be seen using a linear filter)

I think another problem here is that the quads you are creating border other tiles in the atlas. Having a 1 pixel gap would fix this but you create the quads as 17x17, so they will still border other tiles. You can use an additional set of values to indicate the actual size of the tile.

Code: Select all

function generateQuads(atlas, tilewidth, tileheight, sourcewidth, sourceheight)
    -- ...
    for y = 0, sheetHeight - 1 do
        for x = 0, sheetWidth - 1 do
            quads[sheetCounter] =
                love.graphics.newQuad(x * tilewidth, y * tileheight,
                sourcewidth, sourceheight, atlas:getDimensions())
        end
    end
    -- ...
end

-- ...

generateQuads(spriteSheets, 17, 17, 16, 16)

Re: push.lua and love.graphics.newQuad problem

Posted: Sat May 18, 2024 6:12 pm
by pgimeno
pgimeno wrote: Fri May 17, 2024 4:15 pm The images with push use a linear filter, while the images without push use a nearest filter. With the nearest filter the adjacent tiles can bleed into the current tile. Changing to linear should solve it, if that's acceptable for your project. Otherwise, you'll need to fix your tileset by separating the tiles by at least one pixel.
Bondrusiek wrote: Sat May 18, 2024 9:48 am Thanks for a reply. I used a linear filter

Code: Select all

love.graphics.setDefaultFilter('linear', 'linear')
but bug still exists. Moreover I created a test tiles with 17px x 17px(1px for a gap) then I used

Code: Select all

spriteSheets = love.graphics.newImage("upgrade_tiles.png")
tilesSprite = generateQuads(spriteSheets, 17, 17)
and I draw it using:

Code: Select all

        for x = 1, 27 do
            for y = 1, 2 do 
                love.graphics.draw(spriteSheets, tilesSprite[index], (y - 1) * 16, (x - 1) * 16)
                index = index + 1
            end
        end
unfortunately the border bug still exists. Maybe the push library is broken in this area.
Tested png: upgrade_tiles.png
What I said was completely reversed :ultrashocked:

I'm very sorry. Let me rewrite it.

The images with push use a linear filter, while the images without push use a nearest filter. With the linear filter the adjacent tiles can bleed into the current tile. Changing to nearest should solve it, if that's acceptable for your project. Otherwise, you'll need to fix your tileset by separating the tiles by at least one pixel.

In short, what Imnotaplayer said.

Re: push.lua and love.graphics.newQuad problem

Posted: Mon May 20, 2024 9:22 am
by Bondrusiek
Imnotaplayer wrote: Sat May 18, 2024 1:33 pm You should call love.graphics.setDefaultFilter() before creating any images. It does not retroactively apply to images that have already been created. I would think "nearest" would work fine here and that "linear" is what's causing what you see. (In the images you provided, they can still be seen using a linear filter)
Now it works. I used love.graphics.setDefaultFilter('nearest', 'nearest') before creating any images. Lesson from this thread is love.graphics.setDefaultFilter does not retroactively apply to images that have already been created. Thanks Imnotaplayer and pgimeno for help.