Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (11.88 MB, 1,060 trang )
TeamLRN
ViewportLeft and ViewportTop should be set to zero for full screen windows, or should contain the
top left coordinates of the view window if you only wish to render to a view port that covers part of the
screen.
The projection window coordinates range from –1 to +1 in both the x and y dimensions and thus the
window is square (2x2 in size). However, monitor screens are generally not square. Most are
rectangular (usually wider than they are higher). This is also true for the most common video modes:
800 x 600, 640 x 480, 1024 x 768. These are all video modes that have more pixels horizontally than
they do vertically. This presents us with a problem. Suppose we have a polygon in front of the camera
that is a perfect square. This will be projected onto the projection window as a perfect square also.
However, when the projection window coordinates are mapped to screen coordinates, they will be
stretched to take up the extra width of the video mode. This means that the user of your application will
see the square as a rectangle (Fig 1.44).
Figure 1.44
In order to counter this unwanted effect we will set a different FOV in the X dimension of our matrix
(m11). By increasing the FOV in the X dimension, we scale the input x values in our projection matrix
down. This means a square in camera space will be squashed in X onto the projection window such
that when the projection window is stretched into screen coordinates, the resulting rectangle is
stretched back into a square shape (Fig 1.45).
www.gameinstitute.com Graphics Programming with DX9
Page 94 of 97
TeamLRN
Figure 1.45
If we can measure the ratio of Screen Width to Screen Height that our application is using, and set the
FOV for the x axis (m11) in our projection matrix accordingly, we get a wider FOV along the x axis.
This is logical; if the monitor is wider in the x dimension than it is in the y, we should be able to see
more in the x dimension, and therefore have a wider FOV in the x dimension. In order to correct the
problem, we must first measure the ratio of screen distortion. This ratio is nearly always referred to as
the Aspect Ratio, and can be calculated like so:
Aspect Ratio =
Width 1024 800 640
=
=
=
= 1.33333333
Height 768 600 480
Notice how the aspect ratio is the same for all the standard full screen video resolutions (1.3333333). If
you are not using a standard video mode, or are using a viewable area that is not the full screen, Width
and Height in the above equation refers to the width and height of the view in which port you are
rendering (in screen coordinates).
With this aspect ratio, we can adjust the m11 element of our matrix to correct for screen space
distortion by setting up the matrix as follows:
www.gameinstitute.com Graphics Programming with DX9
Page 95 of 97
TeamLRN
Projection Matrix with 60 Degree FOV and Aspect Ratio Correction
θ = 1.047197551
(60 Degree FOV)
θ
1 / Tan( 2 )
0
AspectRatio
θ
M =
0
1 / Tan( )
2
0
0
0
0
0
0
1
0
0
0
1
0
When we specify a FOV of 60 degrees, the FOV is only 60 degrees with respect to the Y axis. It is
60
ATAN (TAN ( ) × 1.333333) × 2 = 75.1781788 degrees with respect to the X axis.
2
Note:
In
some
source
implementations
you
might
see
Aspect
Ratio
calculated
as
Height
= 0.77777777 . These implementations will MULTIPLY element m11 with 0.77777777 instead
Width
of DIVIDING m11 by 1.33333333.
After that somewhat lengthy discussion on setting up a projection matrix, you will be glad to know that
you can set-up a projection matrix easily with a single call to a D3DX function:
D3DXMatrixPerspectiveFovLH( D3DXMATRIX* pOut, FLOAT fovY,
FLOAT zn, FLOAT zf );
FLOAT Aspect,
We pass to this function the address of a matrix that will store the final matrix, a FOV for the Y axis,
and an aspect ratio (ViewportWidth / ViewportHeight). The matrix returned will be calculated in the
way that we have just described.
The two parameters at the end of the parameter list in the above function (zn and zf) are used to
configure the 3rd column of the projection matrix to scale the Z value of the input vector into a range
that can be used by the DirectX Graphics depth buffer. We will not be using a depth buffer in our first
lab project so we can leave this discussion until the next chapter when we use DirectX Graphics to
render our geometry.
www.gameinstitute.com Graphics Programming with DX9
Page 96 of 97
TeamLRN
Conclusion
The key points from this lesson are the core processes involved in transforming objects from model
space to world space to view space to eventual screen coordinates. We also learned that 3D models are
constructed from polygons and that each polygon is made up of a number of vertices. Finally we
covered a good deal of crucial mathematical techniques that will be invaluable as we progress through
the course. At this point it is recommended that you enroll in the Game Mathematics course to continue
to reinforce this mathematics knowledge as well as learn new techniques. The two courses can now be
taken in parallel since the core math you will need for this course has been covered.
www.gameinstitute.com Graphics Programming with DX9
Page 97 of 97
TeamLRN
Workbook Chapter One:
3D Graphics Fundamentals
© 2003, eInstitute, Inc.
You may print one copy of this document for your own personal use. You agree to destroy any
worn copy prior to printing another. You may not distribute this document in paper, fax,
magnetic, electronic or other telecommunications format to anyone else.
www.gameinstitute.com 3D Graphics Programming with DX9
TeamLRN
Getting Started with DirectX Graphics
Veteran programmers, and even veteran games players, will surely remember the days when all games
ran on top of a low-level text based operating system known as DOS™. At the time, Microsoft
Windows™ had become a respectable platform to run business applications but was generally
considered a very poor choice for developing cutting edge 3D games. The problem was that the
platform isolated the programmer from the underlying graphics hardware by using a software layer
called the Graphics Device Interface (GDI). This interface contained a robust collection of 2D text and
primitive drawing functions that the developer could use to render 2D output to the screen. In some
ways this was advantageous because it meant developers did not have to concern themselves with
issues such as which chipset was used by the graphics card in the end user’s system. To the developer
it all looked the same. If you wanted to draw a rectangle, you would simply instruct GDI to draw that
rectangle. GDI would handle the interaction with the graphics hardware to produce the physical output.
The GDI was built to be stable and robust. Unfortunately this came at the cost of prohibiting the
developer direct access to the screen and video memory. This situation is generally unacceptable for
game development projects because drawing operations had to be converted by GDI into native
instructions that the graphics hardware could understand. This heavy software abstraction layer
between the developer and the hardware rendering was very slow; so slow in fact that it could not
seriously be used for modern games.
Games running through DOS had no such limitation. The graphics hardware could be controlled
directly by the programmer using low-level techniques and games could run much faster. Despite these
benefits, DOS games were a challenge. This was true not only for the developer but also for the game
player.
From the developer’s perspective, the PC had become so popular that many manufacturers produced
graphics cards, all with different chipsets, each of which often spoke different languages. This meant
developers had to make sure their games worked on many different types of hardware. There was no
standard rendering API at that time. Because each graphics card had to be uniquely programmed,
developers often had to create many different versions of drawing functions to work with the different
graphics hardware. If new hardware was released after the software application was released there was
a good chance the application would not work with that hardware. This also presented a difficulty for
the bedroom programmer (the hobbyist) because they generally did not have the budget to purchase all
of the available graphics hardware on the market to ensure that their game worked on all of them.
From the perspective of the games player, many felt it too difficult just to get a game to install
correctly. The user would often be quizzed about the chipset they were using on their graphics card
and the amount of available video memory they had. This may not sound like such a big deal to a
technical person, but many people who were not computer savvy did not really understand what all
these terms meant or even exactly what hardware they had inside their system. Software companies
had to provide extensive customer support as an added expense. This was in contrast to games
www.gameinstitute.com 3D Graphics Programming with DX9
TeamLRN
consoles such as the Super Nintendo™, where even a young child could play a game simply by
inserting a cartridge.
Microsoft realized that this problem had to be addressed if they wanted Windows to become a
dominant gaming platform. So shortly after the release of Windows 95, Microsoft released a royaltyfree multimedia development library called ‘The Game SDK’. This was essentially version 1.0 of
DirectX. The name DirectX however, was officially adopted along with version 2.0 of this SDK, likely
because it had matured into a full-blown multimedia library and was no longer limited to just games
development. Although the earlier versions of DirectX were somewhat rough around the edges, it has
matured greatly over the years. From DirectX 5 onwards, developers really started to sit up and take
notice. Now we are at version 9 of DirectX and it really is amazing how far it has come in such a short
period of time.
DirectX provided the answers to many of the problems that had plagued the development of games and
entertainment titles up until that point. First, it was designed for the Windows platform. This meant
that developers could create their games in an environment where Win32 API features (such as multithreading and user interfaces) were already available. Second, it provided a unified API, much like the
GDI had done before, but this time it was very fast. The developer no longer had to worry about what
graphics hardware the end user would be playing on, and could usually leave it up to DirectX to
communicate with the hardware correctly. This was accomplished through the use of driver
programs. Graphics cards that support DirectX (which is virtually all of them now) come with a driver
which is installed on the end user’s system. This driver is written by the card manufacturer and is a
very thin and fast software layer that takes the requests passed through various DirectX functions by
the application, and turns them into instructions that the hardware understands. This means DirectX
can talk to all graphics cards as though they are the same even when they are radically different from
one another. Drivers supplied by the card manufacturer handle the conversion into hardware specific
instructions very quickly. One of the other advantages that DirectX affords us (over the GDI) is that it
does not completely isolate us from the end user’s hardware.
DirectX also takes advantage of 3D hardware acceleration without requiring any additional code from
the developer. If you render a triangle using DirectX, and the computer running the application has a
3D accelerated graphics card, DirectX will use those features to render that triangle at high speeds. The
latest 3D hardware also accelerates 3D mathematics (which was always the domain of the CPU in the
past). This means that many graphics card can handle the thousands of mathematical calculations
needed to render a scene whilst leaving the CPU free to handle other tasks such as artificial
intelligence or other game specific tasks.
www.gameinstitute.com 3D Graphics Programming with DX9
TeamLRN
The DirectX API
DirectX is divided into several code modules or Application Programming Interfaces (APIs). Each
covers different areas of multimedia development. Some of the DirectX APIs are listed below along
with a brief description of the functionality they provide to the developer. Although this course is
primarily focused on DirectX Graphics, it is useful to have a broader picture of the entire DirectX
multimedia library:
DirectX Graphics
In older versions of DirectX, 2D and 3D operations were divided among two APIs called DirectDraw
and Direct3D respectively. From DirectX 8.0 onwards, these APIs were merged into a single API
called DirectX Graphics. Many people still refer to DirectX Graphics as Direct3D. As you will see,
most of DirectX Graphics functions and interfaces usually start with D3D (short for Direct3D) so in
many ways this makes some sense. The terms ‘Direct3D’ and ‘DirectX Graphics’ will be used
interchangeably from this point on. If we mention either of these terms it is to be assumed that we are
talking about the same API: DirectX Graphics.
DirectX Audio
The DirectX Audio API contains functionality for managing and playing audio samples and music
within your application. It includes support for three dimensional / positional audio, and also includes
support for hardware sound processing and environmental effects. DirectX Audio was previously split
into two APIs, known as DirectSound and DirectMusic but following the release of DirectX 8.0 they
have been merged into one. This API is not covered in this course.
DirectInput
The DirectInput API contains functionality to handle user-input peripherals. It provides functions for
managing and reading devices such as Joysticks, Game Pads, and Force Feedback Wheels as well as
the keyboard and the mouse. The Game Institute offers a course covering the full DirectInput API so
be sure to check out the course offerings page at www.gameinstitute.com for more information as you
continue to build out your own projects.
DirectPlay
This API provides functionality generally used in the implementation of networked multiplayer games
and similar applications. It includes support for transmitting and receiving data across many different
types of network environments, including the Internet. As with most aspects of DirectX, this API is
designed as an application layer which unifies the system used to transmit and receive data regardless
of the underlying network infrastructure. The Game Institute also provides training in this API so be
sure to check out this course when you decide to add network capability to your game projects.
DirectShow
The DirectShow API provides features which encapsulate the recording and playback of high quality
multi-media streams. This includes support for many popular formats such as MPEG, AVI, ASF and
MP3 audio files. This API is not covered in this course.
www.gameinstitute.com 3D Graphics Programming with DX9
TeamLRN
Direct Setup
This API provides you with a straightforward way to distribute and install the DirectX runtime
libraries on the end user’s machine. You may have seen this in action many times before when you
installed a new game that uses a more recent version of DirectX than the one you currently have
installed. When this is found to be the case you are often informed that you need the later version of
DirectX, after which the actual installation proceeds. This requires much more than a few file copy
operations, so you should make sure that you use this API to install DirectX on the end user machine
when your game is finally shipped. This API is not covered in this course.
Installing the DirectX9 SDK
In order to use DirectX Graphics and the D3DX utility extension, we need to set up our compiler so
that it can find the DX9 header files and the DX9 library files. We will need to include the d3d9.lib and
d3dx9.lib library files within all of the projects that make use of DirectX Graphics. We must also
include the d3dx9.h header file at the top of the source files that require their functionality (a common
header file could also be used). When using d3dx9.h we do not have to manually include in d3d9.h as
this is included automatically when including d3dx9.h.
Let us first cover setting up the DX9 SDK for your compiler. The following examples are for
Microsoft’s Visual C++ 6 compiler. If you are using a different compiler then you will have to
interpret and translate the following instructions for use with your particular system.
The first thing you will need to do is to visit the Microsoft website (www.microsoft.com) and
download the DirectX9 software development kit (SDK). This is a fairly sizable download especially
for people using 56k dial up accounts (around 200MB). If you are unable to download files this big,
Microsoft provides a means to purchase the DirectX 9 SDK on CD from their website (for a minimal
charge that basically covers postage, packaging, and shipping).
Once the file has been downloaded (or you have received the package on CD), run the setup
executable. This will install the SDK on your computer. In the following example, we have installed
the SDK in the folder “C:\DX9SDK”. If you decide to place it elsewhere on your system, you must
change the path used in the following examples to match the folder into which you decided to install it.
Once the SDK has been installed (and you have rebooted your machine) you will find that a folder has
been created (‘C:\DX9SDK’ in this example) with several sub-folders. The sub-folders of importance
are shown below:
www.gameinstitute.com 3D Graphics Programming with DX9
TeamLRN
C:\dx9sdk
Bin
The ‘Bin’ folder contains utility applications that aid in the development of DX9 applications. These
are incredibly useful tools to have at your disposal. Some worthy of mention are:
a. DXCapsViewer.exe: Allows you to see all of the DirectX features and modes supported by your
current hardware. Video modes, refresh rates, and texture blending operations are some examples.
b. DXErr.exe: Allows you to enter error codes returned by DX API functions and retrieve a
meaningful description to help you to diagnose what went wrong
c. DXTex.exe: Allows you to import bitmaps that are to be used as textures, and convert them to the
DirectX native texture format known as .DDS. You do not have to use DDS files but they can be
convenient in certain circumstances.
d. vsa.exe: Allows you to compile vertex shaders.
e. psa.exe: Allows you to compile pixel shaders.
Doc
This folder contains your lifeline to DirectX Graphics development (ok, perhaps your second lifeline,
after this course). It contains the complete reference manual for DirectX packed with hundreds of
pages of information. You will no doubt use this as a reference time and time again. Every possible
function call, interface, structure, and macro used by DirectX is explained to some degree in here.
Include
This folder contains the entire set of C++ header files that you will need to include in your project to
create a DirectX application. We will discuss shortly how to set up the search paths used by the
development environment so that the compiler automatically uses this folder when building your
project.
Libs
This folder contains all of the library files that you will need to link into your project in order to gain
access to DirectX functions and interfaces. We will show you how to set the environment up in a
moment and discuss which lib files you need to link into your project and when.
Redist
This folder contains the distributable DirectX runtime which you can ship to the end user along with
your application. The executable in this folder allows for the automated version checking and
www.gameinstitute.com 3D Graphics Programming with DX9
TeamLRN
installation of the DirectX9 runtime on the end user system. There are examples of how to use this
system correctly in the samples folder.
Samples
The samples folder is another invaluable resource when it comes to learning DirectX programming. It
contains dozens of example programs (with source code) showing how to use DirectX and all of its
features. This folder also contains precompiled binaries so that you can run the samples without being
required to build the source. This is a good way to test that DirectX9 is correctly installed to your
computer.
SDKDev
This directory contains the runtime install applications that are automatically installed with the SDK.
They are English language only and contain both debug and retail DirectX 9.0 system components.
You can switch between the retail and debug versions of the runtime via the DirectX Control Panel
component (accessible via the Windows Control Panel). You can use the debug runtime to receive
additional debug information from DirectX via the C++ IDE. If the control panel icon is not available,
try re-installing the debug runtime contained in this folder. These installers are not for redistribution,
and are designed for SDK development only.
Note: If you choose to install the debug runtimes, please make sure that you disable it via the control
panel whenever you do not require additional debug information. The debug runtimes are
significantly slower than the retail runtimes.
Setting up the Build Environment for DirectX9
Setting up the environment is easy if you are using Microsoft Visual C++ 6. If you are not using
Microsoft VC++ 6 then you will need to translate the following instructions to work with your
preferred compiler/environment.
The first thing we will do is setup the IDE so that it will search the “C:\DX9SDK\Include” folder
automatically when searching for header files. This is done via the Tools / Options menu item which
will bring up the options property sheet. Next you need to click on the Directories tab as demonstrated
below:
www.gameinstitute.com 3D Graphics Programming with DX9