Page 1 of 1

Replicating old "subtractive" blend mode [SOLVED]

Posted: Sat May 14, 2016 4:33 pm
by Chroteus
Hello, löve community,
To fully explain my problem, I'll explain how my game is set up.
To have a fog of war, I have a fully black canvas. I also have an image with transparent background with a white circle (edges smoothed out) in it.

Code: Select all

		
love.graphics.setCanvas(self.map.fow_canvas) -- the black canvas
love.graphics.setColor(0,0,0,255)
love.graphics.setBlendMode("subtractive")
-- FOW_PUNCH: the aforementioned image
love.graphics.draw(FOW_PUNCH, entity.x-FOW_PUNCH:getWidth()/2, entity.y - FOW_PUNCH:getHeight()/2)
love.graphics.setBlendMode("alpha")
love.graphics.setCanvas()
What this accomplished is it erased the part of canvas (where player walks). It looks the same as if you use eraser in any image editor on a black background with smooth brush.

Now here's the problem: In new version (0.10.1), the blend mode "subtract" does NOT modify alpha in any way, and none of the alpha blend modes accomplish the same thing as old "subtractive" blend mode.

I can use something like this (setCanvas functions left out):

Code: Select all

love.graphics.setColor(255,255,255,0)
love.graphics.setBlendMode("replace")
love.graphics.circle("fill", player.x, player.y, 300 )
And it accomplishes what is needed, kinda. The circle isn't smooth, resulting in a rough looking fog of war.

Re: Replicating old "subtractive" blend mode

Posted: Sat May 14, 2016 6:29 pm
by pgimeno
You can perhaps use multiply mode, and have the second image be 100% white and have a circular transparent hole instead. The white should preserve the original colours (not necessary in this case, since they are black, but that way it's usable in other cases), while the alpha should punch a hole in the black canvas when drawn.

You can mimic subtractive mode using a shader, if you absolutely must, but I think the effect you're after is best accomplished the above way.

Code: Select all

local SubtractiveBlend = love.graphics.newShader[[
  extern Image dst;

  vec4 effect(vec4 colour, Image texture, vec2 texpos, vec2 scrpos)
  {
    vec4 src = Texel(texture, texpos);
    return Texel(dst, scrpos) - src * src.w;
  }
]]

...
SubtractiveBlend:send('dst', yourCanvas)
Edit: Attached proof of concept of the multiplicative method described above.

Re: Replicating old "subtractive" blend mode

Posted: Sun May 15, 2016 11:52 am
by Chroteus
Didn't think about using multiply with inverted image, still wrapping my head around blend modes.
Thanks a lot, pgimeno! :ultrahappy: