Page 1 of 1

[SOLVED] Canvas remains empty despite drawing operations

Posted: Mon Mar 06, 2017 1:56 pm
by entuland
Hello,
I've stomped on a strange behavior where a canvas retained the last drawing operation only (as if it got cleared at every love.draw() run).

Trying to reproduce the issue on a reduced program, I've stomped on a different (but perhaps connected) weird behavior where the same operations get performed on two canvases, the first canvas retains all data and works fine while the second remains completely blank.

Here is the code:

Code: Select all

local handler = {}

function handler.load()
  handler.canvas1 = love.graphics.newCanvas(100, 100)
  handler.canvas2 = love.graphics.newCanvas(100, 100)
  
  love.graphics.setCanvas(handler.canvas1)
  love.graphics.clear(255, 0, 0)
  love.graphics.print("this is canvas 1")
  
  love.graphics.setCanvas(handler.canvas2)
  love.graphics.clear(0, 255, 0)
  love.graphics.print("this is canvas 2")
end

function handler.update()
  handler.randomLine(handler.canvas1)
  handler.randomLine(handler.canvas2)
end

function handler.randomLine(canvas)
  love.graphics.setBlendMode("alpha")
  love.graphics.setCanvas(canvas)
  local l = {
    x1 = math.random(20, 80),
    y1 = math.random(20, 80),
    x2 = math.random(20, 80),
    y2 = math.random(20, 80),
    r = math.random(192, 255),
    g = math.random(192, 255),
    b = math.random(192, 255),
  }
  love.graphics.setColor(l.r, l.g, l.b)
  love.graphics.line(l.x1, l.y1, l.x2, l.y2)
end

function handler.flipCanvas(canvas, x, y)
  love.graphics.setBlendMode("alpha", "premultiplied")
  love.graphics.setColor(255, 255, 255)
  love.graphics.draw(canvas, x, y)
end

function handler.draw()
  love.graphics.setCanvas()
  love.graphics.setBlendMode("alpha")
  love.graphics.clear(0, 0, 255)
  handler.flipCanvas(handler.canvas1, 10, 10)
  handler.flipCanvas(handler.canvas2, 120, 120)
end

local game = {}

function love.load()
  game.handler = handler
  game.handler.load()
end

function love.update(dt)
  game.handler.update(dt)
end

function love.draw()
  game.handler.draw()
end
And here is what I get to see running the above code:
lua-canvas-test.png
lua-canvas-test.png (13.29 KiB) Viewed 3763 times
That is, canvas1 gets drawn, canvas2 appears as just a black square.

Any advice about how to troubleshoot the issue?

Thanks for your attention, cheers!

[Solution: since love.graphics.clear() gets called between love.update() and love.draw(), the currently active drawing target (in my case handler.canvas2) gets blanked out; the solution is to reset the drawing target with love.graphics.setCanvas() before getting into love.draw() or to refactor the code to use a different approach, see messages below for the details]

Re: Canvas remains empty despite drawing operations

Posted: Mon Mar 06, 2017 2:12 pm
by 0x72
This is because after love.update and before love.draw the love.graphics.clear is called.

https://love2d.org/wiki/love.run

Code: Select all

-- ...
  if love.update then love.update(dt) end
 
  if love.window and love.graphics and love.window.isCreated() then
    love.graphics.clear() -- <- HERE
    love.graphics.origin()
    if love.draw then love.draw() end
    love.graphics.present()
  end
-- ...
In order to fix that you can do one of those:
- move your drawing to from love.update (and love.load) to love.draw (best option)
- alter your love.run so it resets target back to screen before the love.graphics.clear (love.graphics.setCanvas())
- alter your love.update so it resets target back to screen just before it finish (love.graphics.setCanvas())

Re: Canvas remains empty despite drawing operations

Posted: Mon Mar 06, 2017 2:25 pm
by entuland
0x72, thanks a lot for the insight, now the issue is fully clear and this will surely help me sort out the original issue as well.

I think I'll go with :renderTo() - as advised on the #love irc channel - so that I don't have to mess with setCanvas() at all, seems the safest option so far.

Thanks again 0x72!

Re: [SOLVED] Canvas remains empty despite drawing operations

Posted: Mon Mar 06, 2017 2:38 pm
by zorg
For the sake of completion, as mentioned on IRC as well, the real issue was that the render target was never set back to the window, it was on the second canvas when love.update ended, meaning the love.graphics.clear call in love.run cleared that canvas, instead of the window; putting a love.graphics.setCanvas() at the end of love.update would have solved it as well, but renderTo is safer in that regard.

Re: [SOLVED] Canvas remains empty despite drawing operations

Posted: Mon Mar 06, 2017 6:04 pm
by entuland
zorg, yep, I mentioned that as part of the solution editing the original post, thanks for the feedback on IRC too :)