tutorial - initialize direct3d

create a direct3d project

  1. Create a new project: Open Microsoft Visual Studio and create a new empty project of the type "Win32 application". Call it "dxtut1" and save it in your favorite project location.


  2. Add the Direct3D libraries: Go to the settings dialog (Project -> Settings), select "Settings For: All Configurations". Go to the "Link" tab and add the libraries "d3dx8.lib" and "d3d8.lib" to the "Object/libary modules" list.


  3. Add a new source file: Create a new C++ source file and add it your project. Name it "dxtut1.cpp".


create a window

For this step I won't go into very much detail and will assume that you already know a little bit about Windows programming. Here we're going to create a simple Windows event loop and put an empty window up on the screen.

  1. Copy the following code into dxtut1.cpp:
    
    #include <d3dx8.h>
    
    //-----------------------------------------------------------------------------
    // MsgProc
    //-----------------------------------------------------------------------------
    // Interprets Windows messages
    
    LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
    {
        switch( msg )
        {
            case WM_DESTROY:
            case WM_KEYUP:
                PostQuitMessage( 0 );
                return 0;
    
            case WM_PAINT:
                ValidateRect( hWnd, NULL );
                return 0;
        }
    
        return DefWindowProc( hWnd, msg, wParam, lParam );
    }
    
    //-----------------------------------------------------------------------------
    // WinMain
    //-----------------------------------------------------------------------------
    // Windows main entry point
    
    int APIENTRY WinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPSTR     lpCmdLine,
                         int       nCmdShow)
    {
        // Register the window class
        WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, 
                          GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
                          "D3D Tutorial 1", NULL };
        RegisterClassEx( &wc );
    
        // Create the application's window
        HWND hWnd = CreateWindow( "D3D Tutorial 1", "D3D Tutorial 1", 
                                  WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
                                  GetDesktopWindow(), NULL, wc.hInstance, NULL );
    
    	// Show the window
        ShowWindow( hWnd, SW_SHOWDEFAULT );
        UpdateWindow( hWnd );
    
        // Enter the message loop
        MSG msg;
        ZeroMemory( &msg, sizeof(msg) );
        while( msg.message != WM_QUIT )
        {
            if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
            {
                TranslateMessage( &msg );
                DispatchMessage( &msg );
            }
        }
    
    
        // Clean up everything and exit the app
        UnregisterClass( "D3D Tutorial 1", wc.hInstance );
        return 0;
    }
    
    
  2. Hit "F5" to compile the code. If you've done everything correctly up until now, everything should compile and run properly.

create a direct3d device

Once you have a window open you can attach a Direct3D device to the window. For the purpose of this tutorial we're going to create a simple Direct3D device inside the window we created in the previous step.

  1. Create global variables to store pointers to our Direct3D device and Direct3D adapter. At the top of dxtut1.cpp add the following globals:
    LPDIRECT3D8             g_pD3D       = NULL;
    LPDIRECT3DDEVICE8       g_pd3dDevice = NULL;
    
  2. Create a Direct3D initialization routine. Add the following function somewhere near the top of your source file:
    //-----------------------------------------------------------------------------
    // D3DInit
    //-----------------------------------------------------------------------------
    
    HRESULT D3DInit(HWND hWnd)
    {
        if( NULL == ( g_pD3D = Direct3DCreate8( D3D_SDK_VERSION ) ) )
            return E_FAIL;
    
        D3DDISPLAYMODE d3ddm;
        if( FAILED( g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) )
            return E_FAIL;
    
        D3DPRESENT_PARAMETERS d3dpp;
        ZeroMemory( &d3dpp, sizeof(d3dpp) );
        d3dpp.Windowed = TRUE;
        d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
        d3dpp.BackBufferFormat = d3ddm.Format;
        d3dpp.EnableAutoDepthStencil = TRUE;
        d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    
        if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd,
                                          D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                          &d3dpp, &g_pd3dDevice ) ) )
        {
            return E_FAIL;
        }
    
        // We're going to handle lighting ourselves, for now
        g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
    
        // Turn on the zbuffer
        g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
    
    
        return S_OK;
    }
    
    This routine takes a pointer to your application's window handle and attaches a Direct3D software rendering device to it. If you want to create a hardware rendered window (if your computer supports it) replace D3DDEVTYPE_REF with D3DDEVTYPE_HAL.


  3. Create a Direct3D shutdown routine. Copy the following code into your source file:
    //-----------------------------------------------------------------------------
    // D3DShutdown
    //-----------------------------------------------------------------------------
    
    void D3DShutdown()
    {
        if( g_pd3dDevice != NULL) 
            g_pd3dDevice->Release();
    
        if( g_pD3D != NULL)
            g_pD3D->Release();
    }
    
    This routine releases the resources we used.


  4. Add the D3DInit() and D3DShutdown() functions into your WinMain() function.
        // Initialize Direct3D
        if( SUCCEEDED( D3DInit(hWnd) ) )
        {
            // Show the window
            ShowWindow( hWnd, SW_SHOWDEFAULT );
            UpdateWindow( hWnd );
    
            // Enter the message loop
            MSG msg;
            ZeroMemory( &msg, sizeof(msg) );
            while( msg.message != WM_QUIT )
            {
                if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
                {
                    TranslateMessage( &msg );
                    DispatchMessage( &msg );
                }
            }
        }
    
        // Clean up everything and exit the app
        D3DShutdown();
        UnregisterClass( "D3D Tutorial 1", wc.hInstance );
        return 0;
    
  5. Verify the code compiles and runs. Notice nothing is drawn in the window (at all) because we haven't drawn anything yet! :-)

add our rendering routine

In this section we add a simple function that will serve as our primary rendering function. It will get called everytime Direct3D wants us to draw.
  1. Create a simple rendering function. Add the following code to your source file:
    //-----------------------------------------------------------------------------
    // D3DRender
    //-----------------------------------------------------------------------------
    
    void D3DRender()
    {
        if( NULL == g_pd3dDevice )
            return;
    
        // Clear the backbuffer to black
        g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
        
        // Begin the scene
        g_pd3dDevice->BeginScene();
        
        // Draw stuff here
        
        // End the scene
        g_pd3dDevice->EndScene();
        
        // Present the backbuffer contents to the display
        g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
    }
    
    This very simple rendering function demonstrates 4 of the 5 steps required to draw using Direct3D:

    • Clear the backbuffer. Before you draw you want to make sure you're starting with a clean slate.
    • Call BeginScene(). This tells Direct3D that you are about to perform drawing.
    • Call EndScene(). This tells Direct3D that you are done drawing.
    • Call Present(). This tells Direct3D to put your current frame up onto the physical device.

    What's the missing step? Drawing, of course. :-)


  2. Insert your rendering function into the event loop. There are two places you need to do this. The first is in the MsgProc:
        switch( msg )
        {
            case WM_DESTROY:
    		case WM_KEYUP:
                PostQuitMessage( 0 );
                return 0;
    
            case WM_PAINT:
                D3DRender();
                ValidateRect( hWnd, NULL );
                return 0;
        }
    
    The second is in WinMain:
            // Enter the message loop
            MSG msg;
            ZeroMemory( &msg, sizeof(msg) );
            while( msg.message != WM_QUIT )
            {
                if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
                {
                    TranslateMessage( &msg );
                    DispatchMessage( &msg );
                }
                else
                    D3DRender();
            }
    
  3. Compile and run your code. You should get a nice black window. :-)

source files

The source file for everything done up until now is available here.

Tutorial Menu