Thursday, October 13, 2011

10 Minute Guide to DirectX 11 Programming in C++

DirectX is already 16 years old. There are tons of resources available online for DirectX programming. This post will give you just some idea how quickly a simple Direct3D based application can be built. This will serve as a starting point for my future posts on XNA Game Studio or SlimDX library for managed 3D visualization on .Net platform.

Prerequisites
1.
DirectX Software Development Kit. It will include DirectX End-User Runtimes (June 2010) which is necessary to run your DirectX application on client computer.
2. Some knowledge of COM programming
3.
Visual C++ 2010 Express IDE. If you are comfortable with building C++ application from command line, you don't need this IDE.

Concepts
  1. Direct3D: Used for all 3D graphics in DirectX
  2. Rendering pipeline: DirectX processes build the scene in multiple layers called rendering pipeline.
  3. Swap Chain - This is ideally buffers for the rendering. Double buffering with 1 front buffer and 1 back buffer is a popular technique to reduce flicker effect.
  4. Rendering: Send your buffer to the output.
Implementation
  1. Create a Win32 Project using Visual C++ 2010 Express "New Project" Wizard like the following and let's name the project RenderDirectX:




  2. Right click your project in the solution explorer and select properties. Select to C/C++ from the tree and add <directx-installation-dir>\Include to "Additional Include Directories" Field. Replace <directx-installation-dir< with the installation directory of your DirectX.


  3. Now select Linker from the tree in the property pages and add <directx-installation-dir>\Lib\X86 to "Additional Library Directories" Field. Replace <directx-installation-dir> with the installation directory of your DirectX.


  4.  Now select Linker->Input and add d3d11.lib;d3dx11.lib;dxerr.lib; to "Additional Dependencies" Field.


  5. Include the following headers in RenderDirectX.cpp file:
    #include<d3d11.h>
    #include<d3dx11.h>
    #include<dxerr.h>
    
  6. Initialize the Direct3D device and swap chain with intended feature level and driver types:
    ID3D11Device* piD3dDevice;
    D3D_FEATURE_LEVEL eFeatureLevel;
    ID3D11DeviceContext* piD3dContext;
    D3D_FEATURE_LEVEL aFeatureLevel[] =
    {
            D3D_FEATURE_LEVEL_11_0,
            D3D_FEATURE_LEVEL_10_1,
            D3D_FEATURE_LEVEL_10_0
    };
    
    DXGI_SWAP_CHAIN_DESC stSwapChainDesc; // initialize the swap description 
    IDXGISwapChain* piSwapChain;
    D3D11CreateDeviceAndSwapChain( 0, D3D_DRIVER_TYPE_HARDWARE, 0, 0, aFeatureLevel, 
             ARRAYSIZE(aFeatureLevel),  D3D11_SDK_VERSION, &stSwapChainDesc, 
             &piSwapChain, &piD3dDevice, &eFeatureLevel, &piD3dContext );
    
  7. Create a render target view and set it to the device context:
    ID3D11Device* piD3dDevice;
    ID3D11Texture2D* piTexture;
    piSwapChain->GetBuffer(0, __uuidof( ID3D11Texture2D ),    ( LPVOID* )&piTexture);
    ID3D11RenderTargetView* piTargetView;
    piD3dDevice->CreateRenderTargetView(bufferTexture, 0, &piTargetView);
    piD3dContext->OMSetRenderTargets( 1, &piTargetView, 0 );
    //Bind viewports to rasterizer stage of pipeline
    piD3dContext->RSSetViewports(1, &viewport);
    
  8. Change your windows message so that it can update the screen even if no event occurs and draw your image:
    ID3D11Device* piD3dDevice;
    while( msg.message != WM_QUIT )
    {
            if( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) )
            {
                TranslateMessage( &msg );
                DispatchMessage( &msg );
            }
            else
            {
                // Update and Draw 
                float afColor[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
                piD3dContext->ClearRenderTargetView(piTargetView, afColor);
                piSwapChain->Present(0, 0);
            }
    }
    
  9. Uninitialize the device and release resources
    ID3D11Device* piD3dDevice;
    piTargetView->Release( );
    piSwapChain->Release( );
    piD3dContext->Release( );
    piD3dDevice->Release( );
    
This is rather quick and dirty way of coding with no error handling and object orientation. For real application you should proceed in more object oriented way and use smart pointers to automatically release the resources. DirectX programming is complex and one needs years of experience to master it due to multidisciplinary knowledge required to create attractive visualization effects. To render even a simple content, you have to understand Geometry, Vertex & Vertex Buffer and Pixel Shader. In future posts, I will give more insights into the wonderful world of Visualization, Animation, Gaming on DirectX.


I hope this tutorial will give you a starting point to play with 3D visualization on Windows platform. The complete code for this post can be downloaded from http://keensocial.freeiz.com/blogs/directx/renderdirectx/renderdirectx.zip

No comments:

Post a Comment