After creating the window, we need to give it DirectX capabilities. To get access to DirectX graphics, we need to include the header file d3d9.h. We also need to add the header file d3dx9.h, as it contains a lot of useful functions and macros.
Following the OOP methodology, I created a class which deals with the creation and release of the devices, handling lost devices and the rendering.
// DxBase.cpp
void cDXBase::Init( const HWND hWnd )
{
m_Hwnd = hWnd;
DirectxInit() ;
#ifdef WINDOWED
SetParameters(false) ;
#else
SetParameters(true) ;
#endif
CreateDirectxDevice() ;
}
void cDXBase::DirectxInit()
{
//create the Direct3d Object
m_pD3D = Direct3DCreate9(D3D_SDK_VERSION) ;
if(m_pD3D == NULL)
{
MessageBox(NULL, _T("Direct3d object creation failed!"), _T("Error!"), MB_ICONEXCLAMATION | MB_OK) ;
}
// get the display mode
m_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &m_displayMode );
// get the device caps
m_pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &m_Caps) ;
}
// DxBase.cpp
void cDXBase::SetParameters(const BOOL bFullScreen)
{
ZeroMemory(&m_d3dpp, sizeof(m_d3dpp)) ;
m_d3dpp.BackBufferCount = 1 ;
m_d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE ;
m_d3dpp.MultiSampleQuality = 0 ;
m_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD ;
m_d3dpp.hDeviceWindow = m_Hwnd ;
m_d3dpp.Flags = 0 ;
m_d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT ;
m_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE ;
m_d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8 ; //pixel format
m_d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8 ; // depth format
m_d3dpp.EnableAutoDepthStencil = true ;
if(bFullScreen)
{
// if its a full screen app
m_d3dpp.BackBufferWidth = m_displayMode.Width ;
m_d3dpp.BackBufferHeight = m_displayMode.Height ;
m_d3dpp.Windowed = false; // fullscreen
m_d3dpp.FullScreen_RefreshRateInHz = m_displayMode.RefreshRate;
}
else
{
// if its a windowed app
m_d3dpp.Windowed = true ;
m_d3dpp.EnableAutoDepthStencil = TRUE ;
m_d3dpp.AutoDepthStencilFormat = D3DFMT_D16 ;
}
}
//DxBase.cpp
void cDXBase::CreateDirectxDevice()
{
int vp = 0 ; // the typeof vertex processing
if(m_Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
// hardware vertex processing is supported.
vp = D3DCREATE_HARDWARE_VERTEXPROCESSING ;
}
else
{
// use software vertex processing.
vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING ;
}
// Create the D3DDevice
if(FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
m_Hwnd,
vp,
&m_d3dpp,
&m_pd3dDevice)))
{
MessageBox(NULL, _T("Direct3d m_pd3dDevice creation failed!"), _T("Error!"),MB_ICONEXCLAMATION | MB_OK) ;
PostQuitMessage(0) ;
DestroyWindow(m_Hwnd) ;
}
}
// Dxbase.cpp
HRESULT cDXBase::BeginRender()
{
HRESULT hr;
// check if the device is available
hr = IsAvailable() ;
if(hr == D3DERR_DEVICELOST || hr == D3DERR_DEVICENOTRESET)
{
HandleLostDevice(hr) ;
}
else
{
if(FAILED(hr))
{
PostQuitMessage(0) ;
}
}
if(SUCCEEDED(hr))
{
// clear the frame
m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,m_BkColor, 1.0f, 0) ;
hr = m_pd3dDevice->BeginScene() ;
}
return hr;
}
//DxBase.inl
inline HRESULT cDXBase::IsAvailable()
{
return(m_pd3dDevice->TestCooperativeLevel()) ;
}
inline void cDXBase::EndRender( const HRESULT hr )
{
if(SUCCEEDED(hr))
{
m_pd3dDevice->EndScene() ;
}
m_pd3dDevice->Present(NULL, NULL, NULL, NULL) ;
}
// DxBase.cpp
void cDXBase::Release()
{
// release the Direct3d device
SAFE_RELEASE(m_pd3dDevice) ;
// release the Direct3d object
SAFE_RELEASE(m_pD3D) ;
}
// DxBase.cpp
void cDXBase::HandleLostDevice(HRESULT hr)
{
if(hr == D3DERR_DEVICELOST)
{
Sleep(500) ;
}
else
{
if(hr == D3DERR_DEVICENOTRESET)
{
//The m_pd3dDevice is ready to be Reset
hr = ResetDevice() ;
}
}
}
HRESULT cDXBase::ResetDevice()
{
if (m_pd3dDevice)
{
HRESULT hr ;
hr = m_pd3dDevice->Reset(&m_d3dpp) ;
return hr ;
}
return 0;
}
Now we just need to make a few changes to our MainWindow to integrate DirectX.
// MainWindow.cpp
GRAPHIC_API HWND cMainWindow::Init( const HINSTANCE &hInstance, const int &nCmdShow, LPCTSTR lpWindowTitle,const int iFullScreenWidth, const int iFullScreenHeight, cBaseApp* const pGameApp )
{
// earlier stuff
m_iFullScreenWidth = iFullScreenWidth ;
m_iFullScreenHeight = iFullScreenHeight ;
// earlier stuff
// initialize DirectX
cDXBase::GetInstance().Init(hWnd);
return hWnd;
}
HWND cMainWindow::CreateMyWindow( const int &nCmdShow, LPCTSTR lpWindowTitle )
{
// earlier stuff
#else
// create the window in full screen mode
m_Hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
_T("Window"),
lpWindowTitle,
WS_EX_TOPMOST | WS_POPUP | WS_VISIBLE,
0, 0,
m_iFullScreenWidth,m_iFullScreenHeight,
NULL,
NULL,
m_hInstance,
this) ;
#endif
// earlier stuff
}
LRESULT CALLBACK cMainWindow::WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
// earlier stuff
case WM_SIZE:
case WM_MOVE:
OnReset();
return 0 ;
case WM_KEYDOWN:
switch(wParam)
{
case VK_ESCAPE:
DestroyWindow(hwnd) ;
break ;
}
return 0 ;
// earlier stuff
case WM_DESTROY:
OnDestroy();
return 0 ;
// earlier stuff
}
}
void cMainWindow::Run()
{
// earlier stuff
//No message to process?
// Then do your game stuff here
OnRender();
}
}
}
void cMainWindow::OnRender()
{
HRESULT hr;
hr = cDXBase::GetInstance().BeginRender();
if (SUCCEEDED(hr))
{
cDXBase::GetInstance().EndRender(hr);
}
}
void cMainWindow::OnDestroy()
{
// release the graphic object
cDXBase::GetInstance().Release();
ReleaseCapture() ;
PostQuitMessage(0) ;
}
void cMainWindow::OnReset()
{
GetWinRect() ;
cDXBase::GetInstance().ResetDevice();
}
Code
Binaries
No comments :
Post a Comment