DirectX入門筆記 00------ 初始化D3D
阿新 • • 發佈:2018-12-17
d3dUtility.h
#include <d3dx9.h> namespace d3d { bool InitD3D( HINSTANCE hInstance, //Application instance int width, int height, //Width and height of Back buffer bool windowed,//Widowed(true) or full screen(false) D3DDEVTYPE devicetype,//HAL/REF/SM IDirect3DDevice9** device);//The created device 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; } } }
Release(); 釋放COM介面並將其設定為NULL
Delete(); 刪除自由堆中的物件並將物件指標設定為NULL
d3dUtility.cpp
InitD3D分了四個步驟初始化D3D
1.建立IDirect3D9物件(此介面用於獲取系統中物理硬體裝置的資訊並建立介面IDirect3DDevice9).
//Initial D3D //Step 1:Create the IDirect3D9 object IDirect3D9* d3d9; D3DDISPLAYMODE DisplayMode; d3d9 = Direct3DCreate9(D3D_SDK_VERSION); //return NULL if fails //Get the desktop display mode if (FAILED(d3d9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &DisplayMode))) return false; if (!d3d9) { ::MessageBox(0, TEXT("Direct3DCreat9 - Failed"), 0, 0); return false; }
2.檢查硬體加速的支援, 指定使用IDirect3DDevice9物件進行頂點運算的型別.
//Step 2: Check D3DCREATE_HARDWARE_VERTEXPROCESSING D3DCAPS9 caps;//struct d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT,//ADPTER:Denotes primary display adapter DeviceType,//Specifies the device type (Usually D3DDEVTYPE_HAL) &caps); //Capabilities of the primary display adapter //can we use hardware vertex processing? int vp = 0; //D3DDEVCAPS_HWTRANSFORMANDLIGHT /* Device can support transformation and lighting in hardware and DRAWPRIMITIVES2EX must be also */ if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) { //#define D3DCREATE_SOFTWARE_VERTEXPROCESSING 0x00000020L //#define D3DCREATE_HARDWARE_VERTEXPROCESSING 0x00000040L vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; } else { vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; }
3.填充D3DPRESENT_PARAMTETER結構體, 以此指定所要建立的IDirect3DDevice9型別物件的一些特性
//Step3: Fill up structure D3DPRESETNT_PARAMETER
D3DPRESENT_PARAMETERS d3dpp;
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;//pixel format
d3dpp.BackBufferCount = 1;//Number of the back buffer
d3dpp.Windowed = windowed;
d3dpp.SwapEffect//Enum: Page Flipping way of the Swap Chain
= D3DSWAPEFFECT_DISCARD;//The most effective way
d3dpp.hDeviceWindow = hwnd;//Handle of the window that need to draw
d3dpp.EnableAutoDepthStencil = true;//Create and maintain Z-Buffer and Stencil Buffer automatically
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;//depth format
d3dpp.Flags //D3DPRESENTFLAG / 0(No Flag)
= 0; //D3DPRESENTFLAG_LOCKABLE_BACKBUFFER D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval //present rate
= D3DPRESENT_INTERVAL_IMMEDIATE; //D3DPRESENT_INTERVAL_DEFAULT
//MultiSample Type
D3DMULTISAMPLE_TYPE multiType = D3DMULTISAMPLE_NONE;//Default MultiType: NONE
if (d3d9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, DeviceType,
DisplayMode.Format,
windowed, D3DMULTISAMPLE_4_SAMPLES, NULL) == D3D_OK) //HResult:D3D_OK = S_OK/S_FALSE
{
multiType = D3DMULTISAMPLE_4_SAMPLES;
}
d3dpp.MultiSampleType = multiType;
d3dpp.MultiSampleQuality = 0;
4.建立IDirect3DDevice9介面, 初始化完成
HRESULT 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(); // done with d3d9 object
::MessageBox(0, TEXT("CreateDevice() - FAILED"), 0, 0);
return false;
}
}
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);//call display function
LastTime = CurrTime;
}
}
return msg.wParam;
}
接收一個指向顯示函式的函式指標, 顯示函式就是實現繪製功能的那個函式.
d3dInitialize.cpp
#include "d3dUtility.h"
IDirect3DDevice9* Device = 0;
bool Setup() {
//Nothing to set up in the sample
return true;
}
void Cleanup() {
//Nothing to clean up in the sample
}
bool Display(float TimeDelta) {
if (Device) {
// Instruct the device to set each pixel on the back buffer black -
// D3DCLEAR_TARGET: 0x00000000 (black) - and to set each pixel on
// the depth buffer to a value of 1.0 - D3DCLEAR_ZBUFFER: 1.0f.
Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.f, 0);
// Swap the back and front buffers.
Device->Present(0, 0, 0, 0);
}
return true;
}
//WndProC
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);
}
return ::DefWindowProc(hwnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hinstance,
HINSTANCE prevInstance,
PSTR cmdLine,
int showCmd)
{
if (!d3d::InitD3D(hinstance, 890, 540, true, D3DDEVTYPE_HAL, &Device)) {
::MessageBox(0, TEXT("InitD3D() - FAILED"), 0, 0);
return 0;
}
if (!Setup()) {
::MessageBox(0, TEXT("Setup - FAILED"), 0, 0);
return 0;
}
d3d::EnterMsgLoop(Display);
Cleanup();
Device->Release();
return 0;
}
初始化完成後繪製好的黑色視窗: