I'm working with SDL1.2 and have been trying to find a solution to this problem for some time. I have an image with some transparency done through the SDL_SetAlpha() function. I want to draw that image to a surface and then draw that surface to the screen. The surface that I'm drawing to is filled with magenta and has its color key set to magenta. When I draw the transparent image to the surface, it is drawn onto the magenta surface, so when the surface is drawn to the screen, the image has gained a pink tint but the rest of the magenta is skipped because of the color key. Is there any way to draw a transparent image to an empty surface and then the screen without picking up the color key?
This produces a fully transparent surface, which is a start. But when I draw a partially-transparent image to the surface, the image gains a black tint and becomes opaque. The image is still blending with a black surface below it before the surface is drawn to the screen. How do I get it to not blend the image with the black? I guess I want the pixels on the surface replaced with the pixels in the image, and retain their partial transparency. I'm just using SDL_BlitSurface() to draw.
If you draw the same image multiple times at the same location the partially transparent areas will undoubtedly become more and more opaque. I'm not sure exactly what you want to happen or what the purpose of the transparent surface is. If you just want the image to show up on the screen why not draw it to the screen directly?
It's not becoming more opaque from redrawing the transparent image, it's gaining a black tint just like the pink tint in my image above.
The purpose of the transparent surface is a trail made of small dots that slowly fade out. I can draw them directly to the screen and that works fine, but there are some trails that I want to be permanent. Instead of drawing each dot in these permanent trails to the screen every frame, I want to draw them to a surface and then delete them to minimize the number of blit operations each frame.
Maybe it's just not possible to draw a transparent object to an intermediate surface and maintain transparency. But it would strike me as strange if you couldn't.
RGBA->RGBA with SDL_SRCALPHA
The source is alpha-blended with the destination using the source alpha channel. The alpha channel in the destination surface is left untouched. SDL_SRCCOLORKEY is ignored.
RGBA->RGBA without SDL_SRCALPHA
The RGBA data is copied to the destination surface. If SDL_SRCCOLORKEY is set, only the pixels not matching the colorkey value are copied.
The second thing is what I want. When I draw a transparent bitmap to the surface, I want to replace the pixels on the surface with the pixels in the bitmap. I don't want to blend the transparent bitmap with the surface, which will make the bitmap opaque and give it a tint of the color key.
Alright, I think I almost have it figured out. I looked a bit more closely into what SDL_DisplayFormatAlpha does:
This function can be used to convert a colorkey to an alpha channel, if the SDL_SRCCOLORKEY flag is set on the surface. The generated surface will then be transparent (alpha=0) where the pixels match the colorkey, and opaque (alpha=255) elsewhere.
So I'm now initializing my middle surface like this:
By using SDL_DisplayFormatAlpha, I convert all the color key pixels in the surface to transparent pixels. Then I can draw the transparent bitmap to the surface without it blending with what was the pink color key. So now I can draw a partially-transparent bitmap to a fully-transparent surface, then to the screen or any other surface, without losing the bitmap's transparency or gaining a pink tint.
The only problem I'm having now is I haven't been able to convert the bitmap to display format without ruining the transparency, but I'll keep going ahead and see if I actually get any noticeable performance issues without display format. If I don't, I won't worry about it. I have the effect I want.