Problem of the century [UPDATED]

Started by
4 comments, last by ChocoboX 19 years, 2 months ago
Hello.So ok.I decided to jump in the confusing world of digital image arithmetic, so I can apply cool effects in my game (zoom, trembling screen, fading,..).I'm still using DirectDraw.What I'm trying to do is fading a logo from black then fade back out.At first it sounded pretty easy.But since I'm a bit old school and hate all the high level stuff I wanted to do it manually(you know, locking the surface, extracting color components etc..).I've been trying to do a simple fade for about 3 days, and I still didn't succeed. What angers me the most, is that sometimes my app just gets back to windows, leaving me searching for what I'm doing wrong.This is time consuming you know. I've researched all the techniques for doing this.From using the DirectX gamma/color control to extracting every color component out of a 16-bit 565 pixel and manually perform the blend. Here's the code, I'll be very grateful to the ones who will try to help me out.Please ! *General info : **surfaces** prim_surf : primary surface ( 1024 x 768 x 16 (565) ) dbl_buff : back buffer bitmap : surface holding the 512 x 512 logo bmp_stretch : surface holding the stretched logo (1024 x 768) (I've blitted the bitmap surface to this surface with a RECT of 1024x768, so the first bitmap surface won't be used anymore) blend result: 1024 x 768 surface filled with black wich will hold the result of the blending. First question, it may be the cause of the problem. Well I tested the number of green bits in a pixel of my primary surface, it returned 16.Wich means the primary surface is 16-bit in 565 format right? ...but when I create other surfaces.Are they also in 16-bit 565 format or do I have to set it myself ? I believe it's already set so it may not be the problem Second question: Bitmaps are stored in BGR format right? In my bitmap loading function I store them in RGB format in my bitmap surface using a specific macro.So when I display the surface it gets displayed correctly, no problems here. ...but what about the other offscreen surfaces? Are they in BGR or RGB ?? Here are the functions I've made to try to achieve the blend : #define RMASK_565 1111100000000000 #define GMASK_565 0000011111100000 #define BMASK_565 0000000000011111 WORD *bmp_data, *bln_data; DDSURFACEDESC2 srf_desc, bmp_desc; /***** this is the function I use to clear blend_result before I call each of the three following functions *************************/ void clearSurface(LPDIRECTDRAWSURFACE7 surface, WORD color) { memset(&clr_color, 0, sizeof(DDBLTFX)); clr_color.dwSize = sizeof(DDBLTFX); clr_color.dwFillColor = color; surface->Blt(NULL,NULL,NULL,DDBLT_COLORFILL|DDBLT_WAIT, &clr_color); } /**************** First attempt ********************************************/ inline void blendAdd(WORD src_pixel, WORD dst_pixel) { register unsigned short new_pixel = 0; register unsigned short temp_pixel; temp_pixel = (src_pixel & RMASK_565) + (dst_pixel & RMASK_565); if( temp_pixel > RMASK_565) temp_pixel = RMASK_565; new_pixel |= temp_pixel; temp_pixel = (src_pixel & GMASK_565) + (dst_pixel & GMASK_565); if( temp_pixel > GMASK_565) temp_pixel = GMASK_565; new_pixel |= temp_pixel; temp_pixel = (src_pixel & BMASK_565) + (dst_pixel & BMASK_565); if( temp_pixel > BMASK_565) temp_pixel = BMASK_565; new_pixel |= temp_pixel; dst_pixel = (WORD)new_pixel; } /** I call it like this **/ clearSurface(blend_result, RGB16(100,100,100)); blend_result->Lock(NULL,&srf_desc, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT,NULL); bmp_stretch->Lock(NULL,&bmp_desc, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT,NULL); bln_data = (WORD*)srf_desc.lpSurface; bmp_data = (WORD*)bmp_desc.lpSurface; for(int y = 0; y < SCREEN_HEIGHT;y++) for(int x = 0; x < SCREEN_WIDTH;x++) blendAdd( bmp_data[ y * bmp_desc.lPitch / 2 + x], bln_data[ y * bln_desc.lPitch / 2 + x]); blend_result->Unlock(NULL); bmp_stretch->Unlock(NULL); /** then I blit blend_result on my back buffer and flip, of course the app just gets back to windows or nothing happens.This attempt is slow as hell I know but I do it before I enter my loop so the two surfaces are already blended **/ /***************** SECOND ATTEMPT ********************************************/ void blendPixels(float src_ratio, float dst_ratio) { static WORD src_pixel, dst_pixel, new_pixel; static BYTE src_red, src_green, src_blue, dst_red, dst_green, dst_blue; WORD *bmp_data, *bln_data; bmp_stretch->Lock(NULL, &bmp_desc, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT, NULL); blend_result->Lock(NULL, &srf_desc, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT, NULL); bmp_data = (WORD*)bmp_desc.lpSurface; bln_data = (WORD*)srf_desc.lpSurface; for(int y = 0; y < SCREEN_HEIGHT;y++) for(int x = 0; x < SCREEN_WIDTH;x++) { src_pixel = (WORD)bmp_data[y * bmp_desc.lPitch/2 + x]; dst_pixel = (WORD)bln_data[y * srf_desc.lPitch/2 + x]; src_red = (src_pixel & RMASK_565); src_green = (src_pixel & GMASK_565) >> 5; src_blue = (src_pixel & BMASK_565) >> 11; dst_red = (dst_pixel & RMASK_565) >> 11; dst_green = (dst_pixel & GMASK_565) >> 5; dst_blue = (dst_pixel & BMASK_565); src_red *= src_ratio; src_green *= src_ratio; src_blue *= src_ratio; dst_red *= dst_ratio; dst_green *= dst_ratio; dst_blue *= dst_ratio; new_pixel = (src_red + dst_red) >> 11; new_pixel |= (src_green + dst_green) >> 5; new_pixel |= (src_blue + dst_blue); (WORD)bln_data[y * srf_desc.lPitch/2+ x] = new_pixel; } bmp_stretch->Unlock(NULL); blend_result->Unlock(NULL); } /** I call it like this before I enter the actual game loop**/ clearSurface(blend_result, RGB16(100,100,100)); blendPixels(0.5, 0.5); /***************** THIRD ATTEMPT *********************************************/ void alphaBlend(void) { int height = SCREEN_HEIGHT; int width = SCREEN_WIDTH; static WORD src_pixel; static WORD dst_pixel; BYTE src_b, src_g, src_r, dst_b, dst_g, dst_r, new_b, new_g, new_r; blend_result->Lock(NULL, &srf_desc, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT, NULL); bmp_stretch->Lock(NULL, &bmp_desc, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT, NULL); srf_data = (WORD*)srf_desc.lpSurface; bmp_data = (WORD*)bmp_desc.lpSurface; while(height-- > 0) while(width-- > 0) { dst_pixel = srf_data[height * srf_desc.lPitch/2 + width]; src_pixel = bmp_data[height * bmp_desc.lPitch/2 + width]; src_b = src_pixel & 0x1f; src_g = (src_pixel >> 5) & 0x3f; src_r = (src_pixel >> 11) & 0x1f; dst_b = dst_pixel & 0x1f; dst_g = (dst_pixel >> 5) & 0x3f; dst_r = (dst_pixel >> 11) & 0x1f; new_b = (128 * (src_b - dst_b) >> 8) + dst_b; new_g = (128 * (src_g - dst_g) >> 8) + dst_g; new_r = (128 * (src_r - dst_r) >> 8 )+ dst_r; dst_pixel = new_b | (new_g << 5) | (new_r << 11); } blend_result->Unlock(NULL); bmp_stretch->Unlock(NULL); } /*** I call it like this ****/ clearSurface(blend_result, RGB16(100,100,100)); alphaBlend(); ************************** GAME OVER ****************************************** I am worn out.Please oh please help me out.If you need to know any info just say it I'll instantly post, I think I'm going to sleep in front of this thread until someone answers. [Edited by - ChocoboX on February 13, 2005 1:07:33 PM]
Advertisement
I can't actually answer your question I'm afraid, but you might want to put your code in source tags so it's easier for people to read. Find out how in the FAQ if you don't know.

Good luck getting an answer to your problem.

- Jason Astle-Adams

One thing that I can see that looks blatantly wrong is this:
#define RMASK_565 1111100000000000#define GMASK_565 0000011111100000#define BMASK_565 0000000000011111


These numbers are in decimal. There is no way in C or C++ to define a constant binary number. Convert them to hex, and this should help quite a bit:

#define RMASK_565 0xF800#define GMASK_565 0x07E0#define BMASK_565 0x001F
The third function doesn't use those masks, it jumps back to the desktop.Even when changing the masks, the two others functions jump back too.
I've isolated the problem.When I call this function, the app
hangs.So the problem lies in it.

void alphaBlend(void) {

WORD src_pixel;
WORD dst_pixel;

BYTE src_b, src_g, src_r, // variables holding the color components of
dst_b, dst_g, dst_r, // the source and destination pixels
new_b, new_g, new_r;

// blend_result is the surface filled with a color (1024x768)
blend_result->Lock(NULL, &srf_desc, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT, NULL);
// bmp_stretch is the surface containing the 1024 x 768 bitmap
bmp_stretch->Lock(NULL, &bmp_desc, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT, NULL);
// final is the surface holding the result of blending blend_result and
// bmp_stretch
final->Lock(NULL, &res_desc, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT, NULL);

srf_data = (WORD*)srf_desc.lpSurface;
bmp_data = (WORD*)bmp_desc.lpSurface;
res_data = (WORD*)res_desc.lpSurface;

for(int y = 0; y < SCREEN_HEIGHT; y++)
for(int x = 0; x < SCREEN_WIDTH; x++) {

// retrieve pixels
dst_pixel = srf_data[y * srf_desc.lPitch/2 + x];
src_pixel = bmp_data[y * bmp_desc.lPitch/2 + x];

// extract color components
src_r = src_pixel & 0x1f;
src_g = (src_pixel << 5) & 0x3f;
src_b = (src_pixel << 11) & 0x1f;

dst_r = dst_pixel & 0x1f;
dst_g = (dst_pixel << 5) & 0x3f;
dst_b = (dst_pixel << 11) & 0x1f;

// blending formula
new_b = (0.5 * (src_b - dst_b) ) + dst_b;
new_g = (0.5 * (src_g - dst_g) ) + dst_g;
new_r = (0.5 * (src_r - dst_r) ) + dst_r;

// assign the pixel value to the pixel(s) of the final surface
res_data[y * res_desc.lPitch/2 + x] = new_r | (new_g >> 5) | (new_b >> 11);
}
// when everything's done, unlock the used surfaces
blend_result->Unlock(NULL);
bmp_stretch->Unlock(NULL);
final->Unlock(NULL);
}

[depressed][depressed][depressed]
Found the problem.I needed to multiply my line number by my surface pitch, not by requested surface width.The app doesn't hang anymore...but the blend function does nothing at all...lol.Can someone help out ?

EDIT: after a few headaches and debug messages outputs, it turned out that the pitch I was using in my loop was equal to zero...that's why it actually ran.So this throws me back at the beginning.

[Edited by - ChocoboX on February 13, 2005 4:12:40 PM]

This topic is closed to new replies.

Advertisement