A question of transparency
edfredcoder

I'm struggling with transparency. I'm trying to draw a bitmap (that I do not load from a file), called fog, onto the screen, but it's not working! What I have is something like this:

//Create the fog
BITMAP *fog;
fog=create_bitmap(640,480);
clear_bitmap(fog);
//Now randomly place a few circles for the fog
for(int i=0;i<10;i++)
 circlefill(fog,rand()%640,rand()%480,rand()%50,makecol(255,255,255));

//Now draw the scene to the screen with out fog
//...

//Draw fog
set_trans_blender(0,0,0,255);
draw_trans_sprite(screen,fog,0,0);

What I would like to happen is for the areas that are covered by the white circles to show completely, with a circle of color makecol(128,128,128) greying the pixels underneath, and the black areas of the fog to completely blot out whatever is under them, so you only see black. So far, I only get the fog covering everything on the screen. Any suggestions on how to do this?

kazzmir

Draw the circles with makecol(255,0,255) so they dont occlude whats beneath them. Then I guess you would have to set the alpha value of the grey circles to less than 255 so that they are translucent.

edfredcoder

It seems to work well; thank you for a solution. However, I'm still confused: what is special about the color makecol(255,0,255) that fixed it so that the circles worked? Also, if I wanted to have a translucent part of the fog, say, have the center of the circle be completely transparent and the other rims increasingly dimmer, how could I do that? And how do I set the alpha value of a pixel in a bitmap (right now I'm using 16 bit color)?

Kikaru

It is called "magic pink." It is defined in allegro as invisible. ;)

edfredcoder

Oh, sorry. I should have thought of that.

Does anyone know how to do the fog effect, but with not 100% transparent fog, but with the center all the way clear and the edges less clear?

Kikaru

Alpha blending. ;)

edfredcoder

I'm not sure how to use alpha blending with Allegro. I think what I need is a 32-bit bitmap called fog, so I could do something like:

BITMAP *fog=create_bitmap_ex(32,640,480);

After that, I need some way of setting the alpha part of each pixel in the image, which I was unable to find in the Allegro manual (so please don't tell me to rtfm!). Then, I need to just blit the fog onto the image like normal, right? Or am I missing something here?

Kikaru

blit() does not take into account any alpha channel!
You basically need look into the manual and try to write your own. I made my own translucent sprite drawing function, here:

1int color_shift(int col1, int col2, int percent)
2{
3 int ipercent = 100 - percent;
4 int n_col, rn, gn, bn;
5 int r1, g1, b1, r2, g2, b2;
6 //get colors
7 r1 = getr(col1);
8 r2 = getr(col2);
9 g1 = getg(col1);
10 g2 = getg(col2);
11 b1 = getb(col1);
12 b2 = getb(col2);
13 //shift
14 rn = ((r1*percent)/100)+((r2*ipercent)/100);
15 gn = ((g1*percent)/100)+((g2*ipercent)/100);
16 bn = ((b1*percent)/100)+((b2*ipercent)/100);
17 //create
18 n_col = makecol(rn, gn, bn);
19 //return
20 return n_col;
21}

1void trans_draw(BITMAP *dest, BITMAP *source, int x, int y, int percent)
2{
3 int w = source -> w;
4 int h = source -> h;
5 int w2 = dest -> w;
6 int h2 = dest -> h;
7 for (int sx = 0; sx < w; sx++)
8 {
9 if ((x + sx >= w2)||(x + w < 0))
10 return;
11 while (x + sx < 0)
12 sx++;
13 for(int sy = 0; sy < h; sy++)
14 {
15 if ((y + sy >= h2)||(y + h < 0))
16 break;
17 while (y + sy < 0)
18 sy++;
19 int col1 = _getpixel32(source, sx, sy);
20 if (col1 != MASK_COLOR_32)
21 {
22 int col2 = _getpixel32(dest, sx+x, sy+y);
23 int col3 = merge(col1, col2, percent);
24 _putpixel32(dest, x+sx, y+sy, col3);
25 }
26 }
27 }
28 return;
29}

You can use it as you want. Basically, just use it like draw_sprite(), only give it the last parameter to tell it how much to blend the image into the background. :)
[EDIT]
Almost forgot! This function only works with 32-bit color depth. :)

edfredcoder

Thanks! The code you posted is great, but as you said, it requires 32-bit color depth. I wrote my own just now, which accepts an 8-bit bitmap which contains the alpha part and anouther bitmap, as well as the position (x,y) of where to place the alpha part on the other (truecolor) bitmap; so far, it works. Here is my alpha-blending function:

1void drawAlpha(BITMAP *alpha,BITMAP *destination,int x,int y)
2{
3 int r,g,b;
4 float alphaPart;
5 int rx,ry;
6 int color;
7 //Out of bounds?
8 if(x>=destination->w || y>=destination->h || x+alpha->w<0 || y+alpha->h<0)
9 return;
10 
11 for(rx=0;rx<alpha->w;rx++) //rx for relative x
12 for(ry=0;ry<alpha->h;ry++) //See above
13 {
14 alphaPart=_getpixel(alpha,rx,ry)/255.0;
15 color=getpixel(destination,x+rx,y+ry);
16 r=alphaPart*getr(color);
17 g=alphaPart*getg(color);
18 b=alphaPart*getb(color);
19 putpixel(destination,x+rx,y+ry,makecol(r,g,b));
20 }
21}

Now the fog of war really does look like fog! :D

Kikaru

I wrote a whole header of cool functions, and I will probably release it sometime. Good that you solved you problem! :D

Thread #589235. Printed from Allegro.cc