Home | Computers & Technology

Introduction to 3D Game Programming with DirectX 9.0

Posted By: | Posted On: | Article ID:

Introduction
This book is an introduction to programming interactive 3D computer graphics using DirectX 9.0, with an emphasis on game development. It teaches you the fundamentals of Direct3D, after which you will be able to go on to learn and apply more advanced techniques. Assumingly, since you have this book in your hands, you have a rough idea of what DirectX is about. From a developer's perspective, DirectX is a set of APIs (application programming interfaces) for developing multimedia applications on the Windows platform. In this book we are concerned with a particular DirectX subset, namely Direct3D. As the name implies, Direct3D is the API used for developing 3D applications.

This book is divided into four main parts. Part I explains the mathematical tools that will be used throughout this book. Part II covers elementary 3D techniques, such as lighting, texturing, alpha blending, and stenciling. Part III is largely about using Direct3D to implement a variety of interesting techniques and applications, such as picking, terrain rendering, particle systems, a flexible virtual camera, and loading and rendering 3D models (XFiles). The theme of Part IV is vertex and pixel shaders, including the effects framework and the new (to DirectX 9.0) High-Level Shading Language. The present and future of 3D game programming is the use of shaders, and by dedicating an entire part of the book to shaders, we have an up-to-date and relevant book on modern graphics programming.

For the beginner, this book is best read front to back. The chapters have been organized so that the difficulty increases progressively with each chapter. In this way, there are no sudden jumps in complexity, leaving the reader lost. In general, for a particular chapter we will use the techniques and concepts previously developed. Therefore, it is important that you have mastered the material of a chapter before continuing. Experienced readers can pick the chapters of interest.

Finally, you may wonder what kinds of games you can develop after reading this book. The answer to that question is best obtained by skimming through this book and seeing the types of applications that are developed. From that you should be able to visualize the types of games that can be developed based on the techniques taught in this book and some of your own ingenuity.

Prerequisites
This book is designed to be an introductory level textbook. However, that does not imply that it is easy for people with no programming experience. Readers are expected to be comfortable with algebra, trigonometry, their development environment (e.g., Visual Studio), C++, and fundamental data structures such as arrays and lists. Being familiar with Windows programming is also helpful but not imperative; refer to Appendix A for an introduction to Windows programming.

Required Development Tools
This book uses C++ as its programming language for the sample programs. To quote the DirectX documentation, "DirectX 9.0 supports only Microsoft Visual C++ 6.0 and later." Therefore, as of publication, in order to write C++ applications using DirectX 9.0, you need either Visual C++ (VC ++) 6.0 or VC ++ 7.0 (.NET).

Note The sample code for this book was compiled and built using VC++ 7.0. For the most part, it should compile and build on VC++ 6.0 also, but be aware of the following difference. In VC++ 7.0 the following will compile and is legal because the variable cnt is considered to be local to the for loop.

int main()
{
for(int cnt = 0; cnt < 10; cnt++)
{
std::cout << "hello" << std::end1;
}

for(int cnt = 0; cnt < 10; cnt++)
{
std::cout << "hello" << std::end1;
}
return 0;
}

However, in VC++ 6.0 this will not compile. It gives the error message error C2374: 'cnt' : redefinition; multiple initialization because in VC++ 6.0 the variable cnt is not treated as being local to the for loop. Therefore, when porting to VC++ 6.0, you may need to make some minor changes to get it to compile due to this difference.

Recommended Hardware
The following hardware recommendations are if you wish to be able to run the sample programs at an acceptable frame rate; all the samples can be run using the REF device, which emulates Direct3D functionality in software. Because things are being emulated in software, they run very slow. We discuss the REF more in Chapter 1.

The sample programs in Part II of this book are fairly basic and should run on low-end cards, such as the Riva TNT or an equivalent graphics card. The sample programs in Part III push more geometry and use some newer features, such as point sprites. For these samples we recommend a graphics card at the level of a GeForce2. The sample programs in Part IV use vertex and pixel shaders; therefore, to run these programs in real time, you will need a graphics card that supports shaders such as the GeForce3.



1.4 Initializing Direct3D
The following subsections show how to initialize Direct3D. The process of initializing Direct3D can be broken down into the following steps:

Acquire a pointer to an IDirect3D9 interface. This interface is used for finding out information about the physical hardware devices on a system and creating the IDirect3DDevice9 interface, which is our C++ object that represents the physical hardware device we use for displaying 3D graphics.

Check the device capabilities (D3DCAPS9) to see if the primary display adapter (primary graphics card) supports hardware vertex processing or not. We need to know if it can in order to create the IDirect3DDevice9 interface.

Initialize an instance of the D3DPRESENT_PARAMETERS structure. This structure consists of a number of data members that allow us to specify the characteristics of the IDirect3DDevice9 interface that we are going to create.

Create the IDirect3DDevice9 object based on an initialized D3DPRESENT_PARAMETERS structure. As said, the IDirect3DDevice9 object is our C++ object that represents the physical hardware device that we use for displaying 3D graphics.

Keep in mind that in this book we use the primary display adapter for drawing 3D graphics. If your system only has one graphics card, that is the primary display adapter. If you have more than one graphics card, then the card you are presently using is the primary display adapter (e.g., the one displaying the Windows desktop, etc.).

1.4.1 Acquiring an IDirect3D9 Interface
Initialization of Direct3D begins by acquiring a pointer to an IDirect3D9 interface. This is easily done using a special Direct3D function, as the following lines of code show:

IDirect3D9* _d3d9;
_d3d9 = Direct3DCreate9(D3D_SDK_VERSION);

The single parameter to Direct3DCreate9 should always be D3D_SDK_VERSION, which guarantees that the application is built against the correct header files. If this function fails, it returns a null pointer.

The IDirect3D9 object is used for two things: device enumeration and creating the IDirect3DDevice9 object. Device enumeration refers to finding out the capabilities, display modes, formats, and other information about each graphics device available on the system. For instance, to create the IDirect3DDevice9 object that represents a physical device, we need to create it using a configuration of display modes and formats that the physical device supports. To find such a working configuration, we must use the IDirect3D9 enumeration methods.

However, because device enumeration can be quite an involved task and we want to get up and running as quickly as possible with Direct3D, we have elected not to perform any enumeration, except for one check as shown in the next section. In order to safely skip enumeration, we have chosen a "safe" configuration that almost all hardware devices will support.

1.4.2 Checking for Hardware Vertex Processing
When we create an IDirect3DDevice9 object to represent the primary display adapter, we must specify the type of vertex processing to use with it. We want to use hardware vertex processing if we can, but because not all cards support hardware vertex processing, we must check if the card supports it first.

To do this, we must first initialize a D3DCAPS9 instance based on the capabilities of the primary display adapter. We use the following method:

HRESULT IDirect3D9::GetDeviceCaps(
UINT Adapter,
D3DDEVTYPE DeviceType,
D3DCAPS9 *pCaps
);

Adapter—Specifies the physical display adapter that we are going to get the capabilities of

DeviceType—Specifies the device type to use (e.g., hardware device (D3DDEVTYPE_HAL) or software device (D3DDEVTYPE REF))

pCaps—Returns the initialized capabilities structure

Then we can check the capabilities, as we did in section 1.3.8. The following code snippet illustrates this:

// Fill D3DCAPS9 structure with the capabilities of the
// primary display adapter.

D3DCAPS9 caps;
d3d9->GetDeviceCaps(
D3DADAPTER_DEFAULT, // Denotes primary display adapter.
deviceType, // Specifies the device type, usually D3DDEVTYPE HAL.
&caps); // Return filled D3DCAPS9 structure that contains
// the capabilities of the primary display adapter.

// Can we use hardware vertex processing?
int vp = 0;
if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
// yes, save in 'vp' the fact that hardware vertex
// processing is supported.
vp = D3DCREATE HARDWARE VERTEXPROCESSING;
}
else
{
// no, save in 'vp' the fact that we must use software
// vertex processing.
vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}

Observe that we save the type of vertex processing that we are going to use in the variable vp. This is because we are going to need to specify the vertex processing type that we are going to use later on when we create the IDirect3DDevice9 object.

Note The identifiers D3DCREATE_HARDWARE_VERTEXPROCESSING and D3DCREATE_SOFTWARE_VERTEXPROCESSING are just predefined values that denote hardware vertex processing and software vertex processing, respectively.

Tip When developing applications and using new, special, or advanced features (in other words, features that are not widely supported), it is recommended that you always check the device capabilities (D3DCAPS9) to see if the device supports the particular feature before using it. Never assume that a feature is available. Also, be aware that the sample applications in this book generally do not follow this advice — we generally do not check device capabilities.

Note If a particular sample application isn't working, it is most likely because your hardware doesn't support the feature that the sample is using; try switching to the REF device.

1.4.3 Filling Out the D3DPRESENT_PARAMETERS Structure
The next step in the initialization process is to fill out an instance of the D3DPRESENT_PARAMETERS structure. This structure is used to specify some of the characteristics of the IDirect3DDevice9 object that we are going to create, and is defined as:

typedef struct _D3DPRESENT_PARAMETERS_ {
UINT BackBufferWidth;
UINT BackBufferHeight;
D3DFORMAT BackBufferFormat;
UINT BackBufferCount;
D3DMULTISAMPLE TYPE MultiSampleType;
DWORD MultiSampleQuality;
D3DSWAPEFFECT SwapEffect;
HWND hDeviceWindow;
BOOL Windowed;
BOOL EnableAutoDepthStencil;
D3DFORMAT AutoDepthStencilFormat;
DWORD Flags;
UINT FullScreen_RefreshRateInHz;
UINT PresentationInterval;
} D3DPRESENT_PARAMETERS;

Note In the following data member descriptions for the D3DPRESENT_PARAMETERS structure, we only cover the flags and options that we feel are the most important to a beginner at this point.

For a description of further flags, options, and configurations, we refer you to the SDK documentation.

BackBufferWidth—Width of the back buffer surface in pixels

BackBufferHeight—Height of the back buffer surface in pixels

BackBufferFormat—Pixel format of the back buffer (e.g., 32-bit pixel format: D3DFMT_A8R8G8B8)

BackBufferCount—The number of back buffers to use. Usually we specify "1" to indicate that we want only one back buffer.

MultiSampleType—The type of multisampling to use with the back buffer. See SDK documentation for details.

MultiSampleQuality—The quality level of multisampling. See SDK documentation for details.

SwapEffect—A member of the D3DSWAPEFFECT enumerated type that specifies how the buffers in the flipping chain will be swapped. Specifying D3DSWAPEFFECT_DISCARD is the most efficient.

hDeviceWindow—The window handle associated with the device. Specify the application window onto which you want to draw.

Windowed—Specify true to run in windowed mode or false for full-screen mode.

EnableAutoDepthStencil—Set to true to have Direct3D create and maintain the depth/stencil buffer automatically.

AutoDepthStencilFormat—The format of the depth/stencil buffer (e.g., 24-bit depth with 8 bits reserved for the stencil buffer: D3DFMT_D24S8).

Flags—Some additional characteristics. Specify zero (no flags) or a member of the D3DPRESENTFLAG set. See the documentation for a complete list of valid flags. Two common ones are:

D3DPRESENTFLAG_LOCKABLE_BACKBUFFER—Specifies that the back buffer can be locked. Note that using a lockable back buffer can degrade performance.

D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL—Specifies that the depth/stencil buffer will be discarded after the next back buffer is presented. By "discard" we mean just that—the depth/stencil buffer memory will be discarded or invalid. This can improve performance.

FullScreen_RefreshRateInHz—Refresh rate; use the default refresh rate by specifying D3DPRESENT_RATE_DEFAULT.

PresentationInterval—A member of the D3DPRESENT set. See the documentation for a complete list of valid intervals. Two common ones are:

D3DPRESENT_INTERVAL_IMMEDIATE—Presents immediately

D3DPRESENT_INTERVAL_DEFAULT—Direct3D will choose the present rate. Usually this is equal to the refresh rate.

An example of filling this structure out is:

D3DPRESENT_PARAMETERS d3dpp;
d3dpp.BackBufferWidth = 800;
d3dpp.BackBufferHeight = 600;
d3dpp.BackBufferFormat = D3DFMT A8R8G8B8; //pixel format
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = D3DMULTISAMPLE NONE;
d3dpp.MultiSampleQuality = 0;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hwnd;
d3dpp.Windowed = false; // fullscreen
d3dpp.EnableAutoDepthStencil = true;
d3dpp.AutoDepthStencilFormat = D3DFMT D24S8; // depth format
d3dpp.Flags = 0;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

1.4.4 Creating the IDirect3DDevice9 Interface
With the D3DPRESENT_PARAMETERS filled out, we can create the IDirect3DDevice9 object with the following method:

HRESULT IDirect3D9::CreateDevice(
UINT Adapter,
D3DDEVTYPE DeviceType,
HWND hFocusWindow,
DWORD BehaviorFlags,
D3DPRESENT_PARAMETERS *pPresentationParameters,
IDirect3DDevice9** ppReturnedDeviceInterface
);

Adapter—Specifies the physical display adapter that we want the created IDirect3DDevice9 object to represent

DeviceType—Specifies the device type to use (e.g., hardware device (D3DDEVTYPE_HAL) or software device (D3DDEVTYPE_REF))

hFocusWindow—Handle to the window that the device will be associated with. This is typically the window that the device will draw onto, and for our purposes it is the same handle that we specify for the data member d3dpp. hDeviceWindow of the D3DPRESENT_PARAMETERS structure.

BehaviorFlags—Specify either D3DCREATE_HARDWARE_VERTEXPROCESSING or D3DCREATE_SOFTWARE_VERTEXPROCESSING for this parameter

pPresentationParameters—Specifies an initialized D3DPRESENT_PARAMETERS instance that defines some of the characteristics of the device

ppReturnedDeviceInterface—Returns the created device

Example call:

IDirect3DDevice9* device = 0;
hr = d3d9->CreateDevice(
D3DADAPTER_DEFAULT, // primary adapter
D3DDEVTYPE HAL, // device type
hwnd, // window associated with device
D3DCREATE_HARDWARE_VERTEXPROCESSING, // vertex processing type
&d3dpp, // present parameters
&device); // returned created device

if( FAILED(hr) )
{
::MessageBox(0, "CreateDevice() - FAILED", 0, 0);
return 0;
}

 

Article Source: http://www.articlecell.com

About The Author
John Aylesbury




Please Rate this Article     
Not yet Rated


 


 

ArticleCell.com » Copyright © 2006 - 2007
Terms of Service | Submission Guidelines | Contact Us | Link to Us | Privacy Policy | About Us

Bridgestone J33R 460CC Driver | J36 Cavity Back Irons | Bridgestone Golf

Powered by Article Dashboard