Initializing DirectX

Published April 17, 2012
Advertisement
Now that we have created our window, we need to give it DirectX Capabilities, Again, since we will want to create only one instance of this class for each application we will create it as singleton. Even though on running the application we will just see a background color (TAN), we will have our DirectX device initialized and up for running. We will be able to Alt-Tab out of our full screen app or toggle between full screen and windowed mode

[subheading]Setting Up the Project[/subheading]
The DXSDK installation defines the DXSDK_DIR environment variable which can be used to include all the directX files into our project.
for all configurations
In the Project Properties -> C/C++ -> Additional Include Directories add $(DXSDK_DIR)\Include (apart from all the include files) (for all configurations)
In the Project Properties -> Linker -> Additional Library Directories add ..\..\bin\;"$(DXSDK_DIR)\Lib\x86"
Debug Mode
In the Project Properties -> Linker -> Input-> Additional Dependencies add d3dx9d.lib DxErr.lib d3d9.lib winmm.lib dinput8.lib dxguid.lib
Release Mode
In the Project Properties -> Linker -> Input-> Additional Dependencies add d3dx9.lib DxErr.lib d3d9.lib dinput8.lib dxguid.lib winmm.lib

[subheading]IDXBase Interface : DxBase.hxx[/subheading]
Since we dont need to expose all the functions to the rest of the world, we will just include a small subset in the interface. We will come to the purpose of each function in just a bit.
[spoiler]

namespace Graphics
{
class IDXBase
: public Base::cNonCopyable
{
public:
virtual ~IDXBase(){}
virtual void VOnInitialization(const HWND hWnd, const D3DCOLOR & bkColor, const bool bFullScreen, const int iWidth, const int iHeight) = 0;
virtual HRESULT VOnResetDevice() = 0;
virtual HRESULT VBeginRender() = 0;
virtual void VEndRender(const HRESULT hr) = 0;
virtual HRESULT VIsAvailable() const = 0;
virtual void VOnDestroy() = 0;
virtual LPDIRECT3DDEVICE9 VGetDevice() const = 0;
virtual void VToggleFullScreen() = 0;

GRAPHIC_API static IDXBase * GetInstance();
};
}

[/spoiler]

[subheading]cDxBase Class : DxBase.h[/subheading]
The cDxBase class handles the creation of the directX device
[spoiler]

namespace Graphics
{
class cDXBase
: public IDXBase
{
public:
static cDXBase * Create();
private:
cDXBase() ;
~cDXBase() ;
void VOnInitialization(const HWND hWnd, const D3DCOLOR& bkColor, const bool bFullScreen, const int iWidth, const int iHeight);
HRESULT VOnResetDevice() ;
HRESULT VBeginRender();
void VEndRender(const HRESULT hr);
LPDIRECT3DDEVICE9 VGetDevice() const;
HRESULT VIsAvailable() const;
void VOnDestroy();
void VToggleFullScreen();
void DirectxInit() ;
void CreateDirectxDevice() ;
void SetParameters();
void Cleanup() ;

private:
LPDIRECT3D9 m_pD3D ;
LPDIRECT3DDEVICE9 m_pd3dDevice ;
D3DCAPS9 m_Caps ;
D3DCOLOR m_BkColor ;
HWND m_Hwnd ;
D3DPRESENT_PARAMETERS m_d3dpp ;
int m_iWidth;
int m_iHeight ;
D3DDISPLAYMODE m_displayMode;
bool m_bFullScreen;
};
static cDXBase * s_pDXBase= NULL;
}

[/spoiler]

[subheading]Implementation : DxBase.cpp[/subheading]
Constructor
[spoiler]

cDXBase::cDXBase()
: m_pD3D(NULL)
, m_pd3dDevice(NULL)
, m_Hwnd(NULL)
, m_BkColor(BLACK)
, m_bFullScreen(false)
, m_iWidth(0)
, m_iHeight(0)
{
}

