Shadow Blade
Morrowland Presents Apron Tutorials
game - design - multimedia - web - programming - tutorials - There are currently viewers visiting Apron Tutorials.







  visual basic










  draw sketch


  3d studio


  shadow blade

  game environment

  virtual 3d guide

  billy blue flame


  win32 api





  about us




In this tutorial you will learn how to create an empty Direct3D window. Before we start I will mention that this window code is created by Ronny André Reierstad to be almost exactly the same window as in the OpenGL tutorials. Since we are using NeHe’s window in the OpenGL section, this window is after my opinion the Direct3D version of the NeHe base code. I’m mentioning this because I have tried to make it easy for you to compare the two most common 3D libraries. DirectX is as you probably already know not just a 3D API, but also include a lot of other facilities. For now we will focus on the 3D part called Direct3D. For those of you who are unfamiliar with C++ syntax, but are familiar with languages like Visual Basic or C# etc. don’t worry. Just focus on the DirectX calls, they are pretty much the same in all the programming languages, and I will try to explain how it works..

In order to create windows applications with DirectX 3D you will first need to download the latest DirectX SDK files. We will use DirectX Version 9.0 or DX9 in this tutorial, but Microsoft has made it simple to upgrade so if you use an other version all you have to do is change a few variables. Download the latest DirectX SDK version     Download DX9.0b SDK

In Microsoft Visual Studio you can include the needed lib files in Project->Settings menu under the Link tab. Or you can include them by code, as you can see below. I have already done this for you in this source code, but since this may be the first time you include a lib file I’ll tell you a little about it. Lib files are library files that can give us programming access to a dll file. For a programmer dll files can be much like a precompiled class with a lot of useful functions.. A lib file can be included like you see below by using a pragma call.

#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "d3d9.lib")

#include "windows.h"		// Header File For Windows
#include "dx9/d3dx9.h"		// Header File For DirectX 3D
#include "dx9/d3d9.h"		// Header File For DirectX 3D

2# Ok! Next we need to declare some variables. Our window will need a window handle and a device context. Next we need two pointers to the DirectX 3D interface. LPDIRECT3D9 pD3D to create our D3D device, and LPDIRECT3DDEVICE9 pd3dDevice as our D3D rendering device. We also will also use an array for our keyboard routine, a boolean called active (set to true if the application is running) and a fullscreen flag.

HDC	   	hDC=NULL;   	// Private GDI Device Context
HWND	   	hWnd=NULL;  	// Holds Our Window Handle
HINSTANCE   	hInstance;  	// Holds The Instance Of The Application
LPDIRECT3D9	pD3D=NULL;	// DirectX 3D Version 9
LPDIRECT3DDEVICE9	pD3DDevice=NULL;	// DirectX 3D Rendering Device

bool	keys[256];          // Array Used For The Keyboard Routine
bool	active=TRUE;        // Window Active Flag Set To TRUE By Default
bool	fullscreen=TRUE;    // Set To Fullscreen Mode By Default

3# The next thing we are going to declare is our window procedure function. This function handles all the messages that are being sent to our window. If we press a key or move the mouse we want our window to know..


4# The ReSizeD3Dscene function is used to resize our Direct3D scene. This function also makes sure we don’t “do a divide by zero” and crash the application. To reset and define our new view port we first pass in our wanted scene width and height as arguments. We then want to create a nice perspective roughly meaning that things get smaller in a distance.

Next we are going to set up our 4x4 projection matrix. The projection matrix is responsible for adding perspective to our scene(transforms geometry from 3D view space to 2D viewport space). To build the perspective view we use D3DXMatrixPerspectiveFovLH For the field of view (45 degrees or 1/4 pi is common), the aspect ratio, and the near and far clipping planes (which define at what distance geometry should not be rendered). Finally we have to set our projection matrix with SetTransform. Don't worry if you don't understand all this stuff.. Just know that it has to be done if you want the window view to be in perspective.

