E-Book

E-Book

Advanced 3D Game Programming Using DirectX 9.0

About the Book
Why was this book written?

I've learned from many amazingly brilliant people, covered a lot of difficult ground, and asked a lot of dumb questions.

One thing that I've found is that the game development industry is all about sharing. If everyone shares, everyone

knows more stuff, and the net knowledge of the industry increases. This is a good thing because then we all get to play

better games. No one person could discover all the principles behind computer graphics and game programming

themselves, and no one can learn in a vacuum. People took the time to share what they learned with me, and now I'm

taking the time to share what I've learned with you.

8

Who should read this book?

This book was intended specifically for people who know how to program already but have taken only rudimentary

stabs at graphics/game programming or never taken any stab at all, such as programmers in another field or college

students looking to embark on some side projects.

9

Who should not read this book?

This book was not designed for beginners. I'm not trying to sound arrogant or anything; I'm sure a beginner will be able

to trudge through this book if he or she feels up to it. However, since I'm so constrained for space, often- times I need to

breeze past certain concepts (such as inheritance in C++). If you've never programmed before, you'll have an

exceedingly difficult time with this book.

10

What are the requirements for using the code?

The code was written in C++, using Microsoft Visual C++ 6.0. The .DSPs and .DSWs are provided on the

downloadable files (http://www.wordware.com/files/dx9); the .DSPs will work with versions previous to 6.0, and the

.DSWs will work with 6.0 and up. If you choose to use a different compiler, getting the source code to work should be a

fairly trivial task. I specifically wrote this code to use as little non-standard C++ as possible (as far as I know, the only

non-standard C++ I use is nameless structures within unions).

11

Why use Windows? Why not use Linux?

I chose to use Win32 as the API environment because 90 percent of computer users currently work on Windows.

Win32 is not an easy API to understand, especially after using DOS coding conventions. It isn't terribly elegant either,

but I suppose it could be worse. I could choose other platforms to work on, but doing so reduces my target audience by

a factor of nine or more.

12

Why use Direct3D? Why not use OpenGL?

For those of you who have never used it, OpenGL is another graphics API. Silicon Graphics designed it in the early

'90s for use on their high-end graphics workstations. It has been ported to countless platforms and operating systems.

Outside of the games industry in areas like simulation and academic research, OpenGL is the de facto standard for

doing computer graphics. It is a simple, elegant, and fast API. Check out http://www.opengl.org for more information.

But it isn't perfect. First of all, OpenGL has a large amount of functionality in it. Making the interface so simple requires

that the implementation take care of a lot of ugly details to make sure everything works correctly. Because of the way

drivers are implemented, each company that makes a 3D card has to support the entire OpenGL feature set in order to

have a fully compliant OpenGL driver. These drivers are extremely difficult to implement correctly, and the performance

on equal hardware can vary wildly based on driver quality. In addition, DirectX has the added advantage of being able

to move quickly to accommodate new hardware features. DirectX is controlled by Microsoft (which can be a good or

bad thing, depending on your view of it), while OpenGL extensions need to be deliberated by committees.

My initial hope was to have two versions of the source code—one for Windows and Direct3D and the other for Linux

and OpenGL. This ended up not being possible, so I had to choose one or the other; I chose Direct3D.

13

Why use C++? Why not C, ASM, or Java?

I had a few other language choices that I was kicking around when planning this book. Although there are acolytes out

there for Delphi, VB, and even C#, the only languages I seriously considered were C++, Java, and C. Java is designed

by Sun Microsystems and an inherently object-oriented language, with some high-level language features like garbage

collection. C is about as low level as programming gets without dipping into assembly. It has very few if any high-level

constructs and doesn't abstract anything away from the programmer.

C++ is an interesting language because it essentially sits directly between the functionality of the other two languages.

C++ supports COM better than C does (this is more thoroughly discussed in Chapter 1). Also, class systems and

operator overloading generally make code easier to read (although, of course, any good thing can and will be abused).

Java, although very cool, is an interpreted language. Every year this seems to be less important: JIT compilation gets

faster and more grunt work is handed off to the APIs. However, I felt C++ would be a better fit for the book. Java is still

a very young language and is still going through a lot of change.

14

Do I need a 3D accelerator?

That depends. Technically, no, you can get by without any accelerator at all, using Direct3D's software rasterizer.

However, it's extremely slow, far from real time for anything but trivially simple scenes. It's almost impossible to buy a

computer these days without some sort of 3D acceleration, and an accelerator capable of handling all the code in this

book can be purchased for under $100.

15

How hardcore is the C++ in this book?

Some people see C++ as a divine blade to smite the wicked. They take control of template classes the likes of which

you have never seen. They overload the iostream operators for all of their classes. They see multiple inheritance as a

hellspawn of Satan himself. I see C++ as a tool. The more esoteric features of the language (such as the iostream

library) I don't use at all. Less esoteric features (like multiple inheritance) I use when it makes sense. Having a coding

style you stick to is invaluable. The code for this book was written over an eleven-month period, plus another three for

the revision, but I can pick up the code I wrote at the beginning and still grok it because I commented and used some

good conventions. If I can understand it, hopefully you can too.

16

What are the coding conventions used in the source?

One of the greatest books I've ever read on programming was Code Complete (Microsoft Press). It's a handbook on

how to program well (not just how to program). Nuances like the length of variable names, design of subroutines, and

length of files are covered in detail in this book; I strongly encourage anyone who wants to become a great

programmer to pick it up. You may notice that some of the conventions I use in this book are similar to the conventions

described in Code Complete; some of them are borrowed from the great game programmers like John Carmack, and

some of them are borrowed from source in DirectX, MFC, and Win32.

I've tried really hard to make the code in this book accessible to everyone. I comment anything I think is unclear, I strive

for good choice in variable names, and I try to make my code look clean while still trying to be fast. Of course, I can't

please everyone. Assuredly, there are some C++ coding standards I'm probably not following correctly. There are

some pieces of code that would get much faster with a little obfuscation.

If you've never used C++ before or are new to programming, this book is going to be extremely hard to digest. A good

discussion on programming essentials and the C++ language is C++ Primer (Lippman et al.; Addison-Wesley

Publishing).

17

Class/Structure Names

MFC names its classes with a prefixed C. As an example, a class that represents the functionality of a button is called

CButton. I like this fine, but due to namespace clashing, I instead prefix my own classes with a lowercase c for classes,

a lowercase s for structs, a lowercase i for interfaces, and a lowercase e for enumerations (cButton or sButton).

There is one notable exception. While most classes are intended to hide functionality away and act as components,

there are a few classes/structures that are intended to be instantiated as basic primitives. So for basic mathematic

primitives like points and matrices, I have no prefix, and I postfix with the dimension of the primitive (2D points are

point2, 3D points are point3, etc.). This is to allow them to have the same look and feel as their closest conceptual

neighbor, float. For the same reason, all of the mathematic primitives have many overloaded operators to simplify

math-laden code.

18

Variable Names

Semi-long variable names are a good thing. They make your code self- commenting. One needs to be careful though:

Make them too long, and they distract from both the code itself and the process of writing it.

I use short variables very sporadically; int i, j, k pop up a lot in my code for loops and whatnot, but besides that I strive

to give meaningful names to the variables I use. Usually, this means that they have more than one word in them. The

system I use specifies lowercase for the first word and initial cap for each word after that, with no underscores (an

example would be int numObjects). If the last letter of a word is a capital letter, an underscore is placed to separate it

from the next word (example: class cD3D_App).

A popular nomenclature for variables is Hungarian notation, which we touch on in Chapter 1. I'm not hardcore about it,

but generally my floats are prefixed with "f," my ints with "i," and my pointers with "p" (examples: float fTimer; int

iStringSize; char* pBuffer). Note that the prefix counts as the first word, making all words after it caps. (I find pBuffer

much more readable than pbuffer.)

I also use prefixes to define special qualities of variables. Global variables are preceded with a "g_" (an example would

be int g_hInstance); static variables are preceded with an "s_" (static float s_fTimer); and member variables of classes

are preceded with an "m_" (int m_iNumElements).

19

Companion Files

The companion files can be downloaded from the following web site:

http://www.wordware.com/files/dx9

These files include the source code discussed in the book along with the game Mobots Attack!. Each chapter (and the

game) has its own workspace so you can use them independently of each other.

20