[/spoiler]
Destructor - Make sure the directX object and device are released
[spoiler]

cDXBase::~cDXBase()
{
Cleanup();
}

[/spoiler]
method Create - Creates an object of this class and returns it
[spoiler]

cDXBase* cDXBase::Create()
{
return(DEBUG_NEW cDXBase());
}

[/spoiler]
method VOnInitialization - This is the first function that needs to be called since it is responsible for creating the directX object and device
[spoiler]

void cDXBase::VOnInitialization( const HWND hWnd, const D3DCOLOR& bkColor, const bool bFullScreen, const int iWidth, const int iHeight)
{
m_Hwnd = hWnd;
m_BkColor = bkColor;
m_bFullScreen = bFullScreen;
m_iHeight = iHeight;
m_iWidth = iWidth;

// Initialize DirectX
DirectxInit() ;

// Fill out presentation parameters
SetParameters() ;

CreateDirectxDevice() ;
}

[/spoiler]
method VOnResetDevice - Resets the device
[spoiler]

HRESULT cDXBase::VOnResetDevice()
{
if (m_pd3dDevice)
{
HRESULT hr ;

hr = m_pd3dDevice->Reset(&m_d3dpp) ;
return hr ;
}
return 0;
}

[/spoiler]
method VBeginRender- This function clears the surface with the specified color and prepares it for rendering. This function must always be called before we render any geometry.
[spoiler]

HRESULT cDXBase::VBeginRender()
{
HRESULT hr;

// clear the frame with the specified color
m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, m_BkColor, 1.0f, 0) ;

hr = m_pd3dDevice->BeginScene() ;

return hr;
}

[/spoiler]
method VEndRender- This function displays what we just rendered to the screen .This function must always be called after we are done rendering
[spoiler]

void cDXBase::VEndRender( const HRESULT hr )
{
if(SUCCEEDED(hr))
{
m_pd3dDevice->EndScene() ;
}
// Present/Display the contents
m_pd3dDevice->Present(NULL, NULL, NULL, NULL) ;
}

[/spoiler]
method VGetDevice
[spoiler]

LPDIRECT3DDEVICE9 cDXBase::VGetDevice() const
{
return m_pd3dDevice;
}
[/spoiler]
method VIsAvailable - This function checks whether the device is available for rendering or not. We need to call this function before we begin rendering
[spoiler]

HRESULT cDXBase::VIsAvailable() const
{
return(m_pd3dDevice->TestCooperativeLevel()) ;
}
[/spoiler]
method VOnDestroy- Releases the DirectX object and deletes the singleton object
[spoiler]

void cDXBase::VOnDestroy()
{
Cleanup();
delete this;
s_pDXBase = NULL;
}
[/spoiler]
method VToggleFullScreen - Toggles between full screen and windowed mode
[spoiler]

void cDXBase::VToggleFullScreen()
{
m_bFullScreen = !m_bFullScreen;
SetParameters();
}
[/spoiler]
method DirectxInit- This function creates the Direct3D object. After creating the object, we get the system's current display mode by calling GetAdapterDisplayMode which will be used when we create a fullscreen device. Then we check what the video card is capable of by calling GetDeviceCaps.
[spoiler]

void cDXBase::DirectxInit()
{
//create the Direct3d Object
m_pD3D = Direct3DCreate9(D3D_SDK_VERSION) ;

if(m_pD3D == NULL)
{
\\ error
PostQuitMessage(0);
}

// get the display mode
m_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &m_displayMode );

// get the device caps
m_pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &m_Caps) ;
}
[/spoiler]
method CreateDirectxDevice - This function check if the hardware supports transformation and lighting and whether it supports a pure device. In the end, we create the directX device based on the parameters that we have filled and the hardware capabilities.
[spoiler]

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 ;

