游戏开发论坛

 找回密码
 立即注册
搜索
楼主: sandy_zc_1

用DDraw画点线到底有多少优势?

[复制链接]

60

主题

1319

帖子

1319

积分

金牌会员

Rank: 6Rank: 6

积分
1319
发表于 2004-10-16 14:52:00 | 显示全部楼层

Re:用DDraw画点线到底有多少优势?

你的程序是VB的吗?

32

主题

1583

帖子

1589

积分

金牌会员

Rank: 6Rank: 6

积分
1589
 楼主| 发表于 2004-10-16 19:14:00 | 显示全部楼层

Re:用DDraw画点线到底有多少优势?

哇………………
慢点

首先,我画点不是使用Lock/UnLock。
DirectX中的DirectDrawSurface对象提供了画基本图型的函数,包括画圆的、矩形的、画线的等等,不过没有专门画点的。

其次,我在以前练习使用调色板时使用过Lock/UnLock函数,自己绘制感觉速度也不是有多快。这也就是为什么我做Alpha时觉得DX不方便的原因。

最后,我的程序是VB的,淡这和画点没有什么关系。

60

主题

1319

帖子

1319

积分

金牌会员

Rank: 6Rank: 6

积分
1319
发表于 2004-10-16 20:14:00 | 显示全部楼层

Re:用DDraw画点线到底有多少优势?

是没什么关系,不过C++版IDirectDrawSurface接口没有那些函数,VB版的有。

32

主题

377

帖子

378

积分

中级会员

Rank: 3Rank: 3

积分
378
发表于 2004-10-16 21:36:00 | 显示全部楼层

Re:用DDraw画点线到底有多少优势?

试试mmx,直接在后台页面上画点或线,再贴到主页面上……

13

主题

978

帖子

978

积分

高级会员

Rank: 4

积分
978
发表于 2004-10-18 09:53:00 | 显示全部楼层

Re:用DDraw画点线到底有多少优势?

你把页面建在哪里了?一般情况下最好建到内存中。还有,如果你想编效果更好的游戏,就放弃vb吧。它写的程序一般比c/c++至少慢20%。
d2d编程要多用mmx指令。可以参考gameres的ftp服务器上的《游戏编程指南》。
如果光画点的话,不如建一个1*1的surface再blt到缓存中,实在不行——memcpy

32

主题

1583

帖子

1589

积分

金牌会员

Rank: 6Rank: 6

积分
1589
 楼主| 发表于 2004-10-18 19:55:00 | 显示全部楼层

Re:用DDraw画点线到底有多少优势?

问题这不是VB的问题呀,如果不画点的话FPS是166呢!

MMX指令?试一下。

60

主题

1319

帖子

1319

积分

金牌会员

Rank: 6Rank: 6

积分
1319
发表于 2004-10-19 07:48:00 | 显示全部楼层

Re:用DDraw画点线到底有多少优势?

VB支持内嵌汇编吗?还是有别的方法用MMX?

60

主题

1319

帖子

1319

积分

金牌会员

Rank: 6Rank: 6

积分
1319
发表于 2004-10-19 07:50:00 | 显示全部楼层

Re:用DDraw画点线到底有多少优势?

MMX我也曾经想学,不过汇编基础太差了。周围的人都学Java的,我再学汇编不知道会不会被人笑话。

13

主题

978

帖子

978

积分

高级会员

Rank: 4

积分
978
发表于 2004-10-19 11:23:00 | 显示全部楼层

Re:用DDraw画点线到底有多少优势?

学java和学汇编是两个概念,顶尖高手肯定都会汇编
这是《游戏编程指南》里的一些东西:(我也不会汇编,只好直接照抄了)

5.6         程序提速
上面的程序看起来好像很简单,但运行速度很可能会很慢,即使你直接用汇编重写也不会快多少。原因是读显存非常慢,写显存的速度也比写内存慢。解决这个问题的方法是:
(1)        把除了主页面外的所有页面放在内存中(初始化页面时将ddsd.ddsCaps.dwCaps中的 DDSCAPS_OFFSCREENPLAIN后再或( | )一项DDSCAPS_SYSTEMMEMORY),当然也要将主页面的页面描述改一下:
        ddsd.dwSize=sizeof(ddsd);
        ddsd.dwFlags=DDSD_CAPS;
        ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE;
           
后台缓冲改为一个普通的离屏页面。这样做的另一个好处是你Lock( )一次后就永远得到了页面指针,而且然后一Unlock( )就又可以使用Blt了。所以你就拥有了两种改变页面的手段。

(2)        将Flip( )和不带透明色的BltFast( )改成直接用memcpy( )拷贝。注意要一行一行地拷贝,比如说640x480x24位色下的全屏幕拷贝是这样的:
BYTE *pSrc=(BYTE *)ddsd_src.lpSurface; //源页面
BYTE *pDest=(BYTE *)ddsd_dest.lpSurface; //目标页面

for (int y=0;y<480;y++)
{
        memcpy(pDest, pSrc, 1920); //若为32位色则为2560=640*32/8
        pSrc+=ddsd_src.lPitch; //移至下一行
        pDest+=ddsd_dest.lPitch; //移至下一行
}

        事实上memcpy( )还有进一步“压榨”的余地,下面是用SSE指令实现的超高速memcpy( )。把它拷贝到你的程序中享受完美的速度吧(快80%以上),呵呵(nQWORDs为要拷贝多少个8字节,注意它应能整除8!)。
void Qmemcpy(void *dst, void *src, int nQWORDs)
{
        #define CACHEBLOCK 1024 //一个块中有多少QWORDs
                                                                //修改此值有可能实现更高的速度
        int n=((int)(nQWORDs/CACHEBLOCK))*CACHEBLOCK;
        int m=nQWORDs-n;
        if (n)
        {
                _asm //下面先拷贝整数个块
                {
                        mov esi, src
                        mov edi, dst
                        mov ecx, n                        //要拷贝多少个块
                        lea esi, [esi+ecx*8]
                        lea edi, [edi+ecx*8]
                        neg ecx
        mainloop:
                        mov eax, CACHEBLOCK / 16
        prefetchloop:
                        mov ebx, [esi+ecx*8]                 //预读此循环
                        mov ebx, [esi+ecx*8+64]        //预读下循环
                        add ecx, 16
                        dec eax
                        jnz prefetchloop
                        sub ecx, CACHEBLOCK
                        mov eax, CACHEBLOCK / 8
        writeloop:
                        movq mm0, qword ptr [esi+ecx*8    ]
                        movq mm1, qword ptr [esi+ecx*8+8 ]
                        movq mm2, qword ptr [esi+ecx*8+16]
                        movq mm3, qword ptr [esi+ecx*8+24]
                        movq mm4, qword ptr [esi+ecx*8+32]
                        movq mm5, qword ptr [esi+ecx*8+40]
                        movq mm6, qword ptr [esi+ecx*8+48]
                        movq mm7, qword ptr [esi+ecx*8+56]

                        movntq qword ptr [edi+ecx*8   ], mm0
                        movntq qword ptr [edi+ecx*8+8 ], mm1
                        movntq qword ptr [edi+ecx*8+16], mm2
                        movntq qword ptr [edi+ecx*8+24], mm3
                        movntq qword ptr [edi+ecx*8+32], mm4
                        movntq qword ptr [edi+ecx*8+40], mm5
                        movntq qword ptr [edi+ecx*8+48], mm6
                        movntq qword ptr [edi+ecx*8+56], mm7
                        add ecx, 8
                        dec eax
                        jnz writeloop
                        or ecx, ecx
                        jnz mainloop
                }
        }
        if (m)
        {
        _asm
        {
                mov esi, src
                mov edi, dst
                mov ecx, m
                mov ebx, nQWORDs
                lea esi, [esi+ebx*8]
                lea edi, [edi+ebx*8]
                neg ecx
copyloop:
                prefetchnta [esi+ecx*8+512]  //预读
                movq mm0, qword ptr [esi+ecx*8   ]
                movq mm1, qword ptr [esi+ecx*8+8 ]
                movq mm2, qword ptr [esi+ecx*8+16]
                movq mm3, qword ptr [esi+ecx*8+24]
                movq mm4, qword ptr [esi+ecx*8+32]
                movq mm5, qword ptr [esi+ecx*8+40]
                movq mm6, qword ptr [esi+ecx*8+48]
                movq mm7, qword ptr [esi+ecx*8+56]

                movntq qword ptr [edi+ecx*8   ], mm0
                movntq qword ptr [edi+ecx*8+8 ], mm1
                movntq qword ptr [edi+ecx*8+16], mm2
                movntq qword ptr [edi+ecx*8+24], mm3
                movntq qword ptr [edi+ecx*8+32], mm4
                movntq qword ptr [edi+ecx*8+40], mm5
                movntq qword ptr [edi+ecx*8+48], mm6
                movntq qword ptr [edi+ecx*8+56], mm7
                add ecx, 8
                jnz copyloop
                sfence
                emms
        }
}
else
{
        _asm
        {
                sfence
                emms
        }
}
}

        同样的,memset也可用SSE指令优化(快300%以上),代码在此(nQWORDs应能被8整除):
