multiple canvases alpha, not working ?

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.
Post Reply
gcmartijn
Citizen
Posts: 50
Joined: Sat Dec 28, 2019 6:35 pm

multiple canvases alpha, not working ?

Post 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 1349 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 1349 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
Attachments
Screenshot 2021-02-24 at 16.43.03.png
Screenshot 2021-02-24 at 16.43.03.png (8.56 KiB) Viewed 1349 times
User avatar
pgimeno
Party member
Posts: 2575
Joined: Sun Oct 18, 2015 2:58 pm

Re: multiple canvases alpha, not working ?

Post 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)
Last edited by pgimeno on Thu Feb 25, 2021 12:28 pm, edited 1 time in total.
gcmartijn
Citizen
Posts: 50
Joined: Sat Dec 28, 2019 6:35 pm

Re: multiple canvases alpha, not working ?

Post 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
User avatar
pgimeno
Party member
Posts: 2575
Joined: Sun Oct 18, 2015 2:58 pm

Re: multiple canvases alpha, not working ?

Post 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.
gcmartijn
Citizen
Posts: 50
Joined: Sat Dec 28, 2019 6:35 pm

Re: multiple canvases alpha, not working ?

Post 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
User avatar
pgimeno
Party member
Posts: 2575
Joined: Sun Oct 18, 2015 2:58 pm

Re: multiple canvases alpha, not working ?

Post 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.
gcmartijn
Citizen
Posts: 50
Joined: Sat Dec 28, 2019 6:35 pm

Re: multiple canvases alpha, not working ?

Post 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.
Post Reply

Who is online

Users browsing this forum: No registered users and 18 guests