Page 1 of 1

Having issues fading things out gradually

Posted: Sun Oct 10, 2021 3:54 am
by m0nkeybl1tz
Hey all, having a weird issue and I'm not exactly sure what's wrong. I want to have an effect where a canvas gets darker over time, and my solution has been to switch to Subtract blend mode, and draw a white rectangle at low opacity. The problem is, if the opacity goes too low it doesn't draw at all. The cutoff seems to be an alpha value of .004. Anything above that will draw, anything below that won't. Is there any reason for this cutoff? Any way around it? Or is there a better way to fade things out slowly?

Re: Having issues fading things out gradually

Posted: Sun Oct 10, 2021 6:10 am
by zorg
if your canvas is 8bit rgba (which is the default), regardless of what number you set with setColor, it can only go in increments of 1/256, or 0.0039, so what you're seeing is the result of that quantization.
I can think of two ways to get around this; either use a canvas that has more bits per color component (with which the transition might still not be fully visible on screen though, due to monitors also having a specific bit depth), or control the speed of the effect differently, e.g. do one "shade" every 2 frames instead of every frame.

Re: Having issues fading things out gradually

Posted: Sun Oct 10, 2021 6:28 am
by pgimeno
Since Zorg already explained the reason while I was typing, I'll go into more details for possible solutions.

Yes, there are other ways to make a fade out effect. Have the alpha controlled by dt, like this:

Code: Select all

local fadealpha = 1.0
local fading = false -- set to true to start fading
local fadespeed = 1/2 -- adjust appropriately (use 1/seconds)

function love.update(dt)
  if fading then
    fadealpha = math.max(0, fadealpha - dt * speed)
  end
end
and then here's two possible ways:

Method 1: Draw to a canvas instead of to the screen, and draw the canvas with the fade alpha.

Code: Select all

function love.draw()
  love.graphics.setCanvas(canvas)
  love.graphics.clear(0, 0, 0, 0)
  myDraw()
  love.graphics.setCanvas()
  love.graphics.setBlendMode("alpha", "premultiplied")
  love.graphics.setColor(1, 1, 1, fadealpha)
  love.graphics.draw(canvas)
  love.graphics.setBlendMode("alpha", "alphamultiply")
  love.graphics.setColor(1, 1, 1, 1)
end
Method 2: Draw normally and then draw a black rectangle with 1 - the fade alpha.

Code: Select all

function love.draw()
  myDraw()
  love.graphics.setColor(0, 0, 0, 1 - fadealpha)
  love.graphics.rectangle("fill", 0, 0, love.graphics.getDimensions())
  love.graphics.setColor(1, 1, 1, 1)
end
Both methods will quantize to 256 levels, though, and since that's the colour resolution of the display, the only way around that quantization is to use some kind of dithering to darken only some pixels every frame. However normally that's enough.

Re: Having issues fading things out gradually

Posted: Mon Oct 11, 2021 5:24 am
by zorg
An implementation to the "darken only some pixels every frame" by pgimeno would be to have a screen-sized image where N% of pixels are transparent, and (1-N)% of them are not (color up to your choice, probably black) - this won't work if you want to support multiple resolutions though (or want to control the percentage dynamically), so a different approach could be using a simple-ish shader that does the same thing in a resolution-independent manner. (i will add that as far as i know, doing randomness on the gpu is not an exact science, but there's probably some boilerplate one can lift that does relatively uniform randomness - if it's not uniform on the whole screen, it will look kind of bad.)

Re: Having issues fading things out gradually

Posted: Mon Oct 11, 2021 9:30 pm
by m0nkeybl1tz
Ah that's hilarious, that explanation totally makes sense. The extra challenge I have is I actually want the screen to be constantly darkening -- not fading out between 100% opacity and 0% so I can't use a fixed timer. However, I think the suggestion of fading it out every x frames instead of every frame should work. I do like the dithering idea as well, but I think just doing it every few frames should work for now.

Thanks!

Re: Having issues fading things out gradually

Posted: Tue Oct 12, 2021 12:56 am
by pgimeno
You can't have it constantly darkening. You can make it fade with an inverse exponential curve, that is, multiply fadealpha by a factor every frame, and then it will never reach zero; but it will eventually be under 1/255, and then everything will be black.

Well, unless you draw something else.