Page 1 of 1

Drawing one canvas on top of another?

Posted: Sun Sep 19, 2021 4:30 am
by m0nkeybl1tz
Right now, I'm working on an effect where the player leaves a trail as they walk. I want the trail to be persistent so I don't clear it every frame, but I also want it to have some transparency and the problem is that the trail keeps drawing on top of itself every frame until it's no longer transparent.

I had a (maybe weird) solution, where I'd have a second canvas that tracks where the player's already walked, and multiply the trail in the first canvas by the value (0 or 1) in the second canvas to determine whether the trail needs to be drawn or not.

For example, I want to add to the trail at the player's current position:
path1.png
path1.png (5.67 KiB) Viewed 4699 times
But I don't want to add to it if they've already been there, so I keep track of where they've been in black:
path2.png
path2.png (6.72 KiB) Viewed 4699 times
I then multiply the trail by the value of the path canvas to mask out any areas they've already been:
path3.png
path3.png (5.65 KiB) Viewed 4699 times
My idea was to draw the trail to a temporary canvas, save the second canvas as an ImageData, then draw the ImageData to the temporary canvas using love.graphics.newImage like so:

Code: Select all

    love.graphics.setCanvas(tempcanvas)
        pathdata = pathcanvas:newImageData( ) --convert the path canvas into ImageData
        love.graphics.setColor(1, 1, 1, .5)
        love.graphics.circle('fill', x, y, 10)  --draw a transparent circle to the tempcanvas
        love.graphics.setBlendMode("multiply","premultiplied") --switch to a multiply mode
        love.graphics.newImage(delaydata) --draw the path on top of the tempcanvas
I know the path canvas is updating correctly, because if I draw it directly, it looks correct. However nothing shows if I try converting it to an ImageData and drawing it onto another canvas like so:

Code: Select all

    love.graphics.setCanvas(tempcanvas)
        pathdata = pathcanvas:newImageData( ) --convert the path canvas into ImageData
        love.graphics.newImage(delaydata) --draw the path on top of the tempcanvas
Do you all know is there a way to draw a Canvas on top of another Canvas? Or if not, is there a better way to do what I'm thinking?

Re: Drawing one canvas on top of another?

Posted: Sun Sep 19, 2021 5:39 am
by BrotSagtMist
Uhm. Newimage returns the image, its not drawing it. Maybe you meant: draw(newimage(delaydata)) instead?
There is no conversation needed anyway, for most task a canvas can be used like a picture.

I gather what you actually want is to:
paint a circle to a canvas depending on where the player stands to create a trail.
apply transparency to the whole drawing using love.graphics.setColor(1,1,1,.5)
and then simply draw the trail canvas as half transparent using love.graphics.draw(canvas)

Re: Drawing one canvas on top of another?

Posted: Sun Sep 19, 2021 6:39 am
by Eglaios
To draw a canvas on top of another, you just need to keep track of the canvas #1, set the canvas#2, then when finished with the #2, call the #1 back, then draw #2 on it (I think), something like this :

Code: Select all

local canvas1 = love.graphics.newCanvas(...)
local canvas2 = love.graphics.newCanvas(...)

love.graphics.setCanvas(canvas1)
 local current_canvas = love.graphics.getCanvas() --Store current canvas(canvas1) for later
 love.graphics.setCanvas(canvas2)
  love.graphics.draw(StuffOnCanvas2)
  
 love.graphics.setCanvas(current_canvas)  --Get back on canvas1
 love.graphics.draw(canvas2) --Draw canvas2 on canvas1

love.graphics.setCanvas()
love.graphics.draw(canvas1)

Re: Drawing one canvas on top of another?

Posted: Sun Sep 19, 2021 7:46 pm
by m0nkeybl1tz
Ah yup, looks like I forgot to actually draw the ImageData. Duh :death:

Thanks for the help!