I am writing a 2D 16 bpp arcade game, It uses the allegro graphics lib.
I have certain sprites (explosions, glows) which are drawn against a
black background, when I blit these against a different background the
sprite's edges do not blend with the background and the sprite
looks bad, I am not talking about anti-aliasing here, I am talking
about reading rgb of source pixel and combining it with rgb of destination
pixel to make it look natural (the way it has been drawn against black
background).
for achieving this I got some helpful code from chris's page
which did alpha and additive blending, the problem is if I additively blend
my sprite with background it looks fine against dark backgrounds but
looks totally bright against bright backgrounds.the problem with alpha
blending is that it completely kills intensity of colors.
equation for additive blending is r3=r1+r2; if (r3>255) r3=255;
equation for alpha blending is
alpha=(2*r1+3*g1+b1)/6;
r3=((r1*alpha)+(r2*(255-alpha)))/256;
equation for screen blending is r3 = r1 + r2 - ((r1*r2) / 100);
where r1 is sprite color, r2 is background color, r3 is result (blended) color.
The right way to do this was while drawing the image to use a additional
alpha channel which controlled the transparency per pixel and to save
this image in a format which supported transparency like tga.
but due to lack of vision all graphics have been drawn and saved as
windows bitmap files.
Now I cant seem to blend them right with the backgrounds
please download my test program all.zip (350k) or
src.zip (70k)
from http://www.geocities.com/lazy_coder/index.htm
basically bmp.bmp is the part
of the sprite which doesnt need blending, blend.bmp (glow) has to blended
with the background, bg.bmp is the background image. Result.bmp shows the
results I got from different blending modes.
You can test the blending with different parts of the background
by moving the mouse, the first sprite is drawn normally without any blending
only skipping the surrounding pure black pixels (mask). The
second sprite uses additive/alpha blending which you can change using spacebar
to make it look right the second sprite must look like the first,
additive blending seems to achieve this against dark background but it
doesnt work against bright areas.
At the moment none of these are satisfactory and I am looking for
a proper solution, If you can help me I will be most obliged and will give full
credit.
Deepak T (coolbool@gmx.net)
Here's a suggestion: you can create the alpha channel out of the light intensity of every color. The equation for this is:
light = (red * 30 + green * 59 + blue * 11) / 100;
Or to speed it up:
light = (red * 77 + green * 151 + blue * 28) >> 8;
Then you can just use the light intensity as your alpha channel.
stupid 50/50 averaging with one bit precision loss(tm):
int color1 >>= 1; //= divide by 2
color1 &= EFEFEF; //masks out fractionals
int color2 >>= 1;
color2 &= EFEFEF;
retunr color1 + color2; //add them together
oops I meant 0x7F7F7F instead of EFEFEF of course hehe...and I haven't seen that you were about to go for 16 bit per pixel, my example were in 24 bpp...
however, use 0x7BEF as bitmask for 5:6:5 16-bit 1/1 average blending bla bla...
And 24bpp 50/50 averaging with No Bit Loss(tm) (but slower).
int low_mask = 0x00010101;
int high_mask = 0x00FEFEFE;
int result = (a & high_mask) >> 1 + (b & high_mask) >> 1 + (a & b & low_mask);
No, these methods dont seem to work, they give the entire glow a blackish tinge, I would suggest you download the 70k program from
http://www.geocities.com/lazy_coder/code/src.zip
it will explain the problem clearly.
note that gimp does this easily if you draw the glow on a seperate layer, then you can change the background layer as you like and gimp keeps the sprite blended with the background
Coolbool: were you refering to the luminosity-as-alpha-channel, the 50-50 transparency, or both?
hmm...what programs like gimp, psp or photoshop do when blending two layers together, is that they have a seperate alpha value for every single pixel, and then they blend the pictures pixelwise, not the whole layer with just one fixedalpha value.
I think one way to get rid of your problems would be to introduce this alpha channel to some of your sprites, allegro already has its own alpha sprite billing routines (wich are unfortunately quite slow). So things like explosions, that are transparent, would have yet another color channel, do determine wich weighting the pixels get at blitting-time, and this usually leads to the best results (for example, an explosion should look solid (alpha = maximum) in its middle, and then kind of "fade" out to the edges (alpha slopes to it's minimum)). but, as you surely can imagine, this way is slow, because of the extra data (not really a problem with 24bit color depth, where there's a nice free byte to put the alpha into, but with 16bit or 15bit color resolution it's getting quite difficult, you see..), and also because of the expensive alpha blending process per pixel.
hey, right now I'm trying to code somekind of alphablending routines that base on the quite fast but lossy method of bitshiftings etc(as seen in my 50%/50% example above). what I'm doing now is to make up a couple of similliar routines, for example 25%/70% or even 12.5%/82.5%. atm I'm at the 12.5% ones, and I make a lot of them so I get (for first testings) 6 different routines for the different weightings(plus 2 routines wich do nothing and just either pass color one or color two for the 100%/0% like cases). then I for example store their function pointers in an array with size of 8. when blitting, every pixel's alpha values could be shiftet by 8 (to loose one byte...) so it's in range of 0..8 - now it's plugged into the array and thus calls the right function for the rgb-values to be mixed. what do you think, could this be fast? I know that only 8 grades of alpha is not enough to always look convincing, the number of blending grades could easily enhanced by power of two (16 grades(I'm just working on that)...32 grades(anyone want to write all that stuff???
...).
anyway, I'm no pro at all, it's just been some silly idea I had (and in case it's been a good one and nobody had it before, I do state now that I'll visit anyone who claims this idea to be from him/herself at night when he/she is sleeping, and I will also make some experimentations with him/her about heart-extraction from a human chest with just a chainsaw and 15 hot needles ;-)
mmmh....maybe I've exagerrated a bit with the 15 hot needles and the chainsaw, I believe I could also manage to do that with just a SpOoN and some opcodes ;-) nah anyway, I was just kidding, feel free to make anything out of it, but please, if it runs fast mail me the sourcecode