[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] blitting from-to surface with per-pixel alpha doesn't work...



------ Original Message ------
> So, my problem is the following:
> I have four surfaces: screen, background, tank and its parts.
> The order of blitting: screen<-background and in another cycle
> screen<-tank<-parts. All surfaces are having per-pixel-data of course.
> 
> Despite of this, the result in the tank surface (the surface I blit into
> the parts) draws a strange black 'belt' around the parts, but other
> transparent areas of the surfaces are showing up well.
> 
I haven't tried doing what you are doing in pygame specifically, but it makes
a lot of sense to me.

Most drawing api's don't support what you are trying to do (drawing a number
of per-pixel alpha images into a temporary buffer), which is often called
"compositing" as opposed to blending... The problem is that the work to get
the alpha in the destination pixels correct is more expensive than the math to
simply alpha blend colors, so if the api did that all the time, it would run
slower than it needs to. 
Moreover, you blend colors differently (and much more expensively) if you
interprent the destination pixel as already having transparency - so even if
SDL spent the time to get the destination alpha to the right value for drawing
to a transparent intermediate layer, it would have to spend even more time to
get the color & alpha right when drawing partially transparent pixels on top
of partially transparent pixels (like where an antialiased edge overlaps
another)

So if pyGame/SDL could do what you want it to, I'm sure you'd probably have to
give it some kind of hint to let it know you wanted the more expensive math,
and I don't see any option like that.

As far as I know, SDL only has 2 ways it can blit RGBA to another RGBA suface
- the first is where it blends the colors, assumes the destination has no
transparency and sets the destination pixel's alpha opaque. The other is where
blending is disabled, and it just copies the pixel information including
alpha.

If I had to guess what's happening in your case, SDL is doing color blending,
so it's setting the alpha to fully opaque in all the pixels it blended to. So
the reason you get the black edge is because the original color of the surface
was black (even fully transparent pixels still must have a color value), so it
blended the color to black, then forced the pixel opaque. If you filled your
intermediate surface with transparent blue first RGBA(0,0,255,0), you'd
probably see a blue edge. So blending won't do what you want.

If you disabled the blending before blitting to the intermediate, the alpha
would copy (so you'd have no black edges), but that would mean all the places
where you have antialised pixels overlapping solid ones would come out
partially transparent with the top images color (so you'd see through the
edges of images that overlap others). so copying should be fine if the items
don't overlap.

..But if you really need to composite partially transparent on top of
partially transparent, I think you'd need to find/write some other function.
It's not hard to write one, and they are likely to perform very slowly
compared to pyGame/SDL blits, but I imagine that would be fine in your case.