Jump to content
  • Advertisement


This topic is now archived and is closed to further replies.

A (hopefully) useful post

This topic is 6616 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Well I haven''t seen any useful posts to this thread (no offense you guys , and I''m about to go to bed, seeing as how it is after 2:30 in the morning. But I feel like helping somebody, and I hope this is of some use to you. Well first of all, you will need a source surface.. and for alpha blending.. you''d want to blit that to a destination surface.. the same as a regular blit. Here is some simple (but inefficient) pseudocode to do a regular blit. Then I''ll try and provide some insight on how to modify it to perform an alpha blended blit. You''ll have to excuse my lack of knowledge of DDraw, since I wrote a wrapper class for it a year ago and haven''t really touched DDraw directly since :/ (remember this is pseudo-code It doesnt perform clipping or anything.. /* same arguments (basically) that BltFast takes i hope my indentation is maintained note that this assumes 8-bit, etc.. and it only intended to demonstrate the concept of a manual blit */ void RegularBlit(Surface Dest, Surface Src, int DestX, int DestY, RECT SrcRect) { int x, y; /* current position that we are working with */ int Xmin, Xmax, Ymin, Ymax; /* bounds of the dest rectangle */ int SrcPitch, DestPitch; /* Source and Dest pitches */ unsigned char *SrcMem, *DestMem; /* Source and Dest surface memory pointers */ /* this should be pretty simple. Xmin-Xmax and Ymin-Ymax are the coordinates on the destination surface that we will be covering */ Xmin = DestX, Ymin = DestY; Xmax = Xmin + (SrcRect.Right - SrcRect.Left); Ymax = Ymin + (SrcRect.Bottom - SrcRect.Top); Lock(Src); Lock(Dest); // set pitches and pointers SrcPitch = Src.Pitch, SrcMem = Src.Mem; DestPitch = Dest.Pitch, DestMem = Dest.Mem; // advance pointers to the point where blitting begins SrcMem = SrcMem + SrcRect.Top*SrcPitch + SrcRect.Left; DestMem = DestMem + DestY*DestPitch + DestX; /* Copy each pixel in the area bounded */ for(y=Ymin;y Well not too often anyway. But you see how in the loop, it merely copied the value from the source to the destination? If you want to do an alpha blend, you will have to examine the two values, extract the red, green, and blue components, mix the colors, and then combine them back together again. Sound hard? Well I''ll try and do my best to explain it In 8-bit palettized mode, the R,G,B colors are stored in the palette of course. In 16+ bit color modes, they are stored directly in the pixel value themselves. You would have to check the surface properties to determine the exact bit masks to extract the red, green, and blue from 16+ bit surfaces, but usually it goes like this. For 16-bit: Imagine your 16 bits.. the colors are usually packed like so: 15 0 RRRRR GGGGGG BBBBB 5 bits for red, 6 for green, and 5 for blue. Green gets the extra bit because our eyes are most sensitive to yellow-green light, and can determine differences better. So given a number that had your 16 bit pixel in it.. you would extract the red, green, and blue like so.. Red = Pixel >> 11; Green = (Pixel >> 5) & 0x3F; Blue = Pixel & 0x1F; This yields values where Red and Blue are from 0-31, whereas Green is from 0-63. Complex? yep :/ ok.. for 24 bit, it''s simpler.. it''s just 3 bytes.. generally arranged like this in memory BGRBGRBGR... etc Blue = Mem[0]; Green = Mem[1]; Red = Mem[2]; Each value is from 0-255. for 32-bit, it''s generally the same way, except the fourth byte is ignored.. BGRXBGRXBGRX where X is whatever.. (often an alpha channel.. but not in DDraw..) Ok.. so you have your Red, Green, and Blue values.. How do you mix them? I''ll abbreviate source red, green, and blue as SR, SG, SB and destination as DR, DG, DB You also will need an alpha value. This can be passed to your function. It is a number which represents how transparent the source bitmap is. 0 is fully transparent, and the max value (I''m going to use an 8-bit alpha, so the max value will be 255) is fully opaque. So you have SR, SG, SB, DR, DG, DB, and Alpha for a single pixel. To blend them, you would use this algorithm, assuming all the values are from 0-255. Remember when you extract the values from 16-bit surfaces, the values are not from 0-255, so you would have to multiply them to get them in the proper range. In the above 16 bit example, Red and Blue would be multiplied by 8, while Green would be multiplied by 4. (I''m doing this from memory.. and it''s 3am.. But I think it''s correct if (SR > DR) NewRed = ((SR-DR) * Alpha / 255) + DR; else NewRed = DR - ((DR-SR) * Alpha / 255); if (SG > DG) NewGreen = ((SG-DG) * Alpha / 255) + DG; else NewGreen = DG - ((DG-SG) * Alpha / 255); if (SB > DB) NewBlue = ((SB-DB) * Alpha / 255) + DB; else NewBlue = DB - ((DB-SB) * Alpha / 255); After you have your new red, green, and blue values, you combine them back together using the reverse of what you did to extract them.. So for 8-bit palettized, this requires a lookup table.. or a nearest color match.. I wont go into this right now, as it doesn''t exactly deal with the concept of alpha blending. For 16-bit, with the usual bit-packing, you would combine them like this: NewPixel = (NewRed << 11) / (NewGreen << 5) / NewBlue; You would then write your new pixel (or your new R,B,G values) into the destination memory. I wish I could provide you with some working code, but like a previous poster mentioned, this is slow.. so I too converted mine to optimized inline asm with lookup tables and such.. (so it''s just 1 add, one subtract, and one mov per channel An interesting idea that you might try is having Alpha vary as you blit.. ie.. you pass in 3 surfaces, source, dest, and an alpha map.. and you read the Alpha value from the Alpha map as you blit.. gives a great effect I apologize that I can''t paste working code, but I hope that I have given you some insight into how to perform an alpha blend. So unfortunately, the coding and optimizing are up to you I would recommend getting a plain blitter working first if you aren''t accustomed to dealing with surfaces directly (and in different bit depths) before you try and tackle alpha blended blitters. One final note: Accessing surfaces stored in video memory is VERY slow, especially reading from them. If you are going to use alpha blending, or any function that directly accesses surfaces, make sure that all of the surfaces you pass to that function are explicitly created in system memory. Check the DirectDraw docs on CreateSurface for more info on this. Note that DirectDraw creates surfaces in video memory by default. Furthermore, the backbuffers that DirectDraw creates for you in the flipping chain are generally always created in video memory. So if you want to use alpha blending to blit to one of these.. I would highly recommend that you create your backbuffer in system memory (not as part of a flipping chain), and then BltFast it to the primary surface. (You can use the WaitForVerticalRetrace() [I think that''s the name anyway] function in the DirectDraw interface to synch to the vertical retrace). Wow, I''ve been working on this for almost an hour. Well I sincerely hope my efforts help you and/or somebody else! If you need any advice, feel free to e-mail me. But no whining Adam Milazzo adamm@san.rr.com

Share this post

Link to post
Share on other sites

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!