I have a game that has simple particles (basically dots) moving around the screen leaving a trail.

My ultimate goal is to be able to change the opacity of the solid black fading texture each drawing call in a way so that I can keep the length of a particle with trails (using a accumulation buffer) is the same even though the particle movement might move with time-stepping. The way I render my particles is I render the current frame based on the particles position, lets call this texture A. Then I take the previous frame and draw a solid black texture over it with set opacity in order to fade this, lets call this texture B. Then I draw texture A over texture B. This way the particle leaves a trail based on where it has been. I am currently time-stepping the movement of the particles so that no-mater how much latency their is it always moves the same speed (considering real-world time).

In essence I want to be able to say say that the particle trial will always be 100 pixels (considering the particle moves 60 pixels in a second) , and have it be that way even if the frame-rate drops. Currently when the frame rate drops the accumulation buffer gets run less times and thus the trail is longer the more latency their is.

The information I need to know to do this is how exactly does fading work. Because I need to change the opacity of the black texture in a way that allows it to fade more when the accumulation buffer is called less times per second, and fade less when it is called many times per second. Right now I really dont understand what happens to a pixel when a black texture with a specific opacity is on it.

Here is some data I collected.

Data 1: This is a chart of the particle trails. The x axis represents the FPS it was running at, and the y axis is how many pixels long the trail was. On the left it says what opacity the black texture used in the accumulation buffer was. Graph You can find all the data, and some best fit line formulas at here (on desmos)

It is important to note I stopped counting after V was lower then 20 since the difference between colors starts getting really small.

some things I noticed about this is that their seems to be either a exponential or division relationship between the numbers. Also I noticed that their were segments for each frame before it was faded, and that the amount of them that were visible were about the same no-mater the fps when considering the same opacity of the black texture.

Data 2: I recreated what I thought was going on with a fading texture with paint.net. I made a 100x100 picture and colored it red. I then added a layer with one black pixel at an opacity of 25/255 then I duplicated this and added another pixel, basically I created a gradient. Then I went through and labeled each pixel considering its rounded darkness (in hsv color space). Then labeled the difference between the darkness values.

enter image description here enter image description here Unfortunately from this I didnt learn much. Just reaffirmed that it is a non linear relationship. And I also noticed if I did the fade one more time that all the darkness values shifted to the square next to them. So I could predict the darkness values if I knew how many times the fade had been applied.

  • So what happens when a semitransparent black texture is blended over another one?
  • If you are willing to put in some extra thought what would a formula be that would give me the opacity the black texture needs to be in order to make the particle trail be about 'N' pixels long, given the dt since last frame?

1 Answer 1


The basic equation for alpha blending is as follows:

$$ c_\text{final} = c_\text{source} \cdot \alpha + c_\text{dest} \cdot (1 - \alpha) $$

Here, $c_\text{source}$ is the color of the thing being blended, $c_\text{dest}$ is the background onto which you're blending it, and $\alpha$ is between 0 and 1.

In your case, $c_\text{source} = 0$ (black fading texture), so blending black $n$ times over a background reduces to

$$ c_\text{final} = c_\text{dest} \cdot (1 - \alpha)^n $$

which is indeed an exponential falloff as you guessed. You can plug this formula in and get numbers pretty similar to those you posted (although when I did it, my results were off by one or two—maybe due to rounding differences; I'm not sure).

Regarding your problem of making the trails appear the same regardless of framerate, a simple approach is to run the accumulation buffer passes multiple times per frame if necessary, so that there's effectively a fixed timestep for the trail regardless of framerate. That will probably give better-looking results than attempting to fiddle with the alpha based on the framerate. It might be too slow, though.

A potentially more efficient approach would be to have the particles spawn a new "trail particle" every so often, where each trail particle stays fixed in position, with its alpha going from 100% to 0 over some length of time (and then it gets recycled). You have to re-render all the particles every frame, but it could end up being faster overall if the overhead of the full-screen blending passes for the accumulation buffer get to be too high.

I should point out though that all of these approaches actually perform time-based fading, not distance-based as you asked for (100-pixel trails). If all the particles move at the same speed, you can just tweak the fade time to make the trails the desired length, but if different particles move at different speeds, then you would need to account for that when setting the fade times for their trails. There's also no trivial way to do that with the accumulation buffer approach, since it implicitly uses the same fade time for everything on the screen.

  • $\begingroup$ Thanyou so much! Now I know the how alpha blending works and fixed the particle stuff! The solution I found worked best was making sure the function got called 60 times a second regardless of the framerate. Thankyou much! $\endgroup$
    – J.Doe
    Dec 29, 2015 at 23:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.