游戏开发论坛

 找回密码
 立即注册
搜索
查看: 3860|回复: 10

关于半透明~~~急啊~~拜托

[复制链接]

6

主题

16

帖子

16

积分

新手上路

Rank: 1

积分
16
发表于 2005-8-13 01:00:00 | 显示全部楼层 |阅读模式
本人刚学习ddraw,在在做半透明时遇到了问题,希望大家能帮帮忙

目前我在试做白云在一个有房子的位图上飘过,这里要让云有飘时有半透明效果
本人写了一个,但是运行起来出奇的慢
我的写法是这样的:(估计由于每次调用都要for循环导致,希望能帮我改进,感激不尽)

LPDIRECTDRAW7         lpdd         ;   // dd object
LPDIRECTDRAWSURFACE7  lpddsprimary ;   // dd primary surface
LPDIRECTDRAWSURFACE7  lpddsback
LPDIRECTDRAWSURFACE7 lpddsScreenBack;


/*//////////////////半透明效果///////////////////////////////////////////////////////////////////
    lpddsScreenBack->BltFast(tableRect.left, tableRect.top,
        lpddsback, &tableRect,
        DDBLTFAST_WAIT);

    if (FAILED(lpddsScreenBack->Lock(NULL, &ddsd,
        DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,
        NULL)))
        return;
    int lpitchBack = (USHORT)(ddsd.lPitch>>1);
    USHORT *backBuffer = (USHORT*)ddsd.lpSurface + (SCREEN_HEIGHT - 180)*lpitchBack;
   
    if (FAILED(lpddsTable->Lock(NULL, &ddsd,
        DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,
        NULL)))
        return;
    int lpitchWordTable = (USHORT)(ddsd.lPitch>>1);
    USHORT *tableBuffer = (USHORT*)ddsd.lpSurface;

   
    for (int j=SCREEN_HEIGHT-180; j<SCREEN_HEIGHT-30; j++)
    {
        for (int i=50; i<SCREEN_WIDTH-50; i++)
        {
            backBuffer = ((backBuffer>>1) & 0x7BEF) + ((tableBuffer>>1) & 0x7BEF);
        }
        backBuffer += lpitchBack;
        tableBuffer += lpitchWordTable;
        kk=0;
    }

    if (FAILED(lpddsTable->Unlock(NULL)))
        return;
    if (FAILED(lpddsScreenBack->Unlock(NULL)))
        return;

    lpddsback->BltFast(tableRect.left, tableRect.top,
        lpddsScreenBack, &tableRect,DDBLTFAST_WAIT);
    lpddsprimary->Flip(NULL, DDFLIP_WAIT);

85

主题

824

帖子

878

积分

高级会员

Rank: 4

积分
878
QQ
发表于 2005-8-13 10:10:00 | 显示全部楼层

Re:关于半透明~~~急啊~~拜托

用汇编试试

以下文字引用自<<游戏编程指南>>:
半透明是一个很炫的特效,其原理是把两张图像的每一个点的颜色值做一个平均。下面就说说最容易做,速度最快,同时也是最常见的50%半透明的做法:
        (1)将特效图像(例如火焰什么的)预先用图像处理软件把RGB值都削减一半。
        (2)在刷新屏幕函数中执行此段代码:
__int64 mask=0x7F7F7F7F7F7F7F7F;
int tt=y*lP +x*4; //lP应为后台缓存的lPitch,x和y应为要处理的区域的左上
//角的坐标
__asm
{
movq edx, pB; //pB应为储存特效图像的页面的指针
        mov eax, pS;  //pS应为后台缓存的指针(lpSurfase)
        add eax, tt;
        mov ecx, h; //h为要处理的区域的高度
outloop:
        push eax;
        push edx;
        mov ebx, w; //w为要处理的区域的宽度/2
innloop:
        movq mm0, [eax];
                psrlw mm0, 1;
                movq mm1, [edx];
                pand mm0, mask; //实现"psrlb"
        paddusb mm0, mm1;
        movq [eax], mm0;
        add eax, 8;
        add edx, 8;
        dec ebx;
        jnz innloop;
        pop edx;
        pop eax;
        add eax, lP;
        add edx, lP1; //lP1应为储存特效图像的页面的lPitch
        dec ecx;
        jnz outloop;
        emms;
}

2

主题

132

帖子

132

积分

注册会员

Rank: 2

积分
132
发表于 2005-8-13 12:00:00 | 显示全部楼层

Re:关于半透明~~~急啊~~拜托

这个问题我也遇到过, 但是问题不是出在计算颜色的过程中.
所以即时用了汇编好像也没有多大的反应.......

问题是在创建页面的时候, 创建主页面不要是用FLIP和COMPLEX方式, 也不要使用后台缓冲平面. 只需要指定DDSCAPS_PRIMARYSURFACE就可以了.

创建后台页面创建为标准的DDSCAPS_OFFSCREENPLAIN页面而不是DDSCAPS_BACKBUFFER, 并且把后台页面放入内存 : DDSCAPS_SYSTEMMEMORY

创建图像页面同样放入内存.(只针对需要Lock的表面)

然后就可以Lock了, 很快的速度哦.

最后不要使用: (前台页面指针)->Flip(0,0);
使用: (前台页面指针)->BltFast(0,0,(后台页面指针),&rect,DDBLTFAST_WAIT);

6

主题

16

帖子

16

积分

新手上路

Rank: 1

积分
16
 楼主| 发表于 2005-8-13 18:58:00 | 显示全部楼层

Re:关于半透明~~~急啊~~拜托

to 楼上:
该方法对于不动的来说可行,但是要让云移动就必须用到翻页啊~

困惑啊~~

谢谢你的建议

63

主题

871

帖子

891

积分

高级会员

Rank: 4

积分
891
QQ
发表于 2005-8-13 23:28:00 | 显示全部楼层

Re:关于半透明~~~急啊~~拜托

他的意思是把后台表面放到SYSTEM RAM里,,显存里只放一个PRIMARYSURFACE

然后用BltFast来做后台到前台的显示,,因为回读VIDEO RAM很慢。。。。。。

PS:我的PCE支持很多MMX/SSE加速的色彩混合

       提供DDRAW和DX8的接口,,强大的SOFT2D功能

(做个广告,,不要骂我啊^^)

2

主题

132

帖子

132

积分

注册会员

Rank: 2

积分
132
发表于 2005-8-14 13:06:00 | 显示全部楼层

Re: Re:关于半透明~~~急啊~~拜托

初学者RELAY: Re:关于半透明~~~急啊~~拜托

to 楼上:
该方法对于不动的来说可行,但是要让云移动就必须用到翻页啊~

困惑啊~~

谢谢你的建议



其实这样的方法和翻页的完全一样啊. 只是最后Flip的代码改变了而已.
中间的需要画移动的图形代码可以一模一样的哦.

2

主题

132

帖子

132

积分

注册会员

Rank: 2

积分
132
发表于 2005-8-14 13:07:00 | 显示全部楼层

Re: Re:关于半透明~~~急啊~~拜托

Quest: Re:关于半透明~~~急啊~~拜托

他的意思是把后台表面放到SYSTEM RAM里,,显存里只放一个PRIMARYSURFACE

然后用BltFast来做后台到前台的...


是呀, 不过具体是读取慢还是写入慢就没有测试过.
其他需要Lock的表面全部放入内存.
不需要Lock的还是放入现存.

0

主题

5

帖子

29

积分

注册会员

Rank: 2

积分
29
发表于 2005-8-14 18:42:00 | 显示全部楼层

Re:关于半透明~~~急啊~~拜托

当前的电脑体系架构决定了对显存的读操作是很慢的,从内存->显存的写操作也相对内存->内存的写操作要慢,所以,尽量减少内存和显存之间的数据传输,特别是从显存中读数据
backBuffer = ((backBuffer>>1) & 0x7BEF) + ((tableBuffer>>1) & 0x7BEF);
中,循环中的每句话都涉及到两个从内存中的读操作,所以会很慢。应该把所有的数据操作全部放在内存里面完成,最后把需要显示的数据一次从内存Blit到显存里面,这样效率才会高。所以导致你的这段代码运行慢的原因不是你代码的问题,而是你对计算机体系结构缺乏了解导致。

希望能帮到你^_^

0

主题

5

帖子

29

积分

注册会员

Rank: 2

积分
29
发表于 2005-8-14 18:59:00 | 显示全部楼层

Re:关于半透明~~~急啊~~拜托

还有,你的半透明算法正确吗?原始公式应该是TP = SP1×透明度+ SP2×(1-透明度),其中TP为最终象素值,SP1和SP2为叠加的两个源象素值,透明度为小数。即使原始公式可以变形为其它形式,但也变不到你的公式上去吧?

以上只是第一眼的直觉

32

主题

1583

帖子

1589

积分

金牌会员

Rank: 6Rank: 6

积分
1589
发表于 2005-8-14 19:54:00 | 显示全部楼层

Re:关于半透明~~~急啊~~拜托

要对表面进行逐点计算就得让表面处在SYSTEMMEMORY里面,否则慢死人。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-27 10:19

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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