游戏开发论坛

 找回密码
 立即注册
搜索
查看: 4002|回复: 11

alpha严重性问题

[复制链接]

47

主题

145

帖子

3602

积分

论坛元老

Rank: 8Rank: 8

积分
3602
发表于 2004-5-29 12:18:00 | 显示全部楼层 |阅读模式
最近在写alpha。。。写了如下代码(从gameres.com上下载的代码)
但有问题出现。。。为什么当用到FLIP的时候画面帧数从原来22帧猛得下降到2,3帧??


我修改过后的代码如下:
============================================
#include<windows.h>
#include<ddraw.h>
#pragma comment(lib,"ddraw")
#pragma comment(lib,"winmm")        //TimeGetTime
#include"ddutil.cpp"
LPDIRECTDRAW lpDD=NULL;
LPDIRECTDRAWSURFACE lpDDSPrimary=NULL;
LPDIRECTDRAWSURFACE lpDDSBack=NULL;
LPDIRECTDRAWSURFACE lpDDSPic1=NULL;
LPDIRECTDRAWSURFACE lpDDSPic2=NULL;

#define SAFE_FREE(x) {if((x)){(x)->Release();(x)=NULL;}}
BOOL bActive;
HWND hWnd;
int pitch;
static DWORD s_dwAlphaMask=0;
#define _ALPHA565RGBMASK 0x07e0f81f //0000,0111,1110,0000,1111,1000,0001,1111
#define _ALPHA555RGBMASK 0x03e07c1f //0000,0011,1110,0000,0111,1100,0001,1111
#define _MODE_FLIP    //这里定义是否用FLIP


inline WORD Alpha(WORD Sour,WORD Dest,int aValue)
{
  DWORD sb,db,sg,dg,sr,dr;
  DWORD blue,green,red;
  DWORD temp;
  
   sb=Sour&0x1f;
   db=Dest&0x1f;
   
   sg=(Sour>>5)&0x3f;
   dg=(Dest>>5)&0x3f;
   
   sr=(Sour>>11)&0x1f;
   dr=(Dest>>11)&0x1f;   
   
   blue = (aValue* (sb - db) >> 5) + db;           
   green = (aValue* (sg - dg) >> 5) + dg;   
   red = (aValue* (sr - dr) >> 5) + dr;  
   
   temp= blue | (green << 5) | (red << 11);
   
   return temp;
     

}





void FreeAll()
{
        SAFE_FREE(lpDDSPic1);
        SAFE_FREE(lpDDSPic2);
        SAFE_FREE(lpDDSBack);
        SAFE_FREE(lpDDSPrimary);
        SAFE_FREE(lpDD);
}
HRESULT RestoreAll()
{
    HRESULT ddrval;
    ddrval=lpDDSPrimary->Restore();
        ddrval=lpDDSBack->Restore();
        :DReLoadBitmap(lpDDSPic1,"bmp1.bmp");
        ::DDReLoadBitmap(lpDDSPic2,"bmp2.bmp");
    return ddrval;
}

