三、 利用DirectDraw完成对图形的加速
从前面可以看出,我们一直在处理速度上比较严格。竭尽所能来提高数据的处理速度,不仅在算法上如此,在显示上更是如此。普通的GDI函数的处理速度在这里是无法容忍的,对此采用了DirectX系列技术中的DirectDraw技术来对图形进行加速处理。
DirectDraw是DirectX SDK系列中的一员,也是其中最主要的一个部件。它允许程序员直接的操作显存、硬件位图映射以及硬件覆盖和换页技术。它在提供直接访问显示设备的同时,与GDI相兼容,它只是一个软件接口,提供了一种与设备无关的途径,以获得访问特定的显示设备的某些高级特性的能力。大体上DirectDraw可以提供了以下几个功能,而这些功能以前只有那些专为特定显示设备所写的软件中才能使用:
·支持双缓冲和换页图形
·访问、控制显示卡的位图映射
·支持3D z-buffers (z缓存)
·支持z方向(z-ordering)硬件辅助覆盖。
·访问图形缩放硬件
·仿真访问标准的和增强的显示设备内存空间
下面就对DirectDraw的在图形加速方面中的具体应用结合本程序的具体实例来进行介绍,为方便起见,本工程采用Microsoft SDK编码,先要对DirectDraw环境进行初始化,完成设置并在其中对主页面和各离屏页面进行创建并初始化之:
BOOL InitDDraw(void) { DDSURFACEDESC ddsd; HRESULT ddrval; …… //创建DirectDraw对象 ddrval = DirectDrawCreate( NULL, &lpDD, NULL ); …… //取得全屏独占模式 ddrval = lpDD->SetCooperativeLevel(hwndful, DDSCL_EXCLUSIVE | DSCL_FULLSCREEN ); …… //设置显示器显示模式 ddrval = lpDD->SetDisplayMode( DISPLAYMODEWIDTH,DISPLAYMODEHEIGHT, 24); …… //填充主页面信息 ddsd.dwSize = sizeof( ddsd ); ddsd.dwFlags = DDSD_CAPS ; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; //创建主页面对象 ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL ); …… ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN |DDSCAPS_SYSTEMMEMORY ; …… lpDD->CreateSurface(&ddsd, &lpDDSPic1, NULL) ; …… lpDD->CreateSurface(&ddsd, &lpDDSPic2, NULL); …… lpDD->CreateClipper(0, &lpClipper, NULL); lpClipper->SetHWnd(0, hwndful); lpDDSPrimary->SetClipper(lpClipper); …… //初始化页面图像 DDReLoadBitmap(lpDDSPic1, MAKEINTRESOURCE(IDB_BITMAP1)); DDReLoadBitmap(lpDDSPrimary,MAKEINTRESOURCE(IDB_BITMAP2)); …… ZeroMemory(buf1, BACKWIDTH*BACKHEIGHT*sizeof(short)); ZeroMemory(buf2, BACKWIDTH*BACKHEIGHT*sizeof(short)); …… return TRUE; } |
另外,必须在应用程序活跃时不断的进行更新,方可完成对整个过程的模拟,在更新帧的函数中负责完成对数据的实时处理及对页面的渲染,最重要的环节--将离屏页面2装载到主页面的工作也将在这里完成:
…… DropStone((int)(BACKWIDTH*((short)rand()/32767.0)), (int)(BACKHEIGHT*((short)rand()/32767.0)), 2,64);//激励点为随机产生,模拟雨点落在水面的情形 Spread();//计算振幅数据缓冲区 Render();//页面渲染 //在window内显示页面2 lpDDSPrimary->Blt(&Window, lpDDSPic2, NULL, DDBLT_WAIT, NULL); …… |
在前面的处理光的折射的Rander()函数中也应增添对页面的渲染部分的编码,可以用一个页面来装载原始的图象,用另外一个页面来进行渲染。先用Lock函数锁定两个页面,取得指向页面内存区的指针,然后根据偏移量将原始图象上的每一个象素复制到渲染页面上:
…… //锁定两个离屏页面 DDSURFACEDESC ddsd1, ddsd2; ddsd1.dwSize = sizeof (DDSURFACEDESC); ddsd2.dwSize = sizeof(DDSURFACEDESC); lpDDSPic1->Lock(NULL, &ddsd1, DDLOCK_WAIT, NULL); lpDDSPic2->Lock(NULL, &ddsd2, DDLOCK_WAIT, NULL); //取得页面象素位深度,和页面内存指针 int depth=ddsd1.ddpfPixelFormat.dwRGBBitCount/8; BYTE *Bitmap1 = (BYTE*)ddsd1.lpSurface; BYTE *Bitmap2 = (BYTE*)ddsd2.lpSurface; …… //中间为对光的折射模拟过程的代码 …… //解锁页面 lpDDSPic1->Unlock(&ddsd1); lpDDSPic2->Unlock(&ddsd2); |
最后,为了养成良好的编程习惯,应在程序退出之前释放掉所使用过的资源,在这里主要为对各个页面的释放以及对DirectDraw对象lpDD的释放:
…… lpDDSPrimary->Release(); lpDDSPic1->Release(); lpDDSPic2->Release(); lpClipper->Release(); lpDD->Release(); …… |
经过上述几步,已基本完成了对水波的模拟工作。通过对DirectDraw技术的应用,在取得了对图形的硬件加速支持后可以在计算机上很流畅地完成对水波自产生、扩散到消失的全部过程的仿真模拟。
小结:
通过本文所述的对自然事物的计算机模拟的实现过程,可以对仿真模拟类程序的一般实现过程有基本的认识,在理解本程序的设计思路与方法的前提下也可以用类似的方法设计出对其他事物的模拟算法。本程序结合具体程序设计要求合理和有效的利用DirectDraw的图形硬件加速等特性很好的实现了对水波模拟的过程显示,对于其他仿真程序的设计也可以根据实际灵活的选用诸如OpenGL、Direct3D等不同的软件接口。本文所述程序在Windows 2000下,在DirectX 9.0的支持下,由Microsoft Visual C++ 6.0编译调试通过。 
说明:本教程来源互联网或网友上传或出版商,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。
2/2 首页 上一页 1 2 |