void ReSizeD3DScene(int width, int height)
   if (height==0)				// Prevent A Divide By Zero By
	height=1;				// Making Height Equal One

   D3DXMATRIXA16 matProjection;		// Create A Projection Matrix

   // Calculate The Aspect Ratio Of The Window
   D3DXMatrixPerspectiveFovLH(&matProjection, 45.0f, width/height, 0.1f, 100.0f);

   pD3DDevice->SetTransform( D3DTS_PROJECTION, &matProjection );
   D3DXMatrixIdentity(&matProjection;	// Reset The Projection Matrix

5# Here we will do all of the geometry initialisation for our Direct3D applications. We turn on the ZBuffer (depth buffer). For now we also turn off lighting, and disable back face culling (to be enable to see polygons from all directions). This function will not be called until the Direct3D Window has been successfully created.

We enabled the depth buffer. Think of the depth buffer as layers into the screen. The depth buffer keeps track of how deep objects are into the screen. It keeps track of which object to draw first so that a square you drew behind a triangle doesn't end up if front of the triangle on the screen. The depth buffer is a very important part of Direct3D, and of 3D programming in general. We don't need to use the depth buffer in this application, but as you start to explore more advanced D3D tutorials, try to disable the depth buffer and see what happens..

What else can you use the setup function for in the future? If you want to load 3D models you need to load the models before you can render them. It would be appropriate to call your model loading functions here, but for now we are only dealing with a blank D3D window.

int InitD3D()				// Setup For D3D Goes Here	
   pD3DDevice->SetRenderState(D3DRS_ZENABLE,  TRUE ); // Z-Buffer (Depth Buffer)
   pD3DDevice->SetRenderState(D3DRS_CULLMODE, FALSE); // Disable Backface Culling
   pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); // Disable Light
   return TRUE;				// Initialization Went OK

6# This is what you been waiting for ; ) It's time to take a look at the rendering function.. In this function you can call all the models you plan to display on the screen. Anything from simple geometry to modern game characters. But fist you must clear the color and depth buffer.. It works like this: You should first clear the color and depth buffer, then you render your scene using double buffering. Double buffering is a technique used by graphic systems to support smooth rendering by drawing with two color buffers often called: the front color buffer and back color buffer. With double buffering, you render your scene to the (off-screen) back buffer. After the scene is finished rendering, you swap the back buffer with the front buffer. This buffer swapping process happens so fast that it is hidden from the user. The double buffering technique eliminates the flickering effects that usually arise when scenes are rendered directly to the screen. You should always clear the screen first. This way you will prevent the frames you paint to the screen from overlapping. If you don’t like the idea of the two “layers swapping”, you can just imagine that you’re drawing directly to the screen, like I do ; ) Now you know how it works, and don’t worry the window code will handle this process for you. Just think of it as a simple flip book..

We use the Clear function to clear the color and depth buffer:
HRESULT Clear( DWORD Count, const D3DRECT *pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil);

Count - The number of individual rectangles you want cleared. If you're clearing the whole back buffer, set this to 0.

pRects - This is an array of RECT structs that are to be cleared. If you want the entire back buffer cleared, set this to NULL.

Flags - Allowed flags (in any combination) are D3DCLEAR_STENCIL, D3DCLEAR_TARGET and D3DCLEAR_ZBUFFER. You can only specify D3DCLEAR_STENCIL if you have a stencil buffer, and D3DCLEAR_ZBUFFER if you have a Z (depth) buffer. If you specify a flag without a matching surface, the call will fail. Also, at least one of these flags must be specified.

Color - D3DCOLOR_COLORVALUE sets the color of the screen. The color values range from 0.0f to 1.0f. 0.0f being the darkest and 1. 0f being the brightest. This function uses RGBA values. The first parameter is the Red Intensity, the second parameter is for Green and the third is for Blue. The closer the value of the number is to 1.0f, the brighter that specific color will be. The last number is an Alpha value. When it comes to clearing the screen, we won’t worry about the 4th number. For now just leave it at zero. You create different colors by mixing the three primary colors for light (red, green, blue).

Z - This value is used to clear the depth buffer. Legal values range from 0.0 to 1.0, with 0.0 being the closest distance and 1.0 being the farthest.

Stencil - The Stencil buffer will be cleared to this value. It's an integer value ranging from 0 to 2n-1, where n is the depth of the stencil buffer.

We always call BeginScene to begin the drawing of the Direct3D scene, and EndScene to end the drawing. At the end we call Present to present/draw the backbuffer content to the screen.

int DrawD3DScene()			// Here's Where We Do All The Drawing
    // Clear Screen And Depth Buffer
		        D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,0.0f), 1.0f, 0 );

    // Place your code here!

    pD3DDevice->Present( NULL, NULL, NULL, NULL );	// Display Result

    return TRUE;				// Keep Going

7# KillD3DScene is our Direct3D unloading function. For the time being we don’t have any thing to unload.

void KillD3DScene()			// Properly Kill D3D Scene
    // Nothing here to unload.