void Qmemset(void *dst, int c, unsigned long nQWORDs)
{
        __asm
        {
                movq mm0, c
                punpcklbw mm0, mm0
punpcklwd mm0, mm0
punpckldq mm0, mm0
                mov edi, dst

                mov ecx, nQWORDs
                lea        edi, [edi + ecx * 8]
                neg ecx

                movq        mm1, mm0
                movq        mm2, mm0
                movq        mm3, mm0
                movq        mm4, mm0
                movq        mm5, mm0
                movq        mm6, mm0
                movq        mm7, mm0

loopwrite:
                movntq         [edi + ecx * 8     ], mm0
                movntq         [edi + ecx * 8 + 8 ], mm1
                movntq         [edi + ecx * 8 + 16], mm2
                movntq         [edi + ecx * 8 + 24], mm3
                movntq         [edi + ecx * 8 + 32], mm4
                movntq         [edi + ecx * 8 + 40], mm5
                movntq         [edi + ecx * 8 + 48], mm6
                movntq         [edi + ecx * 8 + 56], mm7

                add ecx, 8
                jnz loopwrite

                emms
        }
}

(3)        由于DirectDraw提供的带透明色的BltFast( )此时的工作效率不容乐观,所以我们可以使用RLE压缩掉透明色,同时自己写一个能传送带透明色的图像的函数。你可能已经听过RLE压缩,没听过也没关系,下面就举个例子。如果你定义透明色为(255,0,255),那么这样的一串点:(255,0,255), (255,0,255) , (255,0,255), (255,0,255), (100,23,43), (213,29,85), (255,0,255), (34,56,112), (255,0,255), (255,0,255)可用这样的方式存储:
首先是4个透明点,那么我们在开头放一个0,表示由透明色开头,否则需放一个1。然后是0,12,(表示需跳过4x3=0012个字节),接着是0,2,(即后面为002个图像点),100,23,43,213,29,85,0,3(需跳过003个字节),0,1(后面为001个图像点),34,56,112,0,6(需跳过006个字节)。这样用20个字节就表示出了原来需要30个字节的图像,而且BLT时速度更快,因为无须对每一个点进行判断是否透明色。
一般来说,RLE压缩只在图像的每一行内进行(而不是将整块图像作为一个整体)以方便编程。
如果你还需要更快的速度而不在乎文件大小的话,还有一种比较“邪”的解决方案,其思路是用另外一个程序自动生成成千上万条赋值指令实现BLT。这种办法可以省去大量判断和跳转指令所耗的时间,速度显然达到顶峰。

看起来好像要重写很多东西,其实改动的部分并不多。这样改了之后整个程序的速度就会快很多,但还不能很好地满足全屏幕特效的要求,因为全屏幕特效实在很耗时间,只有用汇编和MMX等指令重写速度才能比较快。所以在下面一章中,我们将介绍内嵌汇编和MMX指令。当然,你直接用5.7节的现成代码也行。

13

主题

978

帖子

978

积分

高级会员

Rank: 4

积分
978
发表于 2004-10-19 11:26:00 | 显示全部楼层

Re:用DDraw画点线到底有多少优势?

我看的头都晕了……………………
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-22 21:09

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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