Make your own free website on Tripod.com




programming notes

*note* I'm no longer working on this library, but I still get a surprising number of emails from interested parties, so I'll leave this page in place. Send me an email if you'd like the source to it!

Finishing my thesis among other things has slowed me down a bit, so this section isn't fully finished. I'll keep adding bit by bit until its done. So far I haven't even gotten to the good stuff...so far I've just rambled a little about other peoples code. That in mind, welcome to my programming notes.

I have had three goals in developing this library, speed, speed, and to create a custom blitting routine as easy to use as blitfast. So far, so good :). The thrust of this library is of course, the alpha blending effects. Of course D3D can be used for alpha blending now, and the next version of directx will most likely have alpha blending in plane old ddraw, but I have discovered that there are many great effects and modifications to alpha blending which you can't do with pure directx. Lots of coders are doing custom blending, but I have seen very little source code or explanations except for very basic examples. I have done lots of thinking and research, and had some great help (see acknowledgements) to create this library. Here is some of the information I have gleaned, presented in the order I learned it, so if you know what you're doing the early stuff might be boring. Occasionally I will refer to example code written by others. This can be found in the files section at Angelic Coders unless otherwise noted.

alpha blending in 256 colors
A simple example of alpha blending is a translucent source image which is placed over a second background image. I have seen to basic approaches to achieve this effect. The first is dithering, the second is combining the colors of the source and destination pixels. The DDTRANS example by Mark Harmon is a simple demonstration of both. DDTRANS shows us immediately that dithering doesn't give very pretty results, so this is the last you will here of that from me. The pixel combination using the lookup table (LUT) gives nice results though, and is worth pursuing further...

The LUT is generated using a constant alpha and all 256*256 combinations of source (SRC) and destination (DST). (In most cases the background image will be placed in the destination, the pixels will be blended, and placed back in DST.) The most common alpha blending equation is

Eq 1:DST=SRC*alpha+DST*(1-alpha)

The drawback of the DDTRANS lookup table is that is only suitable for 256 color modes or lower. The lookup table index is something along the lines of SRC+256*DST. This LUT is only 64k for 256 colors, but become prohibitively large for higher color modes, and this is only for one level of alpha. To get nice smooth blending we want to use those higher color modes. Of course, if your application only uses 256 colors, this may well be a very good implementation. Now that I've seen this in action, I've noticed its use in several 256 games.

alpha blending in 16 bit color using shifts
The BLITTEST example by Darius Zolna at angelic-coders contains basic 16 bit alpha blending. I might note that there is a small bug in the memory allignment portion of this code, and the last column of pixels is dropped on odd memory allignments. Otherwise, this is a great example to begin dabbling in alpha blending for a few reasons: it uses a 16 bit pixel mode, it uses assembly language, its in windowed mode, it is set up to nicely compare modes (In fact, my current demo is setup almost the same way.) In 16 bit mode and higher goupings of bits represent the individual color components red, green, and blue (there are other ways to divide them.) The pixel format depends on the vidoe card, with the two most common formats being are 555 rgb and 565 rgb. I believe the human eye is most sensitive to green, which is why green sometimes gets the extra bit. The bits of these look something like

0rrrrrgggggbbbbb and
rrrrrggggggbbbbb

The zero bit in the first format is ussually unused, but I have heard it can be used as an alpha bit. He performs his alpha blending by right shifting the SRC and DST, masking them, then adding them together. (basically the eq 1 with alpha=.5) In 565 the shift and mask look like this in psuedo-assembly

shr rrrrrggggggbbbbb, 1
and 0rrrrrggggggbbbb, mask
-> 0rrrr0ggggg0bbbb

This simultaneously divides the red, green, and blue by two. This is really fast, and although there are some optimizations that can be performed, I haven't seen a faster algorithm for a quick and easy alpha blend. Two shifts, two ands, and an add gives nice blending and very low cost. One disadvantage to the method is it does not give the most accurate blending possible. The shr does not exactly divide by two since the low order byte is dropped. This might seem like a small point, but the difference can be noticable.

My initial alpha blending code was an extension of this technique to varied levels of alpha. My thoughts were that shifts, ands, adds and subtracts are cheap. Using combinations of these you can get all sorts of nifty fractions, for example to get 7/8 of ax

mov bx, ax
shr bx, 3
sub ax, bx

Using just 4 shifts you can do any fraction of 16, leading to 16 levels of alpha. What I did is set up 4 bitmasks before the assembly section, then did 4 shifts, applied the bitmasks, and subtracted. Any bitmask which was unneeded would be set to 0, thus subtracting zero at that stage. Some shifts and subtracts are wasted at some alpha levels. For example, at 50 percent three of the bitmasks are zero. For the fastest possible implementation of this method, each alpha level should have its own hard coded routine. Here is a snippit of source from the generic routine, showing the 4 subtracts for the sprite pixel.
mov ax, [esi] // get sprite pixel
cmp ax, TRANSCOLOR // check if it's transparent
je Skip30

mov ebx, eax
mov edx, eax

shr eax, 1
and eax, bmask1
sub ebx, eax

mov eax, edx
shr eax, 2
and eax, bmask2
sub ebx, eax

mov eax, edx
shr eax, 3
and eax, bmask3
sub ebx, eax

mov eax, edx
shr eax, 4
and eax, bmask4
sub ebx, eax

shadows
Shadows can be achieved using the same process. Don't do the shifts for transparent pixels in the sprite and leave off the add at the end and you have a darkened version of the background. Blit the sprite over that gives a nice effect of an object and its shadow. Alphalib has darken routines hard coded to a single level of alpha for speed, since a single level of alpha creates very nice shadows.




acknowledgements
Currently I am the exclusive coder on this project, so the help from the following has been greatly appreciated.

Gil Gribb-answered questions
Vinnie Falco-dxblt code example
Darius Zolna-blittest code example
Brian Shea-learned lots of good directx from him
Stuart Riffle-Taught me the black art of assembly language
Phillip Evans-Introduced me to VC++