首页>
技术资讯>
详情

游戏开发学堂:Direct3D 入门之我见

2016-05-29 来源:CloudBest 阅读量: 457
关键词: 程序设计


  Direct3D 是DirectX的成员之一.顾名思义,他是DirectX中负责实现3D图形绘制的部分.现在让我们来讨论一下如何编制一个简单的3D程序的问题.
  
  D3D是一个强大的三维图形绘制使用接口.它提供的高级保留模式(Retain mode) 接口功能强大又方便易用,十分适合初学者使用,所以我们使用这个接口来构造我们的程序.
  
  我们的目的是写一个全屏模式的程序.这就需要使用Direct Draw.更关键的是,D3D Retain mode(以下简称RM)是以DirectDraw为基础才能实现的.如果你对DirectDraw了解不多,也没关系,因为我们将要使到的仅是DirectDraw中极少的一部分.
  
  首先我们通过DirectDraw函数建立DirectDraw对象,函数定义如下:
  
  HRESULT DirectDrawCreate(
  GUID FAR lpGUID,
  LPDIRECTDRAW FAR *lplpDD,
  IUnknown FAR* pUnkOutter
  );
  
  第一个参数是全局唯一标识符,代表着要使用的驱动程序.我们在这里简单的使用NULL填充以表示使用活动的显示驱动程序.第二个参数是个指针,如果调用成功则会把建立的DDraw对象地址付给它.
  第三个参数填NULL就行了.如果调用成功则返回DD_OK.
  
  然后我们就可以用DirectDraw的SetCooperativeLevel函数设置合作级别为独占全屏.函数的一般形式如下:
  
  HRESULT SetCooperativeLevel(
  HWND hwnd,
  DWORD dword
  );
  
  第一个参数是应用程序的窗口句柄.第二个参数用 DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN填充表示使用独占全屏模式.这种模式效率较高,是一般游戏的通用模式.代码形式如下:
  
  LPDIRECTDRAW lpDD;
  HRESULT hr;
  ......//建立DDraw对象,错误处理,等
  
  hr=lpDD->SetCooperativeLevel(NULL,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN);
  if(hr!=DD_OK)
  //错误处理
  
  此后我们就可以设置显示模式了.DirectDraw的SetDisplayMode函数用来设置显示模式.
  
  //假设已有LPDIRECTDRAW对象的指针lpDD
  
  hr=lpDD->SetDisplayMode(640,480,16,0,0);
  if(hr!=DD_OK)
  //错误处理
  
  为了尽可能简化,我们没有使用枚举函数来得到可用的显示模式而是直接使用了一般显示设备都支持的640*480分辨率,16位色.
  
  下一步是创建图像输出的目标--主表面.通过DirectDraw的CreateSurface函数来创建表面.首先填充表面的特征到一个DDSURFACEDESC结构.
  
  LPDIRECTDRAWSURFACE lpDDSPrimary=NULL; //主表面
  DDSURFACEDESC ddsd;
  ......
  ZeroMemory(&ddsd,sizeof(ddsd));
  ddsd.dwSize=Sizeof(ddsd);
  ddsd.dwFlags=DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
  ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE| //主表面
  DDSCAPS_FLIP| //可实现翻转动画
  DDSCAPS_COMPLEX|
  DDSCAPS_VIDEOMEMORY|
  DDSCAPS_3DDEVICE; //可以作为D3D 设备
  ddsd.dwBackBufferCount=1; //后备缓冲表面数目为1
  hr=lpDD->CreateSurface(&ddsd,&lpDDSPrimary,NULL);
  if(hr!=DD_OK)
  //错误处理
  
  如果创建成功,我们就有了一个有后缓冲,可实现翻转的,可作为D3D设备的主表面(关于D3D设备,后面还要讲到)然后我们用GetAttachedSurface函数获得指向后备缓冲的指针:
  
  DDSCAPS ddscaps;
  LPDIRECTDRAWSURFACE lpDDSBackbf;
  ......
  ddscaps.dwCaps=DDSCAPS_BACKBUFFER|DDSCAPS_3DDEVICE ;
  hr=lpDDSPrimary->GetAttachedSurface(&ddscaps,&lpDDSBackbf);
  if(hr!=DD_OK)
  //错误处理
  
  一切准备工作就绪,我们就可以开始使用D3D RM了.
  
  RM的最大好处就在于其形象性.不必再在十分抽象的层面上去理解"对象"这一概念.我们完全可以把对象理解为诸如光源,3D物体和摄像机之类的实物.
  
  首先通过Direct3DRMCreate建立一个D3D保留模式对象.它是一切RM对象的基础,只有通过它才能建立其他RM对象.
  
  LPDIRECT3DRM lpD3Drm;
  ......
  hr=Direct3DRMCreate(&lpD3Drm);
  if(hr!=DD_OK)
  //错误处理
  
  然后我们用QueryInterface方法查询一个更新版本的接口并使用它:
  
  hr =lpD3Drm->QueryInterface(IID_IDirect3DRM3,(LPVOID *)&lpD3DrmNew);
  if(FAILED(hr))
  //错误处理
  
  这时旧的接口已经无用,释放它:
  lpD3Drm->Release();
  
  前面我们已经建立了一个DirectDraw表面(Surface)对象,现在我们用它来建立D3DRM设备(Device)对象.设备对象代表了最终图像渲染到的设备和所用的显示驱动程序.在这里使用的是默认设备即显示器.函数如下:
  
  HRESULT CreateDeviceFromSurface(
  LPGUID lpGUID,
  LPDIRECTDRAW lpDD,
  LPDIRECTDRAWSURFACE lpDDSBack,
  LPDIRECT3DRMDEVICE3 * lplpD3DRMDevice,
  );
  
  第一个参数是指向GUID结构变量的指针.GUID是"全局唯一标识符",是Windows系统对可用设备的唯一标识.在这里指的是渲染所用的方式(如软加速,硬加速)为了尽可能简化程序可以直接用NULL表示用默认的方式.建立过程代码如下:
  
  LPDIRECT3DRMDEVICE3 lpDevice;
  hr=lpD3DrmNew->CreateDeviceFromSurface(NULL,(LPDIRECTDRAW)lpDD,
  lpDDSBackbf,
  0,&lpDevice);
  if(FAILED(ddrval))
  //错误处理
  
  现在我们终于可以创建真正意义上的3D对象了.我们有必要先弄清"Frame"(框架)这一概念."Frame"就像一个玻璃盒子,里面可以装任何3D物体,如飞机,坦克,食人魔.Frame可以被设置方向和位置,这时它所装的3D物体也会与它保持同样的方向,位置.Frame是D3DRM的灵魂.
  
  一个场景往往包含一个由Frame构成的层次,即由根Frame及其子Frame(子Frame还可以有子Frame)构成的树型结构.父Frame和子Frame的关系,就像大臂和前臂的关系一样,

热门推荐 查看更多