Alpha-Blending in a DirectDraw app (how-to)

slantz

Freshman
Joined
Dec 12, 2003
Messages
37
So in my app, I really really wanted to be able to use alpha blending, specifically to darken the entire game screen w/ 50% transparency black, whenever I put a 'pop-up' on top of it.

However, as I soon found out, Alpha Blending just isn't possible with DirectDraw. Even if you use, say, Color.FromArgb(AlphaChannel, RedChannel, GreenChannel, BlueChannel), a DirectDraw app will flat-out override any AlphaChannel value with 255.

After researching, I saw where someone on this forum said it should be possible to get a device handle, and then use GDI+ to write to that device handle.

Well, it worked! Unfortunately, my app went from about ~140 FPS to about 10 FPS when I applied that alpha blending to every frame, so we're looking at about a 92% performance degridation, but it did work!

if I weren't so intent on continuing to show the normal game animations under the pop-up, I could simply take a snapshot of the current game surface, darken that, cache that, and then just keep copying that pre-darkened image, which would keep my framerate up. But that doesn't work for me.

Anyway, here's the code I used to alpha blend in DirectDraw (this covers an 800x600 surface with a 50% transparent black overlay):

---------------------------------------------------
//Here are some local variables you'll need.
Byte[,] __tempByte;
IntPtr __tempIntPtr;
Graphics __newGraphics;

//Creates a brush that's 50% transparent black
SolidBrush __myBrush = new SolidBrush(Color.FromArgb(127, 0, 0, 0));

//Lock the surface
__tempByte=_surfaceToDarken.Lock(LockFlags.DoNotWait);

//Get a pointer to the surface's device context
__tempIntPtr=_surfaceToDarken.GetDc();

//Instantiate a GDI+ Graphics object pointing to the DirectDraw surface
__newGraphics = Graphics.FromHdc(__tempIntPtr);

//Apply the alpha-blending to the surface
__newGraphics.FillRectangle(__myBrush, new Rectangle(0, 0, 800, 600));

//Now that we're done, release and unlock the surface (and its device context)
_surfaceToDarken.ReleaseDc(__tempIntPtr);
_surfaceToDarken.Unlock(__tempByte);
---------------------------------------------------

In the end, I chose *not* to go with this approach because I either needed to take a huge performance hit or lock down my surface while I'm showing it darkened. Instead, I just created an 800x600 .bmp that alternated between black and purple(transparent) for every other pixel, and then applied that to the background. It's not as pretty, but at least it can handle on-going animation underneith it without the huge performance hit.
(screenshot of this effect available at http://www.spitshine.com/downloads/ss6_2.gif)


I hope that helps. I'd searched for hours and not found any code that could actually do this...

-Hiro_Antagonist
 
Back
Top