网页功能: 加入收藏 设为首页 网站搜索  
再谈GDI模式作图
发表日期:2006-08-20作者:[转贴] 出处:  

为什么选择GDI?
我并不觉得写游戏用GDI是件好事,然而如果你打算写点小打小闹的程序,选择GDI作图是个好主意,但我觉得更妙的是GDI的开销小,不必象DX那么大动干戈,最让我动心的是它和Windows的控件可以紧密结合比如在C++Builder里面可以通过控制每个控件的HDC来达到自己给控件画图的目的,而且用GDI编写一个地图编辑器是相当方便的事情,配合VCL或者MFC在小规模的图形编程方面DirectX完全是不能比的。

使用的原则
我现在做图形化程序用的是VC写界面程序用的是C++Builder,而研究算法程序用的是BC++3.1。而最近又养成一个坏习惯:写2D图形程序用DDraw而写开始写3D时又用OpenGL。所以写于平台无关的代码对我来说有着迫切的需要,说这个的目的是我打算用WinAPI而不是CBitmap或者TBitmap来完成,代码只可以在VC或者BCB底下运行并不是好主意,因此用API写关键部分然后再配合VCL或者MFC,因此抽象出一个Bitmap类,提供BLIT, LoadFromStream, LoadFromFile, Lock, Unlock等操作,是一个好主意,DDraw的表面Dx8的纹理,或者OpenGL里面的纹理还有GDI位图都通过继承它来实现某些共同特性的功能,实现统一接口的调用,代码做到不偏不倚才能灵活的运用于各个平台。

速度是关键
实现的GDI位图必须是可以自己渲染的及Lock/Unlock的实现。其次就是BLIT的实现,可能我见识有限,我看过的关于GDI文章或者代码对于BLIT功能都是以一种相当慢或者不稳定的方式处理的:

 
1. 根据DIB缓冲区调用CreateBitmap创建一个hBitmap
2. 用CreateCompatibleDC创建一个hDC
3. 用SelectObject把hBitmap选进hDC
4. 然后BitBlt在实现两个hDC间的BLIT功能
 
直接用SetDIBitsToDevice把位图传递到HDC上面,直接送DIB数据到HDC

我们看看第一种方法Windows到底做了些什么:1.首先创建一个大小和DIB一样的hBitmap然后把数据复制过去 2.简单创建一个hDC 3.把hBitmap设置成为hDC的作图对象 4.做BitBlt。这样可以明显看出,速度在1/2两步被拖的地方太多了。于是我发现了第二种方法,速度真实快,但是这种方法最不好的就是基于字节的传送得不到硬件加速。且如果我直接把DIB数据传送到桌面HDC上时就要出错,只有传到窗口的HDC上才稳定。

两种方法对我来说都没有真正发挥GDI的好处,于是下面我介绍神秘的第三种方法。不知各位可曾注意,大名鼎鼎的《图形程序员指南》曾有涉及GDI作图的片段代码,那就是一个步常被WinAPI提及的一个Win32 API:CreateDIBSection。请看说明:


The CreateDIBSection function creates a device-independent bitmap (DIB) that applications can write to directly. The function gives you a pointer to the location of the bitmap's bit values. You can supply a handle to a file mapping object that the function will use to create the bitmap, or you can let the operating system allocate the memory for the bitmap.

 

HBITMAP CreateDIBSection(

 
  HDC hdc, // handle to device context
  CONST BITMAPINFO *pbmi, // pointer to structure containing bitmap size, format, and color data
  UINT iUsage, // color data type indicator: RGB values or palette indices
  VOID *ppvBits, // pointer to variable to receive a pointer to the bitmap's bit values
  HANDLE hSection, // optional handle to a file mapping object
  DWORD dwOffset) // offset to the bitmap bit values within the file mapping object

于是作图步奏不同了,首先用CreateDIBSection从DIB创建hBitmap此时Windows不再复制DIB数据到hBitmap而是直接使用DIB数据为基础每次跟新DIB的点阵数据时hBitmap也就发生了变化,而不象CreateBitmap那样需要再次创建,于是这下第一种方法的一到三步的工作就可以提前到创建DIB的时候,实验证明,这样的做法比通常的做法要快两到三倍!!这是制关重要的提高,大家不信可以自己试试,下面是一个老外写的经典代码,使用了CreateDIBSection的,代码虽然用Delphi写成,不过WinAPI是不变的:-)

我来说两句】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 再谈GDI模式作图
本类热点文章
  在DirectX 8 中进行2D渲染
  DirectDraw打造极速图形引擎(一)
  用窗口模式运行游戏
  DirectDraw编程基础
  Windows的位图alpha混合技术
  再谈GDI模式作图
  终极优化你的游戏——使用脏矩形技术
  D3D8里面的2D图形编程
  全屏模式
  对2D游戏引擎设计的一些思考
  DirectX8中的二维图形高级技巧
  使用标准GDI实现游戏品质的动画系统
最新分类信息我要发布 
最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放  
Copyright ©2003-2024 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00425