Other ways than shaders for transparent color?

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
Eglaios
Prole
Posts: 36
Joined: Mon May 03, 2021 8:45 pm

Other ways than shaders for transparent color?

Post by Eglaios »

I'd want to make an overlay transition like this one :
(at 0:26)

Well that guy really seems to enjoy Pokémon...

Here's what I planned to do :
-Create a canvas with window dimensions, make it all black using love.graphics.clear
-Draw a white circle that'll shrink over time on this canvas
-Render the canvas with a shader to make the white area transparent.

I'd like to know if there'd be a way to do this while avoiding shaders...


Thank you!
Currently working on game music...
User avatar
BrotSagtMist
Party member
Posts: 607
Joined: Fri Aug 06, 2021 10:30 pm

Re: Other ways than shaders for transparent color?

Post by BrotSagtMist »

You can just draw transparent as a normal colour.
It happens we just had that already too: https://love2d.org/forums/viewtopic.php?f=14&t=92033
TL:DR:
love.graphics.setBlendMode("replace")
love.graphics.setColor(0,0,0,0)
obey
Eglaios
Prole
Posts: 36
Joined: Mon May 03, 2021 8:45 pm

Re: Other ways than shaders for transparent color?

Post by Eglaios »

BrotSagtMist wrote: Thu Sep 23, 2021 10:11 pm It happens we just had that already too: https://love2d.org/forums/viewtopic.php?f=14&t=92033
Thank you for pointing it out, I didn't read that far into this...
Should I delete this topic, then?
Currently working on game music...
MrFariator
Party member
Posts: 509
Joined: Wed Oct 05, 2016 11:53 am

Re: Other ways than shaders for transparent color?

Post by MrFariator »

You can also use stencils to achieve this same effect, which may be useful for more complex shapes than simple circles. You'll just have to define a stencil function that draws a circle shape, shrink it over time, and everything this circle is not touching gets rendered. So when the rectangle is being drawn with the stencil function active, it'd punch a hole in it.

Here's some sample code that draws a rectangle with a hole in it (untested):

Code: Select all

local myStencilFunc = function ()
  love.graphics.circle ( "fill", 100, 100, 50 ) -- shrink/increase these values over time to change the hole's size
end

function love.draw()
  -- increment the stencil value of every pixel that touches the stencil function's circle
  love.graphics.stencil(myStencilFunc, "increment", 1)

  -- Only allow rendering of pixels which have a stencil value less than 1.
  love.graphics.setStencilTest("less", 1)

  -- for testing purposes, lets draw the rectangle with a hole in it red
  love.graphics.setColor  (1, 0, 0, 1)
  love.graphics.rectangle ("fill", 0, 0, 200, 200)

  love.graphics.setColor  (1, 1, 1, 1)
  love.graphics.setStencilTest()
end
The resulting output should look roughly like this (the black area should show whatever it is that's being rendered behind the red rect):
Image
Last edited by MrFariator on Thu Sep 23, 2021 10:31 pm, edited 2 times in total.
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Other ways than shaders for transparent color?

Post by pgimeno »

Edit: Ninja'd by MrFariator but I think this post may still be useful.

A shader will work quite well; but if you really must avoid it, one alternative is a stencil.

Code: Select all

local totalTime = 2
local objects = {}
local speed = 600
local effect = false
local canvas = love.graphics.newCanvas()
local T = 0

local function newObject()
  return {love.math.random(0, love.graphics.getWidth()-1),
          love.math.random(0, love.graphics.getHeight()-1)}
end

for i = 1, 10 do
  objects[i] = newObject()
end

function love.keypressed(k)
  if k == "escape" then return love.event.quit() end
  if k == "space" then T = totalTime; effect = true end
end

local function circle()
  local hw, hh = love.graphics.getWidth()/2, love.graphics.getHeight()/2
  if T > 0 then
    love.graphics.circle("fill", hw, hh, T/totalTime*math.sqrt(hw*hw + hh*hh))
  end
end

function love.update(dt)
  if T > 0 then
    T = T - dt
  end
  for i = 1, #objects do
    local obj = objects[i]
    obj[1] = obj[1] + (math.random() - 0.5) * dt * speed
    obj[2] = obj[2] + (math.random() - 0.5) * dt * speed
  end
end

function love.draw()
  love.graphics.setCanvas(canvas)
  love.graphics.clear(.5, .5, .5)
  for i = 1, #objects do
    local obj = objects[i]
    love.graphics.rectangle("fill", obj[1], obj[2], 8, 8)
  end
  love.graphics.setCanvas()

  if effect then
    love.graphics.stencil(circle)
    love.graphics.setStencilTest("gequal", 1)
  end
  love.graphics.draw(canvas)
  love.graphics.print(T)
end
Edit: Another alternative is to use two canvases. This is better in that any antialiasing that the circle gets, goes to the final result; however I don't think there's any antialiasing for filled circles anyway. In the example above, modify the initialization to create two canvases instead of one:

Code: Select all

local canvasRender = love.graphics.newCanvas()
local canvasCrop = love.graphics.newCanvas()
then modify love.draw as follows:

Code: Select all

function love.draw()
  love.graphics.setCanvas(canvasRender)
  love.graphics.clear(.5, .5, .5)
  for i = 1, #objects do
    local obj = objects[i]
    love.graphics.rectangle("fill", obj[1], obj[2], 8, 8)
  end
  love.graphics.setCanvas()

  if effect then
    love.graphics.setCanvas(canvasCrop)
    love.graphics.clear(0,0,0,0)
    circle()
    love.graphics.setCanvas(canvasRender)
    love.graphics.setBlendMode("multiply", "premultiplied")
    love.graphics.draw(canvasCrop)
    love.graphics.setCanvas()
    love.graphics.setBlendMode("alpha", "alphamultiply")
  end
  love.graphics.draw(canvasRender)
  love.graphics.print(T)
end
grump
Party member
Posts: 947
Joined: Sat Jul 22, 2017 7:43 pm

Re: Other ways than shaders for transparent color?

Post by grump »

pgimeno wrote: Thu Sep 23, 2021 10:29 pm however I don't think there's any antialiasing for filled circles anyway
Draw a filled circle, then a line circle with the same radius. Or enable MSAA for the circle canvas.
Post Reply

Who is online

Users browsing this forum: No registered users and 45 guests