Page 1 of 1

Issues with canvases and blendmodes

Posted: Wed May 03, 2023 9:43 pm
by Bobble68
Hello again Lövely people, I once again have an issue I can't figure out.

To preface, I know that the method I'm using definately isn't perfect, but it 'works' for me as is.

Some of you might remember a while back I was trying to draw polygons in a pixelated style, which I have managed to do by generating canvases. Issue is, I'm getting some blending issues now. Generating the image itself isn't having any issues, but drawing it creates this black outline, which I'm aware should be able to be fixed by setting the correct blend mode.
border.png
border.png (254.43 KiB) Viewed 1090 times
The wiki says 'The "premultiplied" constant should generally be used when drawing a Canvas to the screen', however, it looks like this when I set it to that:
border.png
border.png (306.87 KiB) Viewed 1090 times
What am I doing wrong here?

Re: Issues with canvases and blendmodes

Posted: Thu May 04, 2023 1:04 pm
by pgimeno
Could you give a short runnable example? It's hard to understand what you're doing to obtain that result.

Re: Issues with canvases and blendmodes

Posted: Thu May 04, 2023 3:59 pm
by Bobble68
I had a go at recreating it in a new project and found that I couldn't - after some investigating I realised the main issue is that I got my own code confused, though I am still left with some questions.

The polygons have an overlay on top of them which is very similar, however its slightly transparent. Disabling it got rid of the white issue (the black outline was me getting my code mixed up), however I've found that making it transparent with setColour is what causes it to go white. Why is this? On it's own with the base layer disabled is displays fine, but not when both are drawn.

Code: Select all

function love.load()
  
  love.graphics.setDefaultFilter("nearest", "nearest")
  
  canvas1 = love.graphics.newCanvas(64,64)
  canvas2 = love.graphics.newCanvas(64,64)
  
  
  canvas1:renderTo(function()
      love.graphics.setColor(1,0,0)
      love.graphics.circle("fill", 32,32, 16)
      
      end
    )
  canvas2:renderTo(function()
      love.graphics.setColor(0,1,0)
      love.graphics.circle("fill", 32,32, 16)
      
      end
      )


end


function love.draw()
  
  love.graphics.setBackgroundColor(0.5,0.7,1)
  love.graphics.setColor(1,1,1)
  love.graphics.draw(canvas1, 0, 0, 0, 10, 10)
  love.graphics.setColor(1,1,1,0.2)
  love.graphics.setBlendMode("alpha", "premultiplied")
  love.graphics.draw(canvas2, 10, 0, 0, 10, 10)
  love.graphics.setBlendMode("alpha")

end
This isn't getting the exact same results but they're similar.

Edit: I forgot to mention, the original black line is caused by the linear filter, so it can only be fixed by using the premultiplied blend mode or using nearest (which doesn't look great).

Re: Issues with canvases and blendmodes

Posted: Thu May 04, 2023 9:01 pm
by pgimeno
About the black line, there's this related thread: viewtopic.php?f=4&t=92108

About your last example, I don't understand what the problem is. This is the image I get:
SnippetResult.png
SnippetResult.png (1.11 KiB) Viewed 992 times
Edit: Oh I think I get it. You expect a normal blend. With premultiplied rendering, you need to premultiply the colour in the setColor call by the alpha, so instead of this:

Code: Select all

love.graphics.setColor(1,1,1,0.2)
you need to multiply all components by the alpha, in this case:

Code: Select all

love.graphics.setColor(0.2,0.2,0.2,0.2)
In general, instead of love.graphics.setColor(r, g, b, a) you would do love.graphics.setColor(r*a, g*a, b*a, a).