Page 1 of 1

multiple canvases alpha, not working ?

Posted: Wed Feb 24, 2021 3:51 pm
by gcmartijn
Hi,
Screenshot 2021-02-24 at 16.43.03.png
Screenshot 2021-02-24 at 16.43.03.png (8.56 KiB) Viewed 3027 times
How to make the yellow part .50 alpha ?

This is the not working code.

Code: Select all

function love.load()
    canvas1 = love.graphics.newCanvas()
    drawCanvas1()

    canvas2 = love.graphics.newCanvas()
    drawCanvas2()

    love.graphics.setCanvas()
end

function drawCanvas1()
    love.graphics.setCanvas(canvas1)
    love.graphics.setBlendMode("alpha", "premultiplied")
    love.graphics.setColor(1, 0, 0)
    love.graphics.rectangle("fill", 0, 0, 100, 100)
end

function drawCanvas2()
    love.graphics.setCanvas(canvas2)
    love.graphics.setBlendMode("alpha", "premultiplied")
    love.graphics.setColor(1, 1, 0, .5)
    love.graphics.rectangle("fill", 50, 50, 100, 100)
end

function love.update(dt)
    canvas1:renderTo(
        function()
            drawCanvas1()
        end
    )
    canvas2:renderTo(
        function()
            drawCanvas2()
        end
    )
end

function love.draw()
    love.graphics.setColor(1, 1, 1, 1)
    love.graphics.draw(canvas1)
    love.graphics.draw(canvas2)
end
and this is the working code, but without the update code I want to use.
Screenshot 2021-02-24 at 16.46.08.png
Screenshot 2021-02-24 at 16.46.08.png (7.78 KiB) Viewed 3027 times

Code: Select all

function love.load()
    canvas1 = love.graphics.newCanvas()
    drawCanvas1()

    canvas2 = love.graphics.newCanvas()
    drawCanvas2()

    love.graphics.setCanvas()
end

function drawCanvas1()
    love.graphics.setCanvas(canvas1)
    love.graphics.setColor(1, 0, 0)
    love.graphics.rectangle("fill", 0, 0, 100, 100)
end

function drawCanvas2()
    love.graphics.setCanvas(canvas2)
    love.graphics.setColor(1, 1, 0, .5)
    love.graphics.rectangle("fill", 50, 50, 100, 100)
end

-- function love.update(dt)
--     canvas1:renderTo(
--         function()
--             drawCanvas1()
--         end
--     )
--     canvas2:renderTo(
--         function()
--             drawCanvas2()
--         end
--     )
-- end

function love.draw()
    love.graphics.setColor(1, 1, 1, 1)
    love.graphics.draw(canvas1)
    love.graphics.setBlendMode("alpha", "premultiplied")
    love.graphics.draw(canvas2)
end

Re: multiple canvases alpha, not working ?

Posted: Thu Feb 25, 2021 2:57 am
by pgimeno
gcmartijn wrote: Wed Feb 24, 2021 3:51 pm How to make the yellow part .50 alpha ?
You draw to a canvas that you have previously initialized with RGBA=0,0,0,0 (you can clear it with 0,0,0,0 every frame); you use normal blend mode to draw to the canvas, and when you draw the canvas to the screen, you use premultiplied alpha mode.

Note that the love.graphics.setCanvas call is not necessary for renderTo.

Code: Select all

local function drawCanvas1()
    --love.graphics.setColor(0, 0, 0, 0)
    love.graphics.clear()
    love.graphics.setBlendMode("alpha", "alphamultiply")
    love.graphics.setColor(1, 0, 0)
    love.graphics.rectangle("fill", 0, 0, 100, 100)
end

local function drawCanvas2()
    --love.graphics.setColor(0, 0, 0, 0)
    love.graphics.clear()
    love.graphics.setBlendMode("alpha", "alphamultiply")
    love.graphics.setColor(1, 1, 0, .5)
    love.graphics.rectangle("fill", 50, 50, 100, 100)
end

function love.load()
    canvas1 = love.graphics.newCanvas()
    canvas1:renderTo(drawCanvas1)

    canvas2 = love.graphics.newCanvas()
    canvas2:renderTo(drawCanvas2)
end

function love.update(dt)
    canvas1:renderTo(drawCanvas1)
    canvas2:renderTo(drawCanvas2)
end

function love.draw()
    love.graphics.setColor(1, 1, 1, 1)
    love.graphics.setBlendMode("alpha", "premultiplied")
    love.graphics.draw(canvas1)
    love.graphics.draw(canvas2)
    love.graphics.setBlendMode("alpha", "alphamultiply")
end
(edited to comment out the setColor(0,0,0,0) calls)

Re: multiple canvases alpha, not working ?

Posted: Thu Feb 25, 2021 6:48 am
by gcmartijn
Thanks !

Now it's possible for me to convert some things into this multiple canvases structure.

I see that you use setColor(0,0,0,0) and clear().

What I do is sometimes this

Code: Select all

function QuickMenu:draw()
    -- current color
    local pr, pg, pb, pa = love.graphics.getColor()
    local pfont = love.graphics.getFont()

    love.graphics.setColor(self.backgroundColor)
    love.graphics.rectangle("fill", self.x, self.y, self.w, self.h)
    for _, button in ipairs(self.buttons) do
        button:draw()
    end

    -- reset
    love.graphics.setColor(pr, pg, pb, pa)
    love.graphics.setFont(pfont)
end
But maybe this is not needed anymore, if I use your example

Re: multiple canvases alpha, not working ?

Posted: Thu Feb 25, 2021 12:27 pm
by pgimeno
Uh, good point, I'm doing it wrong. I've edited my answer to remove the setColor call. The docs specify that love.graphics.clear() clears to 0,0,0,0 already, and in any case it never uses the current foreground colour implicitly.

Drawing a rectangle is most likely less efficient than love.graphics.clear.

Re: multiple canvases alpha, not working ?

Posted: Thu Feb 25, 2021 12:52 pm
by gcmartijn
And can i do this, because this is working, or is it better to leave the setBlendMode inside the function?

Code: Select all

local function drawCanvas1()
    love.graphics.clear()
    --love.graphics.setBlendMode("alpha", "alphamultiply")
    love.graphics.setColor(1, 0, 0)
    love.graphics.rectangle("fill", 0, 0, 100, 100)
end

local function drawCanvas2()
    love.graphics.clear()
    --  love.graphics.setBlendMode("alpha", "alphamultiply")
    love.graphics.setColor(1, 1, 0, .5)
    love.graphics.rectangle("fill", 50, 50, 100, 100)
end

Re: multiple canvases alpha, not working ?

Posted: Thu Feb 25, 2021 5:35 pm
by pgimeno
gcmartijn wrote: Thu Feb 25, 2021 12:52 pm And can i do this, because this is working, or is it better to leave the setBlendMode inside the function?
Yes, the default blending mode is "alpha","alphamultiply". As long as you restore it when it's changed in love.draw, you can remove it from the functions. It's a bit like changing colour and then forgetting that it was changed elsewhere before drawing the next thing. If you're careful to restore it every time you change it, it's not necessary.

Indeed in the love.draw function that I posted, I restored the default after drawing in premultiplied mode. The only case where you need premultiplied mode is when drawing the canvases to the screen.

Re: multiple canvases alpha, not working ?

Posted: Thu Feb 25, 2021 5:42 pm
by gcmartijn
Oke thanks for the info, I have to say that at this point I din't have any knowledge about blending modes at all ;) but now I can implement this structure in some classes. Thanks.