2D Programming in a 3D World
June 29, 2001 Page 1 of 3
Has the age of so-called "2D" programming drawn to a close? Certainly for some genres the twilight has come -- a designer suggesting a side-scrolling adventure game would likely have just recovered from a long coma. But for other categories, a 3D environment is not an easy fit. Titles such as Sid Meier's Alpha Centauri (and his Civilization series), the Age of Empires games, Talonsoft's Operational Art of War series, and the entire Red Alert series all use a 2D interface and map to good effect. That is not to say everything must look flat, for instance Age of Empires 2 and Red Alert 2 make use of detailed graphics for units, buildings, and landscape that have the appearance of depth. However, this does not change the fact that they are still 2D game engines. More than that, it can be strongly argued that a move to a "full 3D" environment would reduce the quality of gameplay on these products. For instance, Sierra's Ground Control could be considered the 3D evolution of the RTS concept, yet it was Red Alert 2 that beat it out to win IGN's recent Readers Choice Award for Best Strategy Game of 2000.
Having determined that the opportunities for a 2D engine are still alive and well, PC programmers are currently facing three problems: first, Microsoft's recently released DirectX update has focused all its new API development into the area of 3D support; next, game players are clamoring for higher graphics quality and special effects; and finally, there is a substantial learning curve for a 2D programmer to move to the world of 3D graphics APIs such as Direct3D and OpenGL. Yet the newest release of Microsoft's DirectX, version 8, offers some features to help make the transition a bit easier.
A Brief Overview of Traditional 2D Methods
The king of 2D graphics concepts is the sprite. At its very simplest, a 2D engine is capable of drawing a background image and then drawing individual graphic objects -- sprites -- onto that image. The use of color-keying allows a specific color in a sprite to be considered transparent, which allows sprites to be any irregular shape. And the use of a series of sprites to represent an object, for instance a number of different facings of a unit, allow the simulation of animation and action when they are drawn in sequence. The fundamental programming process for 2D graphics is the blit -- bit block transfer -- which is used to move the bit image of a sprite onto the display area. Finally, to provide a smooth transition of the display from frame to frame, graphics operations (primarily blits) are usually done to a back buffer, which is basically a working copy of the screen area. Once the frame is complete, the back buffer is flipped to the display area (front buffer), and the next frame begins from scratch. Almost everything else in 2D graphics is built on these base concepts.
In DirectX, Microsoft provided a capable (but sometimes limited) interface for 2D graphics which they called DirectDraw. This API provided all the basics that a 2D engine required. A DIRECTDRAWSURFACE is used to represent both raw-data graphic surfaces (filled with background images or sprites) and the primary display surface (front and back buffers). Most of these surfaces could be in either video memory or system memory (with the exception of the active front buffer of the display, which is of course always in video memory). The DirectDraw Blt() command is used to move images or portions of images around between surfaces. While there is not any specific support for sprites as a unique object in DirectX, it is a trivial matter to create a library to split one large surface into an array of rectangular cells for use as sprite objects. Take a look at some of the data files on disk used by many commercial games and you'll find these graphic "template" files of object sprites.
The DirectDraw Blt() function handles color keying and also provides support for a few more advanced options such as mirroring, stretching, and shrinking of bitmaps. These features, however, are often driver-dependent and are supported to different extents on different video hardware, providing inconsistent results if used. A simplified code snippet of drawing a frame in DirectDraw is provided in Listing 1.
The entire Red Alert series all use a 2D interface and map to good effect. That is not to say everything must look flat, for instance, Red Alert 2 makes use of detailed graphics for units, buildings, and landscape that have the appearance of depth.
Changes in DirectX 8
With the release of DirectX 8, Microsoft made some significanet changes in the design and implementation of the graphics engine. They replaced the separate DirectDraw and Direct3D components of DirectX 7 with a new component officially called "DirectX Graphics." It does not take long, however, to notice that all the focus in this new component is on 3D functionality, and DirectX Graphics is often interchangeably called "Direct3D 8." The interfaces of DirectX Graphics are not derived from the interfaces of previous DirectX versions, but are an entirely new design. As in all releases of DirectX, older interfaces are available -- meaning that you can install DirectX 8 but still program for the older version 7 (or earlier) functions. And this is, in fact, the oft-suggested solution when DirectDraw programmers take a look at the new API in version 8. To quote from Microsoft's DirectX FAQ, posted February 1, 2001:
"What happened to DirectDraw? Much of the functionality of DirectDraw has now been subsumed into the new Direct3D 8 interfaces. Developers working on purely 2D applications may wish to continue using the old DirectX 7 interfaces. Developers working on 3D applications with some 2D elements are encouraged to use Direct3D alternatives (point sprites and billboard textures, for example) as this will result in improved performance and flexibility."
While this is the official line, there are a few problems with this answer that cause confusion among 2D programmers looking to port their code to the latest API. First, it is misleading to say that "much of the functionality of DirectDraw" has been included in the new Direct3D 8 (possibly explaining their use of the uncommon word "subsumed"). Most significantly, there is no longer a blit command or equivalent function. Early in the beta process of DirectX 8, developers looked at new functions such as CopyRects() to provide some blit features but these lack necessary support for important capabilities such as color keying. Point Sprites, a new feature in DirectX 8, are technically quite limited and do not provide required functionality. That leaves "billboard textures," a concept with little information in the DirectX SDK and no provided examples for a 2D programmer to follow.
There is, however, the carrot at the end of the stick: "improved performance and flexibility." Clearly DirectX 8 is designed to get the most out of modern video cards, utilizing all the hardware acceleration available. Scaling, rotation, and most importantly alpha blending are all standard features with 3D graphics, and all hardware-supported. Alpha blending was defined in the DirectDraw Blt() function, but listed as "Feature Unsupported in DirectX 7," leaving programmers wishing to use this feature quite unsatisfied. So, how can a 2D programmer take advantage of these DirectX 8 features?
Page 1 of 3