8# The next section of code is called just before we exit the application. The purpose of KillD3DWindow is to release the Rendering Device, Direct3D Interface , the Device Context and finally the Window Handler. NeHe have added a lot of useful error checking to this function. If the program is unable to destroy any part of the Window, a message box will appear with a describing error message, making it a lot easier to find errors, and do manual debugging.

void KillD3DWindow()			// Properly Kill The Window
    KillD3DScene();			// Release D3D Scene

    if (pD3DDevice!=NULL)	pD3DDevice->Release();// Release D3D Device
    if (pD3D!=NULL) pD3D->Release();		// Release D3D Interface

    if (fullscreen)			// Are We In Fullscreen Mode?
	ChangeDisplaySettings(NULL,0);	// witch Back To Desktop
	ShowCursor(TRUE);			// Show Mouse Pointer
    if (hDC && !ReleaseDC(hWnd,hDC))		// Are We Able To Release The DC
	MessageBox(NULL,"Release Device Context Failed.",
	hDC=NULL;				// Set DC To NULL

    if (hWnd && !DestroyWindow(hWnd))	// Able To Destroy The Window?
	MessageBox(NULL,"Could Not Release hWnd.",
	hWnd=NULL;			// Set hWnd To NULL

    if (!UnregisterClass("Direct3D",hInstance))// Able To Unregister Class?
	MessageBox(NULL,"Could Not Unregister Class.",
	hInstance=NULL;			// Set hInstance To NULL

9# This LONG function creates an DirectX 3D Win32 window. In general it starts by setting up a Win32 window , moves on to ask if we want fullscreen and then inserts the values we want for our Direct3D window. A last if everything was successful it calls InitD3D our setup function.

The WNDCLASS wc object will be used to hold our Window Class structure. The Window Class structure holds information about our window. By changing different fields in the Class we can change how the window looks and behaves. Every window you see has it’s own Window Class. Before you create your window, you must register a class for the window.

dwExStyle and dwStyle will store the Extended and normal Window Style Information. We can use variables to store the styles so that we can change the styles depending on what type of window we need to create (A popup window for fullscreen or a window with a border for windowed mode)

The following five lines of code holds the values of the upper left, and lower right values of a rectangle. We can use these values to adjust the window size so that the area we draw is the exact resolution we want to have for our window. If we create a 640x480 window, the borders of the window will take up some of our resolution tough.

Now we move on to insert the value of our fullscreen flag. Before we start to define some of the properties of our new window by using our wc window class object. We pass in values like which mouse cursor, application icon and our message handler. After this we register our window class with RegisterClass..

After we have set our wanted display mode we use AdjustWindowRectEx to pass in our rectangle values and CreateWindowEx to create our window with our wanted size and properties. If the function should fail to create the window correctly, it will move to destroy the window and exit the program.

Coming up next is the code that describes a Pixel Format. In most DirectX 3D tutorials you will find the pixel format descriptor this way:

D3DPRESENT_PARAMETERS d3dpp; 	// Pixel Format Decription
ZeroMemory(&d3dpp, sizeof(d3dpp));  // Reset

d3dpp.BackBufferWidth			 = width;
d3dpp.BackBufferHeight			 = height;
d3dpp.BackBufferFormat			 = D3DFMT_R5G6B5;
d3dpp.BackBufferCount			 = 1;
d3dpp.MultiSampleType			 = D3DMULTISAMPLE_NONE;
d3dpp.MultiSampleQuality		 	 = 0;
d3dpp.SwapEffect             	 	 = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow			 = hWnd;
d3dpp.Windowed               	 	 = !fullscreen;
d3dpp.EnableAutoDepthStencil	 	 = TRUE;
d3dpp.AutoDepthStencilFormat	 	 = D3DFMT_D16;
d3dpp.Flags				 = 0;
d3dpp.FullScreen_RefreshRateInHz 	 	 = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval		 	 = D3DPRESENT_INTERVAL_DEFAULT;

After we have set up our pixel-format we can use CheckDeviceFormat to check if our wanted format and device are valid. If it is it’s time to create our Direct3D device. We do this by passing in our parameters into CreateDevice. If everything went smoothly as planned, and our Direct3D Win32 window was created correctly we need to show the new window, set it to be the foreground window (giving it higher priority) and then set the focus on that window. Then we can call ReSizeD3Dscene passing it the screen width and height to set up our new D3D screen with a nice perspective view. FINALLY it’s time to call our D3D setup function InitD3D..

BOOL CreateD3DWindow(char* title, int width, int height, bool fullscreenflag)
    // First some standard Win32 window creating
    WNDCLASS	wc;
    DWORD		dwExStyle;	
    DWORD		dwStyle;	
    RECT		WindowRect;

    // fullscreen variable

    hInstance		= GetModuleHandle(NULL);		= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wc.lpfnWndProc		= (WNDPROC) WndProc;
    wc.cbClsExtra		= 0;
    wc.cbWndExtra		= 0;
    wc.hInstance		= hInstance;
    wc.hIcon		= LoadIcon(NULL, IDI_WINLOGO);	
    wc.hCursor		= LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground	= NULL;			
    wc.lpszMenuName	= NULL;		
    wc.lpszClassName	= "Direct3D";	

    // Register the window class
    if (!RegisterClass(&wc))		
	MessageBox(NULL,"Failed To Register The Window Class.",
	return FALSE;			

    if (fullscreen)	

    AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);

    // Create The Window
    if (!(hWnd=CreateWindowEx(	dwExStyle,	
				dwStyle |		
				0, 0,				
	KillD3DWindow();		// Reset The Display
	MessageBox(NULL,"Window Creation Error.",
	return FALSE;			

    // Did We Get A Device Context?
    if (!(hDC=GetDC(hWnd)))	
	KillD3DWindow();		// Reset The Display
	MessageBox(NULL,"Can't Create A Device Context.",
	return FALSE;		// Return FALSE

    // Check For The Correct DirectX 3D version
    pD3D = Direct3DCreate9( D3D_SDK_VERSION );
    if ( pD3D == NULL )
	KillD3DWindow();		// Reset The Display
	MessageBox(NULL,"Can't find D3D SDK Version 9.",
	return FALSE;		// Return FALSE

    // Tell the window how we want things to be..
	width,			// Back Buffer Width
	height,			// Back Buffer Height
	D3DFMT_R5G6B5,		// Back Buffer Format (Color Depth)
	1,			// Back Buffer Count (Double Buffer)
	D3DMULTISAMPLE_NONE,	// No Multi Sample Type
	0,			// No Multi Sample Quality
	D3DSWAPEFFECT_DISCARD,	// Swap Effect (Fast)
	hWnd,			// The Window Handle
	!fullscreen,		// Windowed or Fullscreen
	TRUE,			// Enable Auto Depth Stencil  
	D3DFMT_D16,		// 16Bit Z-Buffer (Depth Buffer)
	0,			// No Flags
	D3DPRESENT_RATE_DEFAULT,   // Default Refresh Rate
	D3DPRESENT_INTERVAL_DEFAULT	// Presentation Interval (vertical sync)

    // Check The Wanted Surface Format
			d3dpp.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
			D3DRTYPE_SURFACE, d3dpp.AutoDepthStencilFormat ) ) )
	KillD3DWindow();		// Reset The Display
	MessageBox(NULL,"Can't Find Surface Format.",
	return FALSE;		// Return FALSE

    // Create The DirectX 3D Device 
					 &d3dpp, &pD3DDevice ) ) )
	KillD3DWindow();		// Reset The Display
	MessageBox(NULL,"Can't Create DirectX 3D Device.",
	return FALSE;		// Return FALSE

    ShowWindow(hWnd,SW_SHOW);	// Show The Window
    SetForegroundWindow(hWnd);	// Slightly Higher Priority
    SetFocus(hWnd);		// Sets Focus To The Window
    ReSizeD3DScene(width, height);	// Set Up Our Perspective D3D Screen

    // Initialize Our Newly Created D3D Window
    if (!InitD3D())
	KillD3DWindow();		// Reset The Display
	MessageBox(NULL,"Initialization Failed.",
	return FALSE;		// Return FALSE

    return TRUE;			// Success

10# This our windows message handler WndProc (window procedure). It handles all the messages for our window like mouse move, key pressed, application closed .etc. The code below is how we set up a standard message loop:

These commands are being called
WM_ACTIVATE // if the window is activated
WM_SYSCOMMAND // on system command interrupts
WM_CLOSE // on close window command
WM_KEYDOWN // if a key is pressed
WM_KEYUP // if a key is released
WM_SIZE // if window is resized

LRESULT CALLBACK WndProc(	HWND hWnd,	// Handle For This Window
			UINT	uMsg,	// Message For This Window
			WPARAM	wParam,  // Additional Message Information
			LPARAM	lParam)	// Additional Message Information
	switch (uMsg)			// Check For Windows Messages
		case WM_ACTIVATE:	// Watch For Window Activate Message
			if (!HIWORD(wParam))// Check Minimization State
				active=TRUE;// Program Is Active
				active=FALSE;// Program Is No Longer Active

			return 0;	// Return To The Message Loop

		case WM_SYSCOMMAND:	// Intercept System Commands
			switch (wParam)	// Check System Calls
				// Screensaver Trying To Start?
				case SC_SCREENSAVE:	
				// Monitor Trying To Enter Powersave?
				return 0;	// Prevent From Happening
			break;			// Exit

		case WM_CLOSE:	// Did We Receive A Close Message?
			PostQuitMessage(0);// Send A Quit Message
			return 0;		// Jump Back

		case WM_KEYDOWN:		// Is A Key Being Held Down?
			keys[wParam] = TRUE;// If So, Mark It As TRUE
			return 0;		// Jump Back

		case WM_KEYUP:		// Has A Key Been Released?
			keys[wParam] = FALSE;// If So, Mark It As FALSE
			return 0;			// Jump Back

		case WM_SIZE:		// Resize The Direct3D Window
 			// LoWord=Width, HiWord=Height
			ReSizeD3DScene(LOWORD(lParam), HIWORD(lParam));
			return 0;			// Jump Back

	// Pass All Unhandled Messages To DefWindowProc
	return DefWindowProc(hWnd,uMsg,wParam,lParam);

11# Last we will look at the function that is called first by standard Win32 application the WinMain. As you can see this function starts with a declaring two variables. The first variable msg is for the message loop. The second is a boolean to see if we want to exit the message loop. Then it calls a message box that asks which screen mode we prefer. It will then call our function CreateGLWindow with the wanted screen resolution and our fullscreen variable. After the window is created this function will go into a loop. This message loop will go on until the Esc or exit window button is pressed. If you study the function for a while you will see that by pressing F1 you can toggle between fullscreen and window mode.

int WINAPI WinMain( HINSTANCE hInstance,	// Instance
		  HINSTANCE hPrevInstance,	// Previous Instance
		  LPSTR lpCmdLine,		// Command Line Parameters
		  int nCmdShow)		// Window Show State
	MSG	msg;			// Windows Message Structure
	BOOL	done=FALSE;		// Bool Variable To Exit Loop

	// Ask The User Which Screen Mode They Prefer
	if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?",
		fullscreen=FALSE;	// Windowed Mode

	// Create Our DirectX 3D Window
	if (!CreateD3DWindow("APRON TUTORIALS",640,480,fullscreen))
		return 0;		// Quit If Window Was Not Created

	while(!done)		// Loop That Runs While done=FALSE
		// Is There A Message Waiting?
		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
			// Have We Received A Quit Message?
			if (msg.message==WM_QUIT)
				done=TRUE;// If So done=TRUE
			else	// If Not, Deal With Window Messages
				// Translate The Message
				// Dispatch The Message
		else			// If There Are No Messages
			// Draw The Scene.
			// Active?  Was There A Quit Received?
			if ((active && !DrawD3DScene()) || keys[VK_ESCAPE])
				// ESC or DrawD3DScene Signalled A Quit
			else		// Not Time To Quit, Update Screen
				// Swap Buffers (Double Buffering)

			if (keys[VK_F1])	// Is F1 Being Pressed?
				keys[VK_F1]=FALSE;// If So Make Key FALSE
				KillD3DWindow();	// Kill Our Current Window
				// Toggle Fullscreen / Windowed Mode
				// Recreate Our DirectX 3D Window
				if (!CreateD3DWindow("APRON TUTORIALS",
					// Quit If Window Was Not Created
					return 0;

	// Shutdown
	KillD3DWindow();		// Kill The Window
	return (msg.wParam);	// Exit The Program

Ok, that’s it : ) You can shorten the code by removing all the error testing, but I don’t recommend it! You can feel free to use this window in all your Direct3D applications, this way you don't have to create your own. But I do recommend that you read through the code a couple of times. Learn how to use it, and then move on the next and easier tutorial.. If you want you can compare it with the OpenGL window, I think you will find them very comparable, at least that was the idea ; )


Ronny André Reierstad

This Direct3D window code created by Ronny André Reierstad 06.12.03.
Special thanks to NeHe for the OpenGL version of this window.

Download Source Code! Visual Studio C++ Source Code


  morrowland home






  shadow blade

  game environment

  virtual 3d guide

  billy blue flame





  All rights reserved Morrowland © 2011  
Ronny André Reierstad