2D Alpha Blending Using MMX Technology
Many things have changed since the day I got my first computer. While it used to be common practice to squeeze all you could out of your machine, it is now customary to rely on 3D accelerators and blame the hardware for poor performance. It is not surprising that websites dealing with alpha blending usually suggest giving up software implementations and making use of hardware support.
However, there are coders who do not have sophisticated hardware or who simply want to keep the system requirements for their game within a reasonable range. These people are having a hard time trying to get information from the Internet, so I felt that something had to be done.
I also believe that making source code available for other programmers can be beneficial for both the originator and those who study his code, as one of them might find a way to improve it. Besides, in most cases the author is dependent on the help of others as well, and as this was the case with me, I thought it was time to give something back.
This is the point where I want to give credit to John Hebert. He is the author of the only useful article on alpha blending I found, and some of his ideas have made their way into my implementation. If you want to know all the theory about alpha blending, please refer to his article.
However, I think I was able to make some improvements on his version. Here is a brief overview of what has changed:
- The MMX function for alpha blending with arbitrary alpha values was not implemented for the 24 and 32 bit modes, and there was no MMX version of the 50/50 TransAlphaFast() function at all. I filled this gap in my library.
- The routines I wrote can also handle the unlikely event of a graphics card that does neither support the 555 nor the 565 mode for 16 bit.
- The MMX versions required the width of the bitmaps to be a multiple of four, so I modified the code in such a way that the width now can be any size.
- The MMX routines in my library check the pixels for the color key before applying the alpha blend to them. Without this feature, the standard version is faster than the one with MMX if the bitmap contains a lot of black.
- For the sake of speed (and to keep the interface lean), I use a fixed color key of black. According to my experience, no other color key is often needed in game programming.
- The mathematical trick used in the 16 bit versions of TransAlphaImproved() was also utilized in the MMX version, but this is not necessary. I changed the implementation accordingly, and now it is much faster and the calculated picture is more accurate, which makes quite a difference to the beholder.
- Bugfix: As John Hebert states in the comments of his source code, he does not own a graphics card that supports the 555 mode, so he could not notice that he confused the bitmask for 555 with the one for 565.
- Bugfix: I removed a bug that I believe will cause the program to crash when the width of the bitmap is just one pixel (although this is unlikely). I did this by using 'while' instead of 'do - while' loops.
According to my experience as a games programmer, there are only two types of alpha blending you need: one that uses arbitrary alpha values (e.g. in order to fade in your logo in the intro) and one that uses a fixed alpha value (e.g. to make an explosion or a cloud appear translucent). I implemented both an MMX and a standard version for each type, consequently the core of my library consists of four functions:
BltAlpha() - Blits a DirectDraw surface onto another one, using a variable value for alpha.
BltAlphaMMX() - Same as BltAlpha(), but uses MMX.
BltAlphaFast() - Blits a DirectDraw surface onto another one, using a fixed alpha value of 0.5.
BltAlphaFastMMX() - Same as BltAlphaFast(), but uses MMX.
Each function can handle 16, 24 and 32 bit, where the 16 bit mode is subdivided into 555, 565 and a generic mode. A function that can detect MMX technology on a processor is also included. The source code is thoroughly commented, and every function is preceded by a description of its usage. The project was created using Microsoft Visual C++ 6.0 and is ready to be compiled and executed. I also included a ReadMe file, which contains license information, file IDs and contact information.
I do not claim that the code is perfect in any way, but I tried all my best, so take a close look at it and see if you can improve it. I also assume that the alpha blending routines do not contain any bugs, but that's what you always think, so please let me know if you find any. The entire source code is freeware, and you may use it in whatever way you like. You are also allowed to use it in any commercial software without having to pay a single buck to me. However, I do not want you to charge money for the source code, as I want to make sure that it remains available for everyone. If you find ways to improve the source code, please drop me a line, as this is one reason why I made this code public. Here's how you can reach me: