最近学习了下DirectX9.0,让我对这个图形库有了一定的了解。
首先说下DirectX的背景吧,它是Microsoft公司的员工所编写的一个多媒体应用编程接口(Application Program Interface)API,由C++语言进行编写,主要应用在游戏开发,它可以通过和底层的硬件进行交互,从而获得硬件的支持,从而能让软件发挥出最大的性能。
当然关于多媒体应用编程接口,与DirectX势均力敌的还有一个家伙——OpenGL(Open Graphics Library),这家伙是个与硬件无关的软件接口,也可以说这家伙就是一个比较高级的图形库,不过相比Directx可以跨平台,移植性很好。
开始介绍下我所认知的Directx 组成:
1、DirectGraphics:
DirectGraphicsD3D的API(Application Program Interface),主要负责图形的绘制,以及一些渲染。
2、DirectInput:
DirectInput API,可以直接使用所有与计算机所关联的输入设备,比如经常使用的键盘,鼠标,手柄等等。
3、DirectPlay:
这个小家伙可以让咱们写出的应用程序对机器进行网络功能的设置,便可以通过网络连接可以与其他玩家进行交互。
4、DirectMusic与DirectSound:
正如名字所述,DirectMusic这家伙主要负责一些声音的处理,不过它还有一个兄弟(DirectSound)也可以对声音进行处理,DirectMusic可以提供更多的底层控制与更多的灵活性,而且更加方便,但是它的兄弟DirectSound就没它这么有特点了,能做的工作也没DirectMusic多。这就好比编程语言里面的 机器语言——>汇编语言——>高级语言,越高级与人之间的交互性越强,灵活性就越差,反之也是一样。
开始写窗口:
一、首先到微软官网下进行下载Directx SDK(Soft Development Kit)
二、进行安装。
三、安装完毕之后,进行环境的配置:
就如我来说,我所使用的编译器是VS2015,首先打开VS,建立Win32项目:
点击确定,然后点击下一步,不过一定要选择空项目,Win32给的那些,我们没必要会全部运用到。
进行Direct SDK库文件的导入了:
如果不想手动写一些库文件的链接,也可进行导入:
开始编写CODE:
在有文件和源文件处进行添加新建项,快捷键(Ctrl+Alt+A)
头文件中代码:
#include <d3d9.h> //包含D3D基本函数 #include <d3dx9.h> //包含D3D扩展函数,功能更为强大
//如果刚才添加了依赖项,便可不再写此段连接库文件代码
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"winmm.lib") //用于多媒体的库文件连接,这相比Direct所提供的存在一定的局限性
namespace d3d { bool InitD3D( HINSTANCE hInstance, //应用程序实例 int width, int height, //后背缓冲区尺寸 bool windowed, //显示窗口还是全屏化 D3DDEVTYPE deviceType, //HAL(硬件抽象层)OR REF(软件光栅化) IDirect3DDevice9 ** device); //创建设备接口device
bool InitD3D( HINSTANCE hInstance, //应用程序实例 int width, int height, //后背缓冲区尺寸 bool windowed, //显示窗口还是全屏化 D3DDEVTYPE deviceType, //HAL(硬件抽象层)OR REF(软件光栅化) IDirect3DDevice9 ** device); //创建设备接口deviceint EnterMsgLoop(bool(*ptr_display)(float timeDelta));
int EnterMsgLoop(bool(*ptr_display)(float timeDelta));LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); //WPARAM和LPARAM是消息响应机制
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); //WPARAM和LPARAM是消息响应机制template<class T>void Release(T t) //进行将某些接口进行释放(主要是COM接口对象)
{ if (t) { t->Release(); t = 0; } }
{ if (t) { t->Release(); t = 0; } }template<class T>void Delete(T t) //删除堆中的自有空闲对象 { if (t) { delete t; t = 0; } } }
template<class T>void Delete(T t) //删除堆中的自有空闲对象 { if (t) { delete t; t = 0; } } }//重头戏,cpp源文件
#include "start.h" //刚才所写的头文件
IDirect3DDevice9 *Device=0; //创建一个设备指针
const int width=640;
const int height=480;
#define WINDOW_TITLE L"For Dream"
//主体框架
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;
if( Device ) { Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0); Device->Present(0, 0, 0, 0); } return true;}
//开始对前面的命名空间的函数进行定义:
//d3d9开始初始化
bool d3d::InitD3D(HINSTANCE hInstance, int width, int height, bool windowed,D3DDEVTYPE deviceType, IDirect3DDevice9** device) { //1.创建窗口样式 WNDCLASSEX wc = { 0 }; wc.style = CS_VREDRAW | CS_HREDRAW; wc.cbSize = sizeof(WNDCLASSEX); wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.lpfnWndProc =d3d::WndProc; wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.hIcon = (HICON)::LoadImage(NULL, L"icon.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE); wc.hIconSm= (HICON)::LoadImage(NULL, L"icon.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE); wc.hCursor= (HICON)::LoadImage(NULL, L"cursor.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE); wc.lpszMenuName = NULL; wc.lpszClassName = WINDOW_TITLE; //2.注册窗口类 if (!RegisterClassEx(&wc)) { ::MessageBox(NULL, L"Register Error", L"News", NULL); return false; }
//1.创建窗口样式 WNDCLASSEX wc = { 0 }; wc.style = CS_VREDRAW | CS_HREDRAW; wc.cbSize = sizeof(WNDCLASSEX); wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.lpfnWndProc =d3d::WndProc; wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.hIcon = (HICON)::LoadImage(NULL, L"icon.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE); wc.hIconSm= (HICON)::LoadImage(NULL, L"icon.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE); wc.hCursor= (HICON)::LoadImage(NULL, L"cursor.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE); wc.lpszMenuName = NULL; wc.lpszClassName = WINDOW_TITLE; //2.注册窗口类 if (!RegisterClassEx(&wc)) { ::MessageBox(NULL, L"Register Error", L"News", NULL); return false; }//3.创建窗口
//3.创建窗口HWND hwnd=0;
HWND hwnd=0;hwnd=::CreateWindow(wc.lpszClassName, wc.lpszClassName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, NULL, NULL, hInstance, NULL);
hwnd=::CreateWindow(wc.lpszClassName, wc.lpszClassName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, NULL, NULL, hInstance, NULL);if (!hwnd) { ::MessageBox(NULL, L"Create Window Error", L"News", NULL); return false; }
if (!hwnd) { ::MessageBox(NULL, L"Create Window Error", L"News", NULL); return false; }//利用媒体库函数进行音乐的播放: PlaySound(L"水.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP); //循环播放
PlaySound(L"水.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP); //循环播放//4.显示窗口
//4.显示窗口::ShowWindow(hwnd, SW_SHOW);
//5.更新窗口
//5.更新窗口::UpdateWindow(hwnd);
::UpdateWindow(hwnd);
//初始化D3D
//初始化D3DHRESULT hr = 0; IDirect3D9* d3d9 = 0; //创建D3D对象
IDirect3D9* d3d9 = 0; //创建D3D对象d3d9 = Direct3DCreate9(D3D_SDK_VERSION); if (!d3d9) { ::MessageBox(NULL, L"Create Direct Object Error", L"News", NULL); return false; }
if (!d3d9) { ::MessageBox(NULL, L"Create Direct Object Error", L"News", NULL); return false; }
//选择相应的设备
//选择相应的设备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; //硬件不支持,软件进行模拟运算 }
d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps); int vp = 0; if (caps.DevCaps&D3DDEVCAPS_HWTRANSFORMANDLIGHT) { vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; //硬件支持,且进行运算 } else { vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; //硬件不支持,软件进行模拟运算 }//填充D3D设备类型对象的一些特性
//填充D3D设备类型对象的一些特性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;
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;//创建设备,如果创建失败,那就再来一次
//创建设备,如果创建失败,那就再来一次hr = d3d9->CreateDevice( D3DADAPTER_DEFAULT, deviceType, hwnd, vp, &d3dpp, device); if (FAILED(hr)) { // try again using a 16-bit depth buffer d3dpp.AutoDepthStencilFormat = D3DFMT_D16; hr = d3d9->CreateDevice( D3DADAPTER_DEFAULT, deviceType, hwnd, vp, &d3dpp, device); if (FAILED(hr)) { d3d9->Release(); ::MessageBox(0, L"CreateDevice() FAILED", 0, 0); return false; } }
D3DADAPTER_DEFAULT, deviceType, hwnd, vp, &d3dpp, device); if (FAILED(hr)) { // try again using a 16-bit depth buffer d3dpp.AutoDepthStencilFormat = D3DFMT_D16; hr = d3d9->CreateDevice( D3DADAPTER_DEFAULT, deviceType, hwnd, vp, &d3dpp, device); if (FAILED(hr)) { d3d9->Release(); ::MessageBox(0, L"CreateDevice() FAILED", 0, 0); return false; } }d3d9->Release(); return true;
d3d9->Release(); 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 currTime = (float)timeGetTime(); float timeDelta = (currTime - lastTime)*0.001f; ptr_display(timeDelta); lastTime = currTime; } } return msg.wParam; }
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 d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch( msg ) { case WM_DESTROY: ::PostQuitMessage(0); break; case WM_KEYDOWN: if( wParam == VK_ESCAPE ) ::DestroyWindow(hwnd); break; } return ::DefWindowProc(hwnd, msg, wParam, lParam); }
switch( msg ) { case WM_DESTROY: ::PostQuitMessage(0); break; case WM_KEYDOWN: if( wParam == VK_ESCAPE ) ::DestroyWindow(hwnd); break; } return ::DefWindowProc(hwnd, msg, wParam, lParam); }int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd) { if(!d3d::InitD3D(hinstance, 640, 480, true, D3DDEVTYPE_HAL, &Device)) { ::MessageBox(0, L"InitD3D() - FAILED", 0, 0); return 0; } if(!Setup()) { ::MessageBox(0, L"Setup() - FAILED", 0, 0); return 0; } d3d::EnterMsgLoop( Display ); Cleanup(); Device->Release(); return 0; }
HINSTANCE prevInstance, PSTR cmdLine, int showCmd) { if(!d3d::InitD3D(hinstance, 640, 480, true, D3DDEVTYPE_HAL, &Device)) { ::MessageBox(0, L"InitD3D() - FAILED", 0, 0); return 0; } if(!Setup()) { ::MessageBox(0, L"Setup() - FAILED", 0, 0); return 0; } d3d::EnterMsgLoop( Display ); Cleanup(); Device->Release(); return 0; }
最后的运行结果:
代码下载:http://download.csdn.net/detail/qq_33248019/9841038点击打开链接