Render DirectX within a window (plus my introduction)

PollWas this helpful?
7 votes
Posts 1–4 of 4 · Page 1 of 1
Render DirectX within a window (plus my introduction)
Hello everyone... I'm oyasuna.dev, but you may call me Oliver or Ollie if you would like to. I am 16, and currently the leader of the programming branch for an upcoming FPS game which is scheduled to be released in around 3 to 4 years. The name has not been set yet, but my signature will give updates to our progress.

Anyway to the point of this thread... I just wanted to release what I think is the most easy and efficient way to Render Direct3D within a windows application. This is made for fullscreen only, but if you have enough knowledge of C++ and Direct3D you should be able to whip something up. Basically I will be guiding anyone who needs help through the steps to initiate DirectX in a window application.

--------------------

If you have not already downloaded the latest version of DirectX SDK then do so. Learn how to include the files into your Microsoft Visual C++ project. Remember that the ability to include files under Tools->Options was deprecated in Microsoft Visual C++ 2008 and was taken out in 2010. In 2010 you will have to either include the header and library files in the project settings or use the User Property Sheet.

In this tutorial I will be using Direct3D 9, because Direct3D 9 was the last version to support XP. Although I have recently upgraded to Windows 7, I still love Direct3D 9, but time to time use some things from 10 and 11.

Now onto the tutorial!

--------------------

Since we are going to make this as simple as possible we will put everything into one cpp file. You may re-organize later.

Includes:
Code:
#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>

#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")
Globals:
We want these to be accessed from anywhere and have the same value
Code:
HWND g_hWnd = NULL; //Window Handle
LPDIRECT3D9 g_pD3D = NULL;
LPDIRECT3DDEVICE9 g_pDevice = NULL; //D3D Device
int xRes = GetSystemMetrics(SM_CXSCREEN); //Screen Resolution Width
int yRes = GetSystemMetrics(SM_CYSCREEN); //Screen Resolution Height
Prototypes:
The point of prototypes to define the function almost like a global so we don't have to create a function before another function that calls the first
Code:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void init(void);
void shutDown(void);
void render(void);
WinMain:
Code:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	WNDCLASSEX winClass; //Window Class Name
	MSG uMsg; //Message Handler

	memset(&uMsg, 0, sizeof(uMsg));

	winClass.lpszClassName = TEXT("MY_WINDOWS_CLASS");
	winClass.cbSize = sizeof(WNDCLASSEX);
	winClass.style = CS_HREDRAW | CS_VREDRAW;
	winClass.lpfnWndProc = WindowProc;
	winClass.hInstance = hInstance;
	winClass.hIcon = NULL;
	winClass.hIconSm = NULL;
	winClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	winClass.hbrBackground = NULL;
	winClass.lpszMenuName = NULL;
	winClass.cbClsExtra = 0;
	winClass.cbWndExtra = 0;

	if(RegisterClassEx(&winClass) == 0)
	{
		return E_FAIL;
	}

	g_hWnd = CreateWindowEx(NULL, TEXT("MY_WINDOWS_CLASS"), TEXT("Direct3D (DX9) - Full Screen"), WS_POPUP | WS_SYSMENU | WS_VISIBLE, 0, 0, xRes, yRes, NULL, NULL, hInstance, NULL);

	if(g_hWnd == NULL)
	{
		return E_FAIL;
	}

	ShowWindow(g_hWnd, nCmdShow);
	UpdateWindow(g_hWnd);

	init();

	while(uMsg.message != WM_QUIT)
	{
		if(PeekMessage(&uMsg, NULL, 0, 0, PM_REMOVE))
		{ 
			TranslateMessage(&uMsg);
			DispatchMessage(&uMsg);
		}
		else
		{
			render();
		}
	}

	shutDown();

	UnregisterClass(TEXT("MY_WINDOWS_CLASS"), winClass.hInstance);

	return uMsg.wParam;
}
WindowProc:
Code:
LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
	case WM_KEYDOWN:
		{
			switch(wParam)
			{
			case VK_ESCAPE:
				PostQuitMessage(0);
				break;
			case VK_F1:
				//Show info
				break;
			}
		}
		break;

	case WM_CLOSE:
		{
			PostQuitMessage(0);
		}
		break;

	case WM_DESTROY:
		{
			PostQuitMessage(0);
		}
		break;

	default:
		{
			return DefWindowProc(hWnd, msg, wParam, lParam);
		}
		break;
	}

	return 0;
}
Initiate Direct3D:
Code:
void init(void)
{
	g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);

	if(g_pD3D == NULL)
	{
		return;
	}


	int nMode = 0;
	D3DDISPLAYMODE d3ddm;
	bool bDesiredAdapterModeFound = false;

	int nMaxAdapterModes = g_pD3D->GetAdapterModeCount(D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);

	for(nMode = 0; nMode < nMaxAdapterModes; ++nMode)
	{
		if(FAILED(g_pD3D->EnumAdapterModes(D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, nMode, &d3ddm)))
		{
			return;
		}

		//Does this adapter mode support a mode of xRes x yRes?
		if(d3ddm.Width != xRes || d3ddm.Height != yRes)
		{
			continue;
		}

		//Does this adapter mode support a 32-bit RGB pixel format?
		if(d3ddm.Format != D3DFMT_X8R8G8B8)
		{
			continue;
		}

		//Does this adapter mode support a refresh rate of 85 MHz? - Change this to your maximum refresh rate
		if(d3ddm.RefreshRate != 85)
		{
			continue;
		}

		//We found a match!
		bDesiredAdapterModeFound = true;
		break;
	}

	if(bDesiredAdapterModeFound == false)
	{
		return;
	}


	//Can we get a 32-bit back buffer?
	if(FAILED(g_pD3D->CheckDeviceType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, FALSE)))
	{
		return;
	}

	//Can we get a z-buffer that's at least 16 bits?
	if(FAILED(g_pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16)))
	{
		return;
	}


	D3DCAPS9 d3dCaps;

	if(FAILED(g_pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps)))
	{
		return;
	}

	DWORD flags = 0;

	if(d3dCaps.VertexProcessingCaps != 0)
	{
		flags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
	} else {
		flags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
	}


	D3DPRESENT_PARAMETERS d3dpp;
	memset(&d3dpp, 0, sizeof(d3dpp));

	d3dpp.Windowed = false;
	d3dpp.EnableAutoDepthStencil = true;
	d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferWidth = xRes;
	d3dpp.BackBufferHeight = yRes;
	d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
	d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

	if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, flags, &d3dpp, &g_pDevice)))
	{
		return;
	}
}
Release Direct3D:
Code:
void shutDown(void)
{
	if(g_pDevice != NULL)
	{
		g_pDevice->Release();
	}

	if(g_pD3D != NULL)
	{
		g_pD3D->Release();
	}
}
Render Direct3D:
Code:
void render(void)
{
	g_pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

	g_pDevice->BeginScene();
	
	//PUT ALL OF YOUR CRAP HERE!
	
	g_pDevice->EndScene();

	g_pDevice->Present(NULL, NULL, NULL, NULL);
}
Quote Originally Posted by Lyoto Machida View Post
Good Job dude!
Thanks... and to make it even better, you should create a method of toggling fullscreen and windowed...
This is actually the 2nd thing that you learn when you go for D3D. How to create a window with a custom background color. Well it's also nice
Posts 1–4 of 4 · Page 1 of 1

Post a Reply

Tags for this Thread

Talk with us