// Check for pure device
if ( m_Caps.DevCaps & D3DDEVCAPS_PUREDEVICE )
{
vp |= D3DCREATE_PUREDEVICE;
}
}
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)))
{
\\ error
PostQuitMessage(0) ;
}
}
[/spoiler]
method SetParameters - This function fills out the D3DPRESENT_PARAMETERS structures depending on whether it is a full screen or windowed application. We also check which depth stencil format is supported by calling CheckDeviceFormat
[spoiler]

void cDXBase::SetParameters()
{
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.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE ;
m_d3dpp.EnableAutoDepthStencil = true ;
m_d3dpp.Windowed = !m_bFullScreen;

if(m_bFullScreen)
{
m_d3dpp.BackBufferWidth = m_iWidth;
m_d3dpp.BackBufferHeight = m_iHeight;
m_d3dpp.FullScreen_RefreshRateInHz = m_displayMode.RefreshRate;
m_d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; //pixel format
}
else
{
m_d3dpp.BackBufferWidth = 0;
m_d3dpp.BackBufferHeight = 0;
m_d3dpp.FullScreen_RefreshRateInHz = 0 ;
m_d3dpp.BackBufferFormat = m_displayMode.Format;
}

if (SUCCEEDED(m_pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_d3dpp.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8)))
{
m_d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
}
else if (SUCCEEDED(m_pD3D->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_d3dpp.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8)))
{
m_d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
}
else if (SUCCEEDED(m_pD3D->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_d3dpp.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16)))
{
m_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
}
else
{
// error
}
}

[/spoiler]
method Cleanup - This function releases the directx device and object. SafeRelease is a special macro which releases the object if it not released
[spoiler]

void cDXBase::Cleanup()
{
// release the Direct3d device
SAFE_RELEASE(m_pd3dDevice) ;

// release the Direct3d object
SAFE_RELEASE(m_pD3D) ;
}

[/spoiler]

[subheading]Running the code[/subheading]
The code needs to be added in the following functions
MainWindow.cpp
[spoiler]


void cMainWindow::OnWindowCreated()
//Bring the window into the foreground and activates the window
SetForegroundWindow(m_Hwnd);

//Set the keyboard focus
SetFocus(m_Hwnd);

// initialize DirectX
IDXBase::GetInstance()->VOnInitialization(m_Hwnd, TAN, m_bFullScreen, m_iFullScreenWidth, m_iFullScreenHeight);
}

void cMainWindow::OnWindowDestroyed()
{
// return to the default mode
ChangeDisplaySettings(NULL, 0);

// release the graphic object
IDXBase::GetInstance()->VOnDestroy();

ReleaseCapture() ;
PostQuitMessage(0) ;
}

void cMainWindow::VToggleFullScreen()
{
.. // previous code here

if (m_bFullScreen)
{
.. // previous code here
}
else
{
.. // previous code here
}

IDXBase::GetInstance()->VToggleFullScreen();
IDXBase::GetInstance()->VOnResetDevice();

if (!IsWindowVisible(m_Hwnd))
{
ShowWindow(m_Hwnd, SW_SHOW);
}
}

[/spoiler]

WinMain
[spoiler]

int WINAPI WinMain(const HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
.. // previous code
else
{
//No message to process?
// Then do your game stuff here
HRESULT hr = IDXBase::GetInstance()->VIsAvailable() ;

if(hr == D3DERR_DEVICELOST || hr == D3DERR_DEVICENOTRESET)
{
if(hr == D3DERR_DEVICELOST)
{
Sleep(50);
}
else
{
if(hr == D3DERR_DEVICENOTRESET)
{
hr = IDXBase::GetInstance()->VOnResetDevice() ;
}
}
}
if(SUCCEEDED(hr))
{
hr = IDXBase::GetInstance()->VBeginRender();
}
if (SUCCEEDED(hr))
{
// render your stuff here
IDXBase::GetInstance()->VEndRender(hr);
}
}
..// destroy code
}

[/spoiler]
0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement