Initializing Direct3D
Next in line for the helper functions is init_d3d,
which you use to initialize Direct3D and create a 3D device and display window. I tried to keep the code as simple as possible, performing
the typical initialization code you would use in any Direct3D application.
HRESULT init_d3d(IDirect3D9** ret_d3d,
IDirect3DDevice9** ret_device,
HWND hwnd,
BOOL force_windowed,
bool multi_threaded)
{
// error checking
if(ret_d3d == NULL || ret_device == NULL || hwnd == NULL)
return E_FAIL;
IDirect3D9* d3d = Direct3DCreate9(D3D_SDK_VERSION);
if(d3d == NULL)
return E_FAIL;
*ret_d3d = d3d;
// Ask if user wants to run windowed or fullscreen, or force windowed if flagged to do such.
int mode;
if(force_windowed)
mode = IDNO;
else
mode = MessageBox(hwnd, "Use fullscreen mode? (640x480x16)", "Initialize D3D", MB_YESNO | MB_ICONQUESTION);
// set the video (depending on windowed mode or fullscreen)
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
// setup video setttings based on choice of fullscreen or not
if(mode == IDYES) // setup fullscreen format (set to your own if you perfer)
{
// set the presentation parameters (use fullscreen)
d3dpp.BackBufferWidth = 640;
d3dpp.BackBufferHeight = 480;
d3dpp.BackBufferFormat = D3DFMT_R5G6B5;
d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;
d3dpp.Windowed = FALSE;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
}
else // setup windowed format (set to your own demensions below)
{
// get the client and window dimensions
RECT client_rect, window_rect;
GetClientRect(hwnd, &client_rect);
GetWindowRect(hwnd, &window_rect);
// set the width and height (set your dimensions here)
DWORD desired_width = 640, desired_height = 480;
DWORD width = (window_rect.right - window_rect.left) - client_rect.right + desired_width;
DWORD height = (window_rect.bottom - window_rect.top) - client_rect.bottom + desired_height;
// set the window's dimensions
MoveWindow(hwnd, window_rect.left, window_rect.top, width, height, TRUE);
// get the desktop format
D3DDISPLAYMODE display_mode;
d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &display_mode);
// set the presentation parameters (use windowed)
d3dpp.BackBufferWidth = desired_width;
d3dpp.BackBufferHeight = desired_height;
d3dpp.BackBufferFormat = display_mode.Format;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.Windowed = TRUE;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
}
// create the 3D device
DWORD flags = D3DCREATE_MIXED_VERTEXPROCESSING;
if(multi_threaded)
flags |= D3DCREATE_MULTITHREADED;
IDirect3DDevice9* device;
HRESULT hr = d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, flags, &d3dpp, &device);
if(FAILED(hr))
return hr;
// store the 3D device object pointer
*ret_device = device;
// set the perspective projection
float aspect = (float)d3dpp.BackBufferWidth / d3dpp.BackBufferHeight;
D3DXMATRIX mat_proj;
D3DXMatrixPerspectiveFovLH(&mat_proj, D3DX_PI/4.0f, aspect, 1.0f, 10000.0f);
device->SetTransform(D3DTS_PROJECTION, &mat_proj);
// set the default render states
device->SetRenderState(D3DRS_LIGHTING, FALSE);
device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
// set the default texture stage states
device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
// set the default texture filters
device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
return S_OK;
}