DirectX-Intro by xumiaomaio


									                     Introduction to
            DirectX 3D Game Programming

                                  Dr Abdennour El Rhalibi

PacMan by Midway, released 1980
                   What is DirectX
• DirectX is a set of components, referred to as the
  Foundation, developed to provide Windows-based
  programs with high-performance, real-time access to
  available hardware on current computer systems.

• DirectX was primarily developed for Windows 95, but
  Windows NT 4.0 and later Server versions of Windows
  also supported a subset of DirectX.

• 2D/3D graphics / multimedia API
  – Designed for Game and Multimedia Programming
  – Works only on MS Windows platform
     • 95/98/ME/2000/XP
     • Old version for Windows NT
• Windows API for making games
• Microsoft says ―The power of multimedia in
  Windows, DirectX gives you the best possible
  experience with graphics, sound, music, and 3-
  D animation.‖
• API in MSDN:

               Versions of DirectX
• First introduction in 1996
   – Goal: ―Easy‖ game programming under MS Windows
• Backward Compatible
  – Applications compiled with older version should work
    with newer version
• Current versions
   – DirectX 9c
   – DirectX 8.1b : Windows 95/98/ME/2000 (2001)
      • Built-in to Windows XP

        Components of DirectX : 9c
•   Direct3D
•   DirectDraw: integrated into Direct3D in DX 8
•   DirectShow: integrated into Direct3D in DX 8
•   DirectSound / DirectMusic
•   DirectInput
•   DirectPlay
•   DirectSetup

                          Direct3D 9
• There is no more DirectDraw--only Direct3D:
   – Historically, graphics in DirectX has been divided into two parts: DirectDraw
     for 2D graphics and Direct3D for taking care of the 3D graphics pipeline.
     DirectX 8.0 merged DirectDraw and Direct3D into a single entity
• Direct3D 9 provides a hardware-independent way for using 3D
  capabilities of video cards.
• Standard 3D transformation pipeline is supported: world matrix,
  view matrix, projection matrix.
• Support for rasterising geometric primitives: points, lines,
   – Higher-order primitives are also supported, but only in hardware way - no
     software emulation.
• Powerful lighting subsystem: materials and lights.
• 3D texturing
                       Direct3D 8
• Before DirectX 8.0
  Graphics in DirectX were handled through two different libraries.
  DirectDraw and Direct3D( version 6.0 onwards). The rendering of
  graphics in the 2D plane were the responsibility of the
  DirectDraw. It supported bitmaps, lines, pixels, polygons.

• After DirectX 8.0
  Graphics is now handled in one library DirectGraphics. This was
  many due to the complaints by the hardware industry.

• Basic Principles – within a window the Basic way to use DirectX
  is to create a instance of the surface object and render directly to
  this surface.
                        DirectX 9 SDK
 First of all for Direct3D to work you need to download the most recent SDK
   (Software Development Kit) from Microsoft.

 For the creation of a Direct3D 9 application you must include all necessary
  header files into your program and link your program with all necessary
 There are two useful header files and two necessary libraries:

     d3d9.h    - Header file with core Direct3D9 interfaces declarations.

     d3d9.lib - Library file for linking your program with Direct3D9 DLL.

     d3dx9.h    - Header with some very useful tool functions and interfaces.

     d3dx9.lib - Library for d3dx9.h.

      How does DirectX work?
• Almost hardware-level control of all devices
• Through a Microsoft technology called
  Component Object Model (COM)
• With a set of drivers and libraries written by
  – MS : conventions of functions, variable, data
    structure …
  – Hardware vendors : implement their drivers
    using the convention.

              Practical Issues
• DirectX 9.0c needs Visual Studio 2003 or 2005
• Older releases of DirectX 9 might compile with
  Visual Studio 6.0
• However VS 6.0 is 8 years old
• Visual Studio Express can compile some of the
  simpler SDK 9.0 tutorials but cannot handle
  things like Resource files etc.
• Get VS 2003/2005 from MSDNAA (copy CD in
  Lab 616)
Architecture of DirectX

         The HEL and HAL
• HAL (Hardware Abstraction Layer)
  – Device driver from the vendor
  – HAL is directly used when an operation is supported
    directly by the hardware.
  – Ex) bitmap rotation (supported by hardware)
• HEL (Hardware Emulation Layer)
  – Emulate the operations by software algorithm when the
    operation is not supported by the hardware.
  – Slower than directly using HAL but it works!
• DirectX  HEL  HAL  H/W or
• DirectX  HAL  H/W
• Using HEL and HAL is transparent to programmers.
  DirectX v.s. GDI/MCI
Graphic Device Interface/Media controller Interface

      (Component Object Model)
• DirectX libraries are implemented as COM
• COM object is a black box performing one or
  more tasks
  – Similar to C++ objects
  – Implemented as DLL
  – Strict encapsulation
  – Not explicitly loaded
  – Supports many programming languages:
    • C++, Delphi, VB, C#, etc…
         Game Program Complexity
• Game programs are some of the most complex
  – Basically they are ultra-high performance computer programs
• Real-time, multithreaded, intelligent simulations
  displaying 30 frames per second or more
• Speed is extremely important
• Experienced game programmers sometimes use a
  coding style that optimizes program execution speed
• Warning: Video game programming is 90 % data
  – Careful data structure (simple is usually better)
  – Very careful algorithm selection (efficient is better!)   15
State Transition Diagram for Game

   Game               Game            Game
    Init              Menu             Exit

            Game             Game
           Starting          Ending

    What’s happening programically?
  while (game not closed)
  Simple game loop                        Start
                                  Display Menu GUI        Exit to O/S

                                  • Allocate memory
                                  • Load levels
                                  • …

                                  Retrieve player input

                                  Main logic
   Cleanup                        • Collision Detection
   • Deallocate                   • Game AI
   • Close files
                   Exit to menu
                                  • Physics

                                  Render next frame

What’s missing?     Timing                                              18
                 What is timing?
• We don’t want our game loop to go too slow or
  too fast
  – different machines have different capabilities
• Solution:
  – time your game loop
  – synch games on all PCs to the same pace, even if
    they are rendering more or less frames per second
  – synch all behavior to time, not to frames
• How?
  – ―throttle frames‖ using high-resolution timer
  – we must do this for good animation and movement
• Windows has a low-resolution timer
   – call GetTickCount( )

• we could cap loop speed in milliseconds
• Ex:
if ((GetTickCount()-start) >=30)
    start = GetTickCount();
• Problem is, this timer is not very precise
• We’ll see a high-resolution timer is better
• DirectX uses devices to represent hardware
• Direct3D device is the graphics processor
  – required for all rendering
  – gets created when application first loads
  – gets recreated during toggle between full screen &
    windowed mode

    Example: Create a Device with D3D
• To use Direct3D, you first create an application window, then you create
  and initialise Direct3D objects. You use the COM interfaces that these
  objects implement to manipulate them and to create other objects required to
  render a scene.

• The CreateDevice example illustrates these tasks by creating a Direct3D
  device and rendering a blue screen.

• We apply the following steps to initialise Direct3D, render a scene, and
  eventually shut down.

•   Step 1: Creating a Window
•   Step 2: Initialising Direct3D
•   Step 3: Handling System Messages
•   Step 4: Rendering and Displaying a Scene
•   Step 5: Shutting Down
    DirectX Set-up – 20 easy steps 
•   Setup
     –   Direct3DCreate8(…);
     –   GetDeviceCaps(…);
     –   GetAdapterCount(); and GetAdapterModeCount();
     –   CreateDevice(…);
•   Resources
     –   CreateVertexBuffer
     –   CreateIndexBuffer
     –   CreateTexture
     –   CreateVertexShader();
     –   CreatePixelShader();
•   Rendering
     –   Begin/EndScene();
     –   SetMaterial(...);
     –   SetLight(...);
     –   LightEnable(...);
     –   SetViewport(...);
     –   SetTransform(...); - World, view and projection
     –   SetStreamSource(...);
     –   SetIndices(…);
     –   SetRenderState(...);
     –   DrawIndexedPrimitive(…);
• We have seen how DirectX has developed
• We have seen the architecture of a game loop
• We have looked at the basic framework of a
  Direct3D program
• Next week: DirectX Set-up and How basic
  primitives are coloured and drawn.

                             Create a Window
•   The first thing any Windows application must do when it is executed is create an
    application window to display to the user.
•   The following sample code performs window initialisation.
•   { // Register the window class.

•   WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL),
    NULL, NULL, NULL, NULL, "D3D Example", NULL };
•   RegisterClassEx( &wc );

•   // Create the application's window.
•    HWND hWnd = CreateWindow( "D3D Example", "D3D Example 01: CreateDevice",
    WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, GetDesktopWindow(), NULL, wc.hInstance, NULL );

•   The code is standard Windows programming. The example starts by defining and registering a window
    class called "D3D Example." After the class is registered, the sample code creates a basic top-level
    window that uses the registered class, with a client area of 300 pixels wide by 300 pixels tall. This
    window has no menu or child windows.

•   The example uses the WS_OVERLAPPEDWINDOW window style to create a window that includes
    Minimize, Maximize, and Close buttons common to windowed applications.

•   Once the window is created, the code calls standard Microsoft Win32 functions to display and 25
    update the window.
                     Initialising Direct3D
•   After you create an application window, you are ready to initialise the Direct3D object
    that you will use to render the scene.
•   This process includes creating a Direct3D object, setting the presentation parameters,
    and finally creating the Direct3D device.
•   After creating a Direct3D object, you can use the IDirect3D9::CreateDevice method to
    create a Direct3D device. You can also use the Direct3D object to enumerate devices,
    types, modes, and so on.
•   The code fragment below creates a Direct3D object with the Direct3DCreate9 function.

•   if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL;

•   The only parameter passed to Direct3DCreate9 should always be
•   This informs Direct3D that the correct header files are being used. This value is
    incremented whenever a header or other change would require applications to be
    rebuilt. If the version does not match, Direct3DCreate9 will fail.

                   Initialising Direct3D
•   The next step is to retrieve the current display mode by using the
    IDirect3D9::GetAdapterDisplayMode method as shown in the code fragment below.
•   if( FAILED( g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) ) return E_FAIL;

•   The Format member of the D3DDISPLAYMODE structure will be used when creating
    the Direct3D device. To run in windowed mode, the Format member is used to create
    a back buffer that matches the adapter's current mode.
•   By filling in the fields of the D3DPRESENT_PARAMETERS you can specify how you
    want your 3-D application to behave.
•   ZeroMemory( &d3dpp, sizeof(d3dpp) );
•   d3dpp.Windowed = TRUE;
•   d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
•   d3dpp.BackBufferFormat = d3ddm.Format;

•   The CreateDevice example sets its Windowed member to TRUE, its SwapEffect
    member to D3DSWAPEFFECT_DISCARD, and its BackBufferFormat member to
    d3ddm.Format.                                                             27
            Initialising Direct3D
•The final step is to use the IDirect3D9::CreateDevice method to create the
Direct3D device, as illustrated in the following code example.


•The code example creates the device with the default adapter by using the

•In most cases, the system will have only a single adapter, unless it has multiple
graphics hardware cards installed. Indicate that you prefer a hardware device over a
software device by specifying D3DDEVTYPE_HAL for the DeviceType parameter.

•This code sample uses D3DCREATE_SOFTWARE_VERTEXPROCESSING to tell
the system to use software vertex processing.

•Note that if you tell the system to use hardware vertex processing by specifying
performance gain on video cards that support hardware vertex processing.
  Handling System Messages
•After you have created the application window and initialised Direct3D, you are
ready to render the scene.
•In most cases, Windows applications monitor system messages in their message
loop, and they render frames whenever no messages are in the queue.
•However, the CreateDevice example waits until a WM_PAINT message is in the
queue, telling the application that it needs to redraw all or part of its window.

•// The message loop.
•MSG msg; while( GetMessage( &msg, NULL, 0, 0 ) ) { TranslateMessage( &msg ); DispatchMessage(
&msg ); }

•Each time the loop runs, DispatchMessage calls MsgProc, which handles
messages in the queue. When WM_PAINT is queued, the application calls Render,
the application-defined function that will redraw the window. Then the Microsoft
Win32 function ValidateRect is called to validate the entire client area.
•The sample code for the message-handling function is shown below.
•LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
•{ switch( msg )
  – { case WM_DESTROY: PostQuitMessage( 0 );
  – return 0;
  – case WM_PAINT: Render();
  – ValidateRect( hWnd, NULL ); return 0; }                                              29
•return DefWindowProc( hWnd, msg, wParam, lParam ); }
    Rendering and Displaying a Scene
•To render and display the scene, the sample code in this step clears the back buffer to a
blue colour, transfers the contents of the back buffer to the front buffer, and presents the
front buffer to the screen.
•To clear a scene, call the IDirect3DDevice9::Clear method.
•// Clear the back buffer to a blue
•color g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );

•The first two parameters accepted by Clear inform Direct3D of the size and address of the array of
rectangles to be cleared. The array of rectangles describes the areas on the render target surface to
be cleared.
•In most cases, you use a single rectangle that covers the entire rendering target.
•You do this by setting the first parameter to 0 and the second parameter to NULL.
•The third parameter determines the method's behaviour. You can specify a flag to clear a render-
target surface, an associated depth buffer, the stencil buffer, or any combination of the three.

•This example does not use a depth buffer, so D3DCLEAR_TARGET is the only flag used.
•The last three parameters are set to reflect clearing values for the render target, depth buffer, and
stencil buffer.
•The CreateDevice example sets the clear colour for the render target surface to blue
•The final two parameters are ignored by the Clear method because the corresponding flags are not
present.                                                                                           30
      Rendering and Displaying a Scene
•After clearing the viewport, the CreateDevice sample project informs Direct3D that rendering
will begin, then it signals that rendering is complete, as shown in the following code fragment.
•// Begin the scene.
•// Rendering of scene objects happens here.
•// End the scene.
•The IDirect3DDevice9::BeginScene and IDirect3DDevice9::EndScene methods signal to
the system when rendering is beginning or is complete.
•You can call rendering methods only between calls to these methods. Even if rendering
methods fail, you must call EndScene before calling BeginScene again.
•After rendering the scene, you display it by using the IDirect3DDevice9::Present method.
•g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
•The first two parameters accepted by Present are a source rectangle and destination
rectangle. The sample code in this step presents the entire back buffer to the front buffer by
setting these two parameters to NULL.
•The third parameter sets the destination window for this presentation. Because this parameter
is set to NULL, the hWndDeviceWindow member of D3DPRESENT_PARAMETERS is used.                31
The fourth parameter is the DirtyRegion parameter and in most cases should be set to NULL.
                        Shutting Down
•Shutting down a DirectX application not only means that you destroy the
application window, but you also deallocate any DirectX objects your application
uses, and you invalidate the pointers to them.

•The CreateDevice example calls Cleanup, an application-defined function to
handle this when it receives a WM_DESTROY message.

•VOID Cleanup() { if( g_pd3dDevice != NULL) g_pd3dDevice->Release();
•if( g_pD3D != NULL) g_pD3D->Release(); }

•The preceding function deallocates the DirectX objects it uses by calling the
IUnknown::Release methods for each object. Because this example follows COM
rules, the reference count for most objects should become zero and should be
automatically removed from memory.
•In addition to shutdown, there are times during normal execution—such as when
the user changes the desktop resolution or colour depth—when you might need to
destroy and re-create the Direct3D objects in use.
•Therefore it is a good idea to keep your application's cleanup code in one place,
which can be called when the need arises.

To top