【笔记】《DirectX 9.0 3D游戏开发编程基础》:Direct3D初始化
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 <d3dx9.h>
#include <windows.h>
#include <tchar.h> 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<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;
}
}
} #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;
}
程序运行效果截图:
【笔记】《DirectX 9.0 3D游戏开发编程基础》:Direct3D初始化的更多相关文章
- 《DirectX 9.0 3D游戏开发编程基础》必备的数学知识 读书笔记
最近在看游戏导航源码,但是看了几天感觉看不懂.里面全是一些几何运算,以及一些关于3d方面的知识.发现自己缺少3d这方面的知识,正好也想研究一下3d游戏开发的基本原理,于是决定买本书看看了,后来在ope ...
- 《DirectX 9.0 3D游戏开发编程基础》 第二章 绘制流水线 读书笔记
模型的表示 场景:物品或模型的集合 任何物品都可以用三角形网络逼近表示.我们经常用以下术语描述三角形网络:多边形(polygons).图元(primitives).网络几何单元(mesh geomet ...
- 《DirectX 9.0 3D游戏开发编程基础》 第一章 初始化Direct3D 读书笔记
REF设备 参考光栅设备,他能以软件计算方式完全支持Direct3D Api.借助Ref设备,可以在代码中使用那些不为当前硬件所支持的特性,并对这此特性进行测试. D3DDEVTYPE 在程序代码中, ...
- 自己在完第一遍STL和Directx 9.0 游戏开发编程基础书后的体会
如果一本书看一遍就能看懂,说明书对自己相对容易,没有必要在去看第二遍,但是对于大多数书籍,都有自己陌生的知识,看完一遍无法理解的地方,说明就是自己知识点最薄弱的,最需要去理解的地方,一旦自己理解了这些 ...
- Unity 4.2.0 官方最新破解版(Unity3D 最新破解版,3D游戏开发工具和游戏引擎套件)
Unity是一款跨平台的游戏开发工具,从一开始就被设计成易于使用的产品.作为一个完全集成的专业级应用,Unity还包含了价值数百万美元的功能强大的游戏引擎.Unity作为一个游戏开发工具,它的设计主旨 ...
- 转载:[转]如何学好3D游戏引擎编程
[转]如何学好3D游戏引擎编程 Albert 本帖被 gamengines 从 游戏引擎(Game Engine) 此文为转载,但是值得一看. 此篇文章献给那些为了游戏编程不怕困难的热血青年,它的 ...
- DirectX12 3D 游戏开发与实战第八章内容(下)
DirectX12 3D 游戏开发与实战第八章内容(下) 8.9.材质的实现 下面是材质结构体的部分代码: // 简单的结构体来表示我们所演示的材料 struct Material { // 材质唯一 ...
- DirectX12 3D 游戏开发与实战第八章内容(上)
8.光照 学习目标 对光照和材质的交互有基本的了解 了解局部光照和全局光照的区别 探究如何用数学来描述位于物体表面上某一点的"朝向",以此来确定入射光照射到表面的角度 学习如何正确 ...
- DirectX12 3D 游戏开发与实战第五章内容
渲染流水线 学习目标: 了解用于在2D图像中表现出场景立体感和空间深度感等真实效果的关键因素 探索如何用Direct3D表示3D对象 学习如何建立虚拟摄像机 理解渲染流水线,根据给定的3D场景的几何描 ...
随机推荐
- MongoDB中的高级查询(二)
$mod取模运算 查询index对5取模运算等于1的数据. $not $not是元条件句,即可以用在任何其他条件之上.查询index对5取模运算不等于1的数据. $exists判断字段是否存在 查询出 ...
- 如何引用jQuery实现下拉列表,点击展开,点击关闭。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- .net中对象序列化技术浅谈
.net中对象序列化技术浅谈 2009-03-11 阅读2756评论2 序列化是将对象状态转换为可保持或传输的格式的过程.与序列化相对的是反序列化,它将流转换为对象.这两个过程结合起来,可以轻松地存储 ...
- paip.最省内存的浏览器评测 cah
paip.最省内存的浏览器评测 cah 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn.net/at ...
- paip.导入数据英文音标到数据库mysql为空的问题之道解决原理
paip.导入数据英文音标到数据库mysql为空的问题之道解决原理 #---原因:mysql 导入工具的bug #---解决:使用双引号不个音标括起来. 作者 老哇的爪子 Attilax 艾龙, E ...
- paip.提升性能----硬盘不同转速不同缓存对比转
paip.提升性能----硬盘不同转速不同缓存对比转 西数 WDC WD2500BEVT-08A23T1 ( 250 GB / 5400 转/分 ) 5400转 8M缓存 单碟250 GB ...
- Git 操作 学习资源 网址
用git 有一段时间了,有点自己的小心得.个人觉得相对SVN来讲他更灵活,更合理. 陆陆续续的收集了一些学习资源: 1.理解Xcode 中的Git 版本控制 http://www.open-open. ...
- Leetcode-462 Minimum Moves to Equal Array Elements II
#462. Minimum Moves to Equal Array Elements II Given a non-empty integer array, find the minimum n ...
- 提高D3js力导向图加载速度(转)
过去一段时间曾两次使用了 D3 力导向图来描绘族群关系. http://bl.ocks.org/mbostock/1062288 第一次用的时候不求甚解,交差了事.当时点也不多,很顺利完成了任务.这一 ...
- Revit2013工具栏工具无法显示BUG
该BUG在Revit2013版中存在,主要症状就是当你激活某些工具的时候,上部工具栏中本应该显示的上下文工具显示不出来,比如当你选中模型中的风管的时候,正常情况下工具栏应该是这个样子. 但是在Revi ...