0

While working on a particle engine in SDL, I stumbled over the following problem:

After implementing a frame interpolation technique as described here (Step 6: Optimization, I'm basically drawing the last frame with an alpha of 254 to the current frame) so that it fades out), I noticed that some pixels which were supposed to gradually fade from white to black, ended up staying gray, with rgba values of 112 to be precise. After doing some math I've found what's causing this: every frame I multiply the rgba values of the last frame by 254/255, which works fine up to and excluding 112.

Then something funny happens. When you do the following: round(112/255*254)=112, the values will stay the same (I'm rounding the number because the end value is to be stored as an 8bit color value of a pixel), meaning that my fading technique using alpha doesn't work anymore. The problem is that I would like these gray pixels which stay at 112 to fade out further. The question is, how would I achieve such a thing within SDL?

I know I could just make the value of 254 lower so that this sort of minimum decreases but I would like my particles to fade out really gently (I'm making a 60fps game). I've also considered creating an OpenGL graphics engine myself (so that I could use floating point textures, which do have to precision I need in this case), but I'm simply not good enough at OpenGL and lack the time to do such a thing. The reason I need to use a texture for storage is that I would like to have particles which emit trails (as if you stopped clearing your frame buffers and you moved an object, but instead of the screen becoming a mess the older pixels would fade out)

                currentFrame->renderTo();//Draw to the current frame rendertarget
                graphics.clear(Color(0,0,0,0)); //Clear the screen using the given color
                graphics.scale=1.0f; //Manipulate pixel size (for visible pixel art)
                SDL_SetTextureBlendMode(lastFrame->texture, SDL_BLENDMODE_NONE); 
                //Set blendmode to opaque
                graphics.drawTexture(lastFrame,graphics.camera.position,Color(255,255,255,254));
                //Draw the last frame 
                SDL_SetTextureBlendMode(lastFrame->texture, SDL_BLENDMODE_BLEND);
                //Revert blendmode to alpha blending
tbvanderwoude
  • 587
  • 6
  • 17

1 Answers1

1

I would use a global float variable called 'decay' to store the non-rounded alpha value.

float decay = 255.0;
[...]
decay  = decay / 255.0 * 254.0;
Uint8 alpha = round(decay);

If you need one 'decay' value per pixel then you could declare a struct for a particle:

typedef struct {
    int active;
    float x,y;
    float dx,dy; // directions for x and y
    float decay;
    Uint8 r,g,b,a; // colour
} s_dots;

s_dots dots[MAX_NUMBER_OF_DOTS];
Joseph Paul
  • 346
  • 1
  • 7
  • This is indeed the kind of solution I'm looking for, but the problem is that every pixel has it's own (decayed) alpha value (For instance, the newly drawn pixels of the current frame have an alpha value of 255, while the old frame get's faded), meaning that a single alpha value won't suffice. – tbvanderwoude Jun 28 '16 at 12:51
  • By pixels I was actually referring to the pixels belonging to the buffer, not particle object (I've updated the question for clarity's sake). The problem is that this technique would require me to maintain many structs for each particle (of which some 40 could be present at the time). I cannot accept this as a solution, but I do thank you for the effort of trying to help me. – tbvanderwoude Jun 28 '16 at 13:29