LRESULT CALLBACK WinProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam )
{
    switch(message)
    {
    case WM_ACTIVATEAPP:
        bActive=wParam;
        break;
    case WM_SETCURSOR:
                SetCursor(NULL);
                break;
    case WM_KEYDOWN:
        switch(wParam)
        {
        case VK_ESCAPE:
            PostMessage(hWnd, WM_CLOSE, 0, 0);
            break;
        }
        break;
    case WM_DESTROY:
        FreeAll();
        PostQuitMessage(0);
        break;
        default:
                return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 1;
}
bool InitWindow(HINSTANCE hInstance,int nCmdShow )
{
    WNDCLASS wc;
    wc.style=0;
    wc.lpfnWndProc=WinProc;
    wc.cbClsExtra=0;
    wc.cbWndExtra=0;
    wc.hInstance=hInstance;
    wc.hIcon=NULL;
    wc.hCursor=NULL;
    wc.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
    wc.lpszMenuName=NULL;
        wc.lpszClassName="AlphaTest";
    RegisterClass(&wc);
    hWnd=CreateWindow("AlphaTest","AlphaTest",WS_POPUP,0,0,
                GetSystemMetrics(SM_CXSCREEN),
                GetSystemMetrics(SM_CYSCREEN),
                NULL,
                NULL,
                hInstance,
                NULL);
    if(!hWnd )               
                return false;
    ShowWindow(hWnd,nCmdShow);
    UpdateWindow(hWnd );
        return true;
}
#define D_ASSERT(x) {if((x)!=DD_OK)return false;}
BOOL InitDDraw(void)
{
    DDSURFACEDESC       ddsd;
    DDSCAPS                         ddscaps;
    D_ASSERT(DirectDrawCreate(NULL,&lpDD,NULL));
    D_ASSERT(lpDD->SetCooperativeLevel(hWnd,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN|DDSCL_ALLOWREBOOT));
    D_ASSERT(lpDD->SetDisplayMode(640,480,16));

        ZeroMemory(&ddsd,sizeof(ddsd));
    ddsd.dwSize=sizeof(ddsd);

#ifdef _MODE_FLIP
        ddsd.dwFlags=DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
        ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE|DDSCAPS_COMPLEX|DDSCAPS_FLIP;
        ddsd.dwBackBufferCount=1;
#else
        ddsd.dwFlags=DDSD_CAPS;
        ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE;
#endif

    D_ASSERT(lpDD->CreateSurface(&ddsd,&lpDDSPrimary,NULL));

#ifdef _MODE_FLIP
        ddscaps.dwCaps=DDSCAPS_BACKBUFFER;       
        D_ASSERT(lpDDSPrimary->GetAttachedSurface(&ddscaps,&lpDDSBack));
#else
        ddsd.dwFlags=DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH;
    ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
    ddsd.dwWidth=640;
    ddsd.dwHeight=480;
    D_ASSERT(lpDD->CreateSurface(&ddsd,&lpDDSBack,NULL));
#endif

        DDPIXELFORMAT DDPixelFormat;
        ZeroMemory(&DDPixelFormat,sizeof(DDPixelFormat));
        DDPixelFormat.dwSize=sizeof(DDPixelFormat);
        D_ASSERT(lpDDSPrimary->GetPixelFormat(&DDPixelFormat));//得到象素格式(在16位色下分555和565)
        if((DDPixelFormat.dwGBitMask>>5)==0x1f)//00000011111
    {
            s_dwAlphaMask=_ALPHA555RGBMASK;
    }
    else if((DDPixelFormat.dwGBitMask>>5)==0x3f)//00000111111
    {
                s_dwAlphaMask=_ALPHA565RGBMASK;
        }
        else
                return false;
        if(!(lpDDSPic1=::DDLoadBitmap(lpDD,"bmp1.bmp",640,480)))
                return false;
        if(!(lpDDSPic2=::DDLoadBitmap(lpDD,"bmp2.bmp",640,480)))
                return false;
        return true;
}

void UpdateScreen()
{
        DDBLTFX ddBltFx;
        ddBltFx.dwSize=sizeof(DDBLTFX);
        ddBltFx.dwFillColor=0;
        lpDDSBack->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddBltFx);
       
        RECT rect;
       
        ::SetRect(&rect,0,0,640,480);
       
        lpDDSBack->BltFast(0,0,lpDDSPic1,&rect,DDBLTFAST_WAIT);

        DDSURFACEDESC ddsdDest,ddsdSour;
        ZeroMemory(&ddsdDest,sizeof(ddsdDest));
        ZeroMemory(&ddsdSour,sizeof(ddsdSour));
        ddsdDest.dwSize=sizeof(ddsdDest);
        ddsdSour.dwSize=sizeof(ddsdSour);

        HRESULT ddrval;
///*
        while(1)
        {
                ddrval=lpDDSBack->Lock(NULL,&ddsdDest,DDLOCK_WAIT,NULL);
                pitch=ddsdDest.lPitch>>1;
                if(ddrval==DD_OK)
                        break;
                if(ddrval==DDERR_SURFACELOST)
                        RestoreAll();
                else
                        return;
        }
        while(1)
        {
                ddrval=lpDDSPic2->Lock(NULL,&ddsdSour,DDLOCK_WAIT,NULL);
                if(ddrval==DD_OK)
                        break;
                if(ddrval==DDERR_SURFACELOST)
                        RestoreAll();
                else
                        return;
        }

        WORD*BufDest=(WORD*)ddsdDest.lpSurface;
        WORD*BufSour=(WORD*)ddsdSour.lpSurface;
         

        static int alpha=0;
        static int k=1;

        int index=0;
    int index1=0;

        for(int y=0;y<480;y++)
        {
                for(int x=0;x<640;x++)
                {        index1=x+y*pitch;
                        BufDest[index1]=Alpha(BufDest[index1],BufSour[index],alpha);       
                        index++;
                }
        }

        alpha+=k;
        if(alpha>31)
        {
                k=-k;
                alpha=31;
        }
        if(alpha<0)
        {
                k=-k;
                alpha=0;
        }


        lpDDSBack->Unlock(&ddsdSour);
        lpDDSPic2->Unlock(&ddsdSour);

//*/
        static DWORD fpsoldTime=timeGetTime();
        static int frames=0,fps=0;
        if(timeGetTime()-fpsoldTime<1000)
        {
                frames++;
        }
        else
        {
                fpsoldTime=timeGetTime();
                fps=frames;
                frames=0;
        }
        HDC hdc;
        char buf[32];
        memset(buf,0,32);
        lpDDSBack->GetDC(&hdc);
        ::SetBkMode(hdc,TRANSPARENT);
        ::SetTextColor(hdc,RGB(255,0,0));
        TextOut(hdc,10,10,buf,wsprintf(buf,"FPS:%d",fps));
        lpDDSBack->ReleaseDC(hdc);
       
        ::SetRect(&rect,0,0,640,480);
        while(1)
        {
#ifdef _MODE_FLIP
                ddrval=lpDDSPrimary->Flip(NULL,0);
#else
                ddrval=lpDDSPrimary->BltFast(0,0,lpDDSBack,&rect,DDBLTFAST_WAIT);
#endif
                if(ddrval==DD_OK)
                        break;
                if(ddrval==DDERR_SURFACELOST)
                        RestoreAll();
                else
                        break;
        }
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
    MSG         msg;
       
        if(!InitWindow(hInstance,nCmdShow))
                return false;
        if(!InitDDraw())
        {
                MessageBox(hWnd,"初始化DirectDraw过程中出错!", "",MB_OK);
                FreeAll();
                DestroyWindow(hWnd);
                return false;
        }
        while(1)
        {
                if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
                {
                        if(!GetMessage(&msg, NULL,0,0))
                                return msg.wParam;
                        TranslateMessage(&msg);
                        DispatchMessage(&msg);
                }
                else if(bActive)
                {
                        UpdateScreen();
                }
                else
                        WaitMessage();
        }
    return true;
}

====================================================

但用了FLIP后,叶面从原来的20几帧掉到了2,3帧。。。。到底是为什么啊?以前有人解决过的。。但我不知道啊~希望高手门慷慨告诉我为什么爸

1万

主题

1万

帖子

2万

积分

管理员

中级会员

Rank: 9Rank: 9Rank: 9

积分
20527
发表于 2004-5-29 12:42:00 | 显示全部楼层

Re:alpha严重性问题

你混合的面积是不时很大? 这个alpha混合的算法效率并不高,如果打范围混合,速度疾速下降也是可能的。

3

主题

21

帖子

85

积分

注册会员

Rank: 2

积分
85
QQ
发表于 2004-5-29 12:48:00 | 显示全部楼层

Re:alpha严重性问题

用汇编语言优化一下。

30

主题

298

帖子

299

积分

中级会员

Rank: 3Rank: 3

积分
299
QQ
发表于 2004-5-29 12:52:00 | 显示全部楼层

Re:alpha严重性问题

使用翻面链的话,图面是建在显存中的,所以你的ALPHA算法很慢。

47

主题

145

帖子

3602

积分

论坛元老

Rank: 8Rank: 8

积分
3602
 楼主| 发表于 2004-5-29 13:33:00 | 显示全部楼层

Re:alpha严重性问题

的确是这个原因。/。。因为我是用cpu来操作显存。。很慢的,但我又找不到合适的方法。。。。。请各位指教

85

主题

824

帖子

878

积分

高级会员

Rank: 4

积分
878
QQ
发表于 2004-5-29 14:29:00 | 显示全部楼层

Re:alpha严重性问题

MMX

85

主题

824

帖子

878

积分

高级会员

Rank: 4

积分
878
QQ
发表于 2004-5-29 14:30:00 | 显示全部楼层

Re:alpha严重性问题

或干脆用D3D

47

主题

145

帖子

3602

积分

论坛元老

Rank: 8Rank: 8

积分
3602
 楼主| 发表于 2004-5-29 18:02:00 | 显示全部楼层

Re:alpha严重性问题

现阶段我只能把2D的学起来。。。。3D太难。。。等有了基础再想上攀爬
哪位能否帮我解决这个棘手的问题/》?先谢谢了

47

主题

145

帖子

3602

积分

论坛元老

Rank: 8Rank: 8

积分
3602
 楼主| 发表于 2004-5-29 19:21:00 | 显示全部楼层

Re:alpha严重性问题

哈哈~~问题我自己解决了~~谢谢大家了!~!~!~!

47

主题

145

帖子

3602

积分

论坛元老

Rank: 8Rank: 8

积分
3602
 楼主| 发表于 2004-5-29 19:29:00 | 显示全部楼层

Re:alpha严重性问题

问题正如我所说的。。因为DX下的backbuffer后背缓冲是开在显存的。。。而alpha运算的时候需要CPU来算。。当然内存要比现存来得快了。。。解决方法。。在内存中再开辟一个新的叶面
LPDIRECTDRAWSURFACE lpDDSPic3=NULL;
把计算的结果给它就行了。。最后记得把它的内容BLT到后备缓冲中去。。。然后在进行FLIP。。。。效果最好!!!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-7-1 11:24

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表