【DirectX 9.0学习之路(第二话)】——Direct3D初始化(下)

Direct3D初始化(下)


Direct3D初始化步骤:

        (1)获取接口  IDirect3D9  的指针。
        (2)检查设备性能(D3DCAPS9,判断主否支持硬件顶点运算。
        (3)初始化  D3DPRESENT_PARAMETERS  结构体的一个实例。该结构体的众多变量可以指定将要创建的接口 IDirect3DDevice9 的特性。
        (4)利用已经初始化的 D3DPRESENT_PARAMETERS 结构体创建IDirect3DDevice9对象(一个C++对象,代表显示3D图像的物理硬件设备)。

第一步:获取接口  IDirect3D9  的指针

        IDirect3D9  *d3d9;
        d3d9 = Direct3DCreate9(D3D_SDK_VERSION);

第二步:检验硬件定点运算
       我们需要检查主显卡是否支顶点运算。
        所用函数:
        HRESULT  IDirect3D9::GetDeviceCaps(
                UINT  Adapter,                          //指定物理显卡序号
                D3DDEVTYPE  DeviceType,       //指定设备类型(D3DDEVTYPE_HAL 硬件设备, D3DDEVTYPE_REF 软件设备)
                D3DCAPS9  *pCaps                   //返回设备性能结构体实例
        );
具体代码如下:
D3DCAPS9 caps;
d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps);
int vp = 0;
if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
{
	vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; //硬件顶点运算类型 
}
else {
	vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; //软件顶点运算类型 
}
//注意,我们用变量vp保存顶点运算类型, 因为在创建IDirect3DDevice类型
//的对象的时候,必须指定以后所需要使用的顶点运算类型。 

第三步:填充D3DPRESENT_PARAMETERS结构体
typedef struct D3DPRESENT_PARAMETERS {
  UINT                BackBufferWidth;                //后台缓存中表面的宽度
  UINT                BackBufferHeight;               //后台缓存中表面的高度
  D3DFORMAT           BackBufferFormat;               //后台缓存的像素格式  (如32位像素格式:D3DFMT_A8R8G8B8)
  UINT                BackBufferCount;                //后台缓存的个数
  D3DMULTISAMPLE_TYPE MultiSampleType;                //后台缓存采用的多重采样类型
  DWORD               MultiSampleQuality;             //多重采样的质量水平
  D3DSWAPEFFECT       SwapEffect;                     //交换链缓存的页面置换方式
  HWND                hDeviceWindow;                  //窗口句柄
  BOOL                Windowed;                       //true为窗口模式,false为全屏模式
  BOOL                EnableAutoDepthStencil;         //为true,则自动创建并维护深度缓存或模板缓存
  D3DFORMAT           AutoDepthStencilFormat;         //深度缓存或者模板缓存的像素格式
  DWORD               Flags;                          //一些附加的特征。
  UINT                FullScreen_RefreshRateInHz;     //刷新频率
  UINT                PresentationInterval;           //D3DPRESENT集合的一个成员
} D3DPRESENT_PARAMETERS, *LPD3DPRESENT_PARAMETERS;
详细参数说明,见后续文章【DirectX 9.0学习之路(第三话)】——D3DPRESENT_PARAMETERS 结构参数的详细说明。
一个填充实例:
D3DPRESENT_PARAMETERS d3dpp;
		
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.MultiSampleQuality = 0;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.Windowed = windowed;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.Flags = 0;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

第四步:创建IDirect3DDevice9接口
使用的方法:    
HRESULT CreateDevice(
  [in]           UINT Adapter,     //指定IDirect3DDevice9对象代表那块物理显卡
  [in]           D3DDEVTYPE DeviceType,   //指定使用的设备类型
  [in]           HWND hFocusWindow,       //窗口句柄
  [in]           DWORD BehaviorFlags,
  [in, out]      D3DPRESENT_PARAMETERS *pPresentationParameters,  //返回已经完成初始化的D3DPRESENT_PARAMETERS 类型的实例指针(很重要)
  [out, retval]  IDirect3DDevice9 **ppReturnedDeviceInterface     //返回所创建的设备
);
下面是一个调用实例:
D3DPRESENT_PARAMETERS d3dpp;
IDirect3DDevice9 *device = 0;

hr = d3d9->CreateDevice(
	D3DADAPTER_DEFAULT,
	D3DDEVTYPE_HAL,
	hWnd,
	D3DCREATE_HARDWARE_VERTEXPROCESSING,
	&d3dpp,
	&device); 
	
	if(FAILED(hr)) {
	::MessageBox(0, "CreateDevice() - FAILED", 0, 0);
	return 0;
	}

        在开始写代码之前,首先我们将Direct3D的初始化相关的操作封装于d3dUtility.h/d3dUtility.cpp文件中。在以后的工程中可以直接调用,提高开发效率。
d3dUtility.h头文件:
//d3dUtility.h文件
#include <d3dx9.h>
 
 namespace d3d {
 	//D3D初始化函数声明 
 	bool InitD3D(
	 	HINSTANCE hInstance,
	 	int width,
	 	int height,
	 	bool windowed,
	 	D3DDEVTYPE deviceType,
	 	IDirect3DDevice9 **device);
	
	//消息循环声明	
	int EnterMsgLoop(
		bool (*ptr_display)(float timeDelta)
		);
	
	//消息处理函数声明 
	LRESULT CALLBACK WndProc(
		HWND hWnd,
		UINT msg,
		WPARAM wParam,
		LPARAM lParam);
	
	//释放COM对象	
	template<class T> void Release(T t) {
		if(t) {
			t->Release();
			t = 0;
		}
	}
	
	//删除对象 
	template<class T> void Delete(T t) {
		if(t) {
			delete t;
			t = 0;
		}
	}	
 }

d3dUtility.cpp源文件
//d3dUtility.cpp源文件

bool d3d::InitD3D(
	HINSTANCE hInstance,
	int width,
	int height,
	bool windowed,
	D3DDEVTYPE deviceType,
	IDirect3DDevice9 **device) 
	{
		
		//第一步:获取IDirect3D9对象指针 
		IDirect3D9 *d3d9;
		d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
		
		//第二步:检验硬件顶点运算
		D3DCAPS9 caps;
		d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps);
		int vp = 0;
		if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
		{
			vp = D3DCREATE_HAEDWARE_VERTEXPROCESSING;
		}
		else {
			vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
		}
		
		//第三步:填充D3DPRESENT_PARAMETERS结构体
		D3DPRESENT_PARAMETERS d3dpp;
		
		d3dpp.BackBufferWidth = width;
		d3dpp.BackBufferHeight = height;
		d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
		d3dpp.BackBufferCount = 1;
		d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
		d3dpp.MultiSampleQuality = 0;
		d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
		d3dpp.hDeviceWindow = hWnd;
		d3dpp.Windowed = windowed;
		d3dpp.EnableAutoDepthStencil = TRUE;
		d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
		d3dpp.Flags = 0;
		d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
		d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
		
		//第四步:创建IDirect3DDevice9接口 
		IDirect3DDevice9 *device = 0;
		HRESULT hr;
		hr = d3d9->CreateDevice(
			D3DADAPTER_DEFAULT,
			D3DDEVTYPE_HAL,
			hWnd,
			D3DCREATE_HAEDWARE_VERTEXPROCESSING,
			&d3dpp,
			&device);
		if(FAILED(hr)) {
			::MessageBox(0, "CreateDevice() - FAILED", 0, 0);
			return 0;
		}

		return true;
	}
	
	
	int d3d::EnterMsgLoop(bool (*ptr_display)(float timeDelta))
	{
		MSG msg;
		::ZeroMemory(&msg, sizeof(MSG));
		
		static float lastTime = (float)timeGetTime();
		
		while(msg.message != WM_QUIT) {
			if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
				::TranslateMessage(&msg);
				::DispatchMessage(&msg);
			}
			else {
				float currentTime = (float)timeGetTime();
				float timeDelta = (currentTime - lastTime)*0.001f;
				
				ptr_display(timeDelta); //渲染
				
				lastTime = currentTime; 
			}
		}
		return msg.wParam;
	}
	 


程序框架:
(1) bool  SetUp()  例程所需要进行的全部设置和初始化。
(2) void  Display(float  timeDelta) 实现全部的绘制代码以及相邻帧之间应执行的操作,例如更新物体的位置。参数timeDelta是相邻帧之间的时间差,主要用于将动画与显示器的刷新频率保持同步。


综合例程:
  
   
        


你可能感兴趣的:(DirectX,DirectX,Direct3D,9.0,Direct3D初始化)