博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【笔记】《DirectX 9.0 3D游戏开发编程基础》:Direct3D初始化
阅读量:6148 次
发布时间:2019-06-21

本文共 6013 字,大约阅读时间需要 20 分钟。

Direct3D初始化大概分为4个步骤:

1.获取接口IDirect3D9的指针。(Direct3DCreate9函数调用)。

     该接口用户获取系统中物理硬件设备的信息并创建接口IDirect3DDevice9,此接口是一个C++对象,代表显示3D图形的物理硬件设备。

2.检查设备性能(D3DCAPS9结构体),判断主显卡是否支持某些特性,比如是否支持顶点运算。创建IDirect3DDevice9之前,必须确定主显卡支持的特性。

3.初始化D3DPRESENT_PARAMETER结构的一个实例,通过设置该结构体的成员变量来指定即将创建的借口IDirect3DDevice9的特性。

4.利用已经初始化的D3DPRESENT_PARAMETER结构创建IDirect3DDevice9对象。

 

以下是DirectX 9.0 3D游戏开发编程基础的基本程序框架(包含初始化的过程):

d3dUtility.h

 InitD3D:该函数对应用程序主窗口进行了初始化(windows程序设计的基础,RegisterClass,CreateWindow,ShowWindow,UpdateWindow);

             然后执行Direct3D初始化过程,返回一个指向已经创建好的IDirect3DDevice9接口的指针。

EnterMsgLoop:封装了消息循环,参数为一个指向显示函数的函数指针。空闲处理期间显示场景。

Release:模板函数是方便地释放COM接口并将其设置为NULL。

Delete:模板函数是方便地删除自由堆对象,将其指针设置为NULL。

WndProc:主窗口的窗口过程函数,针对不同类型的消息进行相对应的相应。

#ifndef D3DUTILITY_H#define D3DUTILITY_H#include 
#include
#include
namespace d3d { bool InitD3D( HINSTANCE hInstance, int width, int height, bool windowed, D3DDEVTYPE deviceType, IDirect3DDevice9 **device); //[in] 应用实例 [in] 后台缓存的宽 [in]后台缓存的高 [in] 是否窗口或者全屏 [in] 设备类型 HAL或REF [out] 初始化成功的IDirect3DDevice指针 int EnterMsgLoop( bool (*ptr_display)(float timeDelta) ); LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); template
void Release(T t) { if( t ) { t->Release(); t = 0; } } template
void Delete(T t) { if( t ) { delete t; t = 0; } }}#endif

d3dUtility.cpp

上述接口的具体实现部分。

#include "d3dUtility.h"namespace d3d {	bool InitD3D( HINSTANCE hInstance, int width, int height, bool windowed, D3DDEVTYPE deviceType, IDirect3DDevice9 **device) {
HWND hwnd; //窗口句柄 WNDCLASS wndclass; //窗口类别,在CreateWindow之前需要RegisterClass , 针对WNDCLASS的参数可以了解一下API wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = (WNDPROC)d3d::WndProc; //WndProc wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = NULL ; wndclass.lpszClassName = _T("Direct3D9App"); if( !RegisterClass(&wndclass) ) { MessageBox(0, _T("This program requires windows NT!"), 0, 0); return false; } hwnd = CreateWindow(_T("Direct3D9App")/*0*/,_T("Direct3D9App")/*0*/,WS_EX_TOPMOST/*WS_OVERLAPPEDWINDOW*/,0,0,width,height,0,0,hInstance,0); ::ShowWindow(hwnd,SW_SHOW/*0*/); ::UpdateWindow(hwnd); //完成了主窗口初始化的过程,以下部分实现Direct3D的初始化过程,并且设置IDirect3DDevice9指针 IDirect3D9 *_d3d9; _d3d9 = Direct3DCreate9(D3D_SDK_VERSION); //获取IDirect3D9的指针,进行设备的迭代,检测特性&获取IDirect3DDevice9指针准备 if( !_d3d9 ) { ::MessageBox(0, _T("Direct3DCreate9() - FAILED"), 0, 0); return false; } D3DCAPS9 caps; //检测图形设备的支持的特性 _d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps); int vp = 0; //是否支持硬件顶点运算 if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) { vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; } else { vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; } D3DPRESENT_PARAMETERS d3dpp; //D3DPRESENT_PARAMETERS设置,设置IDirect3DDevice的特性 ::ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS)); 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; HRESULT hr = _d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, vp, &d3dpp, device); if( FAILED(hr) ) { ::MessageBox(0, _T("CreateDevice() - Failed"), 0, 0); return false; } return true; } int 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 currTime = (float)timeGetTime(); float timeDelta = (currTime - lastTime)*0.001f; ptr_display(timeDelta); lastTime = currTime; } } return msg.wParam; } LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch( msg ) { case WM_DESTROY: ::PostQuitMessage(0); break; case WM_KEYDOWN: if(wParam == VK_ESCAPE) //esc退出主窗口程序 ::DestroyWindow(hwnd); break; } return ::DefWindowProc(hwnd, msg, wParam, lParam); }}

commonFunc.h

此书中的3个例程函数:

Setup:设置和初始化部分在此函数中进行,如分配资源,检查设备性能,设置应用程序状态。

Cleanup:释放Setup函数中分配的任何资源,如分配的存储单元。

Display:实现全部的绘制代码以及相邻帧之间应该执行的操作,如更新物体的位置。参数timeDelta为相邻帧的时间差,主要用于将动画与显示器的刷新频率保持同步。

后续的章节的实现部分集中在这3个函数中,其他部分的代码设计到Direct3D的初始化和Windows程序设计的基本概念,在其他章节中改动很少。

#ifndef COMMONFUNC_H#define COMMONFUNC_H#include "d3dUtility.h"IDirect3DDevice9  *Device = 0;bool windowed = true;bool Setup() {	return true;}void Cleanup() {	}bool Display(float timeDelta) {	if( Device ) {		Device->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);		Device->Present(0, 0, 0, 0);	}	return true;} #endif

Entry.cpp

window程序设计的入口,WinMain函数部分。

#include "d3dUtility.h"#include "commonFunc.h"int WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd ) {	if( !d3d::InitD3D(hInstance, 800, 600, true, D3DDEVTYPE_HAL, &Device )) {		::MessageBox(0,_T("InitD3D() - Failed"), 0, 0 );		return 0;	}	if( !Setup() ) {		::MessageBox(0,_T("Setup() - Failed"), 0, 0 );		return 0;	}		d3d::EnterMsgLoop( Display );	Cleanup();	Device->Release();	return 0;}

 

程序运行效果截图:

转载地址:http://arlya.baihongyu.com/

你可能感兴趣的文章
焊盘 往同一个方向增加 固定的长度方法 总结
查看>>
eclipse的maven、Scala环境搭建
查看>>
架构师之路(一)- 什么是软件架构
查看>>
jquery的冒泡和默认行为
查看>>
USACO 土地购买
查看>>
【原创】远景能源面试--一面
查看>>
B1010.一元多项式求导(25)
查看>>
10、程序员和编译器之间的关系
查看>>
前端学习之正则表达式
查看>>
配置 RAILS FOR JRUBY1.7.4
查看>>
AndroidStudio中导入SlidingMenu报错解决方案
查看>>
修改GRUB2背景图片
查看>>
Ajax异步
查看>>
好记性不如烂笔杆-android学习笔记<十六> switcher和gallery
查看>>
JAVA GC
查看>>
3springboot:springboot配置文件(外部配置加载顺序、自动配置原理,@Conditional)
查看>>
9、Dubbo-配置(4)
查看>>
前端第七天
查看>>
图解SSH原理及两种登录方法
查看>>
[转载] 七龙珠第一部——第058话 魔境圣地
查看>>