Page 1 of 1

Overlay

Posted: Sat May 30, 2020 10:26 pm
by tobiasvl
Hey, I don't really understand blend modes, and am wondering if this is possible.

I'm drawing a monochrome white and transparent black canvas, and I want to overlay that with a colored image. The transparent black parts of the canvas should stay transparent black, but the white parts should take on the colors of the overlay. Is this possible?

The overlay is currently a PNG image that's transparent wherever I don't want the color affected, and the other parts are solid colors. I can change that, of course.

Re: Overlay

Posted: Sun May 31, 2020 12:11 am
by pgimeno
I'm not sure I'm understanding, but doesn't "multiply", "premultiplied" do this?

Re: Overlay

Posted: Sun May 31, 2020 6:16 pm
by tobiasvl
Maybe? I have no idea. Where would I set that blend mode, before drawing the canvas or the overlay? I guess my main problem is that I have no idea how blend modes work, lol. None of the ways I try work, but I'm just doing it blindly here. Are there any good tutorials on blending?

Re: Overlay

Posted: Mon Jun 01, 2020 10:08 am
by pgimeno
If I understood what you're after I would be able to give you better advice.

For colours, white (or full intensity of a given component) counts as 1.0, black counts as 0.0; for alpha, fully opaque counts as 1.0 and transparent as 0.0. That's the value that gets multiplied by the given component.

This means that with multiply blend mode, everything transparent will remain transparent (per the alpha multiplication) and everything of a certain colour will remain that colour when applied to a white background (per the multiplication of the colour components by 1).

But if the image you're drawing on the white circle has alpha, that alpha will result in the trimming of the other alpha when multiplied, which does not seem what you want. So, this method can be used on an image which has a white background.

But I don't know what you have exactly and what you want exactly.

Re: Overlay

Posted: Mon Jun 01, 2020 8:41 pm
by tobiasvl
Yeah, I think I confused myself too. Sorry.

Basically, I want to combine two images/canvases. One is monochrome black and white, and the other is a background that "tints" the white parts of the first one. But then I want to overlay that combined canvas on top of another background again, where the black parts are now transparent and show the final background.

I didn't really explain that final part, sorry about that, I just said the first canvas had a "transparent black" background.

See this image for a simplified visualization:
love2d-overlay.png
love2d-overlay.png (3.62 KiB) Viewed 13320 times

Re: Overlay

Posted: Tue Jun 02, 2020 4:29 am
by FloatingBanana
Maybe love.graphics.stencil can do it.

Re: Overlay

Posted: Tue Jun 02, 2020 12:38 pm
by tobiasvl
Thank you! Stencil looks exactly like what I want.

Re: Overlay

Posted: Tue Jun 02, 2020 3:59 pm
by pgimeno
OK, so I assume that the black and white image is a mask, the blue image is the background, and the red image is the one you want to draw over the background using the mask.

This works for me:

Code: Select all

local bg = love.graphics.newImage('mountain-and-lake-landscape-800x600.jpg')
local fg = love.graphics.newImage('image1.jpg')
local mask = love.graphics.newImage('Circle.png')
local canvas = love.graphics.newCanvas()

local x, y
local a = 0

-- In the Circle.png image, the circle is at 570, 370 with a size of 460x460.
function love.update(dt)
  a = a + dt
  x = (math.sin(a * 1.5) + 1) / 2 * (love.graphics.getWidth() - 460) - 570
  y = (math.sin(a * 2) + 1) / 2 * (love.graphics.getHeight() - 460) - 370
end

function love.draw()
  love.graphics.setCanvas(canvas)
  love.graphics.setBlendMode('replace', 'premultiplied')
  love.graphics.draw(fg)
  love.graphics.setBlendMode('multiply', 'premultiplied')
  love.graphics.draw(mask)
  love.graphics.setCanvas()

  love.graphics.setBlendMode('replace', 'premultiplied')
  love.graphics.draw(bg)
  love.graphics.setBlendMode('alpha', 'alphamultiply')
  love.graphics.draw(canvas)
end
See attached demo.

The stencil has the problem that the borders have no antialiasing.

Re: Overlay

Posted: Tue Jun 02, 2020 4:29 pm
by grump
Another solution using a shader:

Code: Select all

local lg = love.graphics
local red, blue, mask = lg.newCanvas(), lg.newCanvas(), lg.newCanvas()
red:renderTo(function() lg.clear(1, .2, .2) end)
blue:renderTo(function() lg.clear(.2, .2, 1) end)
mask:renderTo(function() lg.circle('fill', 200, 200, 100) end)

local maskShader = lg.newShader([[
	uniform Image imageA, imageB;

	vec4 effect(vec4 color, Image mask, vec2 uv, vec2 fc) {
		return color * mix(Texel(imageB, uv), Texel(imageA, uv), Texel(mask, uv));
	}
]])

function love.draw()
	lg.setBlendMode('alpha', 'premultiplied')
	lg.setShader(maskShader)
	maskShader:send('imageA', red)
	maskShader:send('imageB', blue)
	lg.draw(mask)
end

Re: Overlay

Posted: Fri Jun 05, 2020 12:03 pm
by tobiasvl
Thanks a lot, that blend example helped. The shader is also very interesting, haven't really looked too much into shaders yet. Stencil seems to do the job for me at the moment (aliasing isn't an issue right now) but I'll experiment a bit. Thanks again!