Replicating old "subtractive" blend mode [SOLVED]

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
Chroteus
Citizen
Posts: 87
Joined: Wed Mar 20, 2013 7:30 pm

Replicating old "subtractive" blend mode [SOLVED]

Post by Chroteus » Sat May 14, 2016 4:33 pm

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.
Last edited by Chroteus on Sun May 15, 2016 11:53 am, edited 1 time in total.

User avatar
pgimeno
Party member
Posts: 2335
Joined: Sun Oct 18, 2015 2:58 pm

Re: Replicating old "subtractive" blend mode

Post by pgimeno » Sat May 14, 2016 6:29 pm

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.
Attachments
mask.love
(142.68 KiB) Downloaded 101 times

User avatar
Chroteus
Citizen
Posts: 87
Joined: Wed Mar 20, 2013 7:30 pm

Re: Replicating old "subtractive" blend mode

Post by Chroteus » Sun May 15, 2016 11:52 am

Didn't think about using multiply with inverted image, still wrapping my head around blend modes.
Thanks a lot, pgimeno! :ultrahappy:

Post Reply

Who is online

Users browsing this forum: No registered users and 33 guests