Sei sulla pagina 1di 30

CSE 380 Computer Game Programming Graphics Device Management

Tennis for Two, 1958, by William Higinbotham, Brookhaven National Lab

What is a 2D game graphically speaking? Basically 2 things:


Texture rendering (images) Text rendering

Rendering textures & text is easy

Efficiently managing the data of the game is not

DirectX 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:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_m/directx/directx9m.asp

DirectX Architecture
Windows Win32 Application

Direct3D

XAudio

HEL: Hardware Emulation Layer

Software emulation

HAL: Hardware Abstraction Layer

Hardware: Audio, Video, Input, Storage

DirectX Devices
Represent hardware

Direct3D device is the graphics processor


Graphics cards can render fast So, we call DirectX methods they are implemented on the GPU What if you dont have a GPU? you cant play

Challenge to PC game programmers


Every gamer has a different machine

Different graphics cards, which means: different available screen resolutions different available color models
You want to reach a broad audience Whats the end result? a headache a lot of code devoted to dealing with these differences

Whats a color model?


A format for storing color on the graphics card

Many different formats Ex:


32 ARGB
8 bits for Alpha 8 bits for Red 8 bits for Green 8 bits for Blue

What does a GPU have?


A grid of pixels
match the current screen resolution when we force to screen it ends up on monitor

Memory for additional visual data


ex: textures

Implementations of efficient graphics processing algorithms

Strategy for creating graphics devices Pick a common resolution, ex: 1024 X 768 Pick a common color model, ex: 32 XRGB When the application starts:
check to make sure the players graphics card has these capabilities What if the player doesnt have our desired format?
have backup choices tell the player to come back when they have a better computer

Creating a D3D Graphics Device


1. Make a Direct3D object (LPDIRECT3D9) 2. Get all the available GPU display modes (D3DDISPLAYMODE) 3. Pick one and use it to fill in the setup parameters (D3DPRESENT_PARAMETERS) 4. Use parameters to create a graphics device (LPDIRECT3DDEVICE9) 5. Use the graphics device to make a sprite handler (LPD3DXSPRITE) More on using this in a minute

Setup Direct3D Methods


CreateDevice Direct3DCreate9 EnumAdapterModes GetAdapterModeCount

These can tell us about the capabilities of the GPU

Making a Direct3D Object


Lets us make other stuff
LPDIRECT3D9 d3d; d3d = Direct3DCreate9(D3D_SDK_VERSION);

How about getting the available modes?


each color mode is numbered lets look for all modes in 1-1000 range (way overkill)

Getting all display modes


vector<D3DDISPLAYMODE*> *displayOptions = new vector<D3DDISPLAYMODE*>(); int adapterCounter = 1; D3DFORMAT format; while (adapterCounter < 1000) { format = D3DFORMAT(adapterCounter); int numAdapters = d3d->GetAdapterModeCount( D3DADAPTER_DEFAULT, format); D3DDISPLAYMODE *displayModes = new D3DDISPLAYMODE[numAdapters]; for (int i = 0; i < numAdapters; i++) { d3d->EnumAdapterModes(D3DADAPTER_DEFAULT, format, i, &displayModes[i]); displayOptions->push_back(&displayModes[i]); } adapterCounter++; }

Does it have our desired format?


bool hasMode = false; vector<D3DDISPLAYMODE*>::iterator iterator; iterator = displayOptions->begin(); while ((iterator != displayOptions->end()) && !hasMode) { D3DDISPLAYMODE *testMode = (*iterator); if ((testMode->Format == DEFAULT_COLOR_MODE) && (testMode->Width == DEFAULT_SCREEN_WIDTH) && (testMode->Height == DEFAULT_SCREEN_HEIGHT)) hasMode = true; iterator++; }

Now we can make our graphics device & sprite handler

LPDIRECT3DDEVICE9 graphicsDevice; D3DPRESENT_PARAMETERS presentParameters; LPD3DXSPRITE spriteHandler; ZeroMemory(&presentParameters,sizeof(presentParameters)); presentParameters.Windowed = true; presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; presentParameters.hDeviceWindow = hWnd; presentParameters.BackBufferFormat = formatToUse; presentParameters.BackBufferWidth = screenWidthToUse; presentParameters.BackBufferHeight = screenHeightToUse; HRESULT result = d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, presentParameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &presentParameters, &graphicsDevice); result = D3DXCreateSprite(graphicsDevice, &spriteHandler);

So what?
LPD3DXSPRITE can draw 2D images

LPDIRECT3DDEVICE9 can draw text To draw text we need a LPD3DXFONT

Making a font object


LPD3DXFONT textFont; HRESULT result = D3DXCreateFont( graphicsDevice, 20, 0, FW_BOLD, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_MODERN, TEXT(""), &textFont );

Oh, and we need to load images


For this, we need a color key. Whats that? color ignored while loading an image Why would this be useful? game shapes arent all rectangular Important methods: D3DXGetImageInfoFromFile D3DXCreateTextureFromFileEx Lets use them:

D3DXIMAGE_INFO info; HRESULT result = D3DXGetImageInfoFromFile(fileName, &info); if (result == S_OK) { D3DCOLOR colorKey = D3DCOLOR_XRGB(96, 128, 224); LPDIRECT3DTEXTURE9 textureToLoad; result = D3DXCreateTextureFromFileEx( graphicsDevice, fileName, info.Width, info.Height, 1, D3DPOOL_DEFAULT, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, texture, D3DX_DEFAULT, D3DX_DEFAULT, colorKey, &info, NULL, &textureToLoad );

Now we want to draw them


There is a bit of overhead in rendering a single texture Solution?
pool that overhead called batch texture rendering

Each Frame
1. 2. 3. 4. 5. 6. 7. 8. clear screen reserve the GPU for rendering start sprite batch render all textures render text end sprite batch unreserve the GPU force the GPU to the screen

Rendering a frame
graphicsDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(96, 96, 96), 1.0f, 0); graphicsDevice->BeginScene(); spriteHandler->Begin(D3DXSPRITE_ALPHABLEND); result = spriteHandler->Draw( texture, imageRect, NULL, &position, alphaColor); result = textFont->DrawText ( spriteHandler, L"Render this Text", -1, &textRect, DT_LEFT, D3DCOLOR_XRGB(96, 96, 96) ); spriteHandler->End(); graphicsDevice->EndScene(); graphicsDevice->Present(NULL, NULL, NULL, NULL);

Did you get all that?

Believe me, youll get used to it

Texture Management
Skilled game programmers recycle images

Think of a tiled game background


the same images duplicated many times

Efficient Solution: texture manager


When you load a level:
load one of each needed image into a level texture manager for rendering, refer to image indices in texture manager

What might a texture manager do?


Store all textures

Store all names of texture files & paths


map<wstring, LPDIRECT3DTEXTURE9> textures;

Provide methods for:


loading, accessing, reloading, etc.

We might also want a string table


vector<wstring> stringTable;

Why?
ints take up less memory than wstrings

So how do we use it?


when initializing game items use image index game items store stringTable index to represent texture when time to draw, ask stringTable for string at index swap string for texture in texture manager

Well use 2 TextureManagers


One for the GUI

One for the Level Why use 2?

Windowed vs Fullscreen mode


Windowed:
Can minimize, maximize, hit x to close, etc. Share GPU Share all resources

Fullscreen
you get the resources how do we get out?
Game control (exit game for example) ALT-TAB

The Evil ALT-TAB


When in Full-Screen mode:
What happens when someone ALT-TABS?
We lose the graphics device How do we get it back? Someone needs to ALT-TAB back

How can we deal with this?


Check to see if our game has the GPU every single frame

HRESULT result = graphicsDevice->TestCooperativeLevel(); if (SUCCEEDED(result)) { // RENDER THE GAME HERE } else if (result == D3DERR_DEVICELOST) { // SOME OTHER APPLICATION HAS THE GPU, MAYBE // AN ALT-TAB, WE JUST HAVE TO KEEP TRYING TO // GET IT BACK Sleep(100); } else if (result == D3DERR_DEVICENOTRESET) { // YAY! WE GOT THE GPU BACK, MAYBE SOMEONE ALT-TABBED BACK // RESET THE GRAPHICS CARD AND RELOAD ALL THE TEXTURES if (FAILED(graphicsDevice->Reset(&presentParameters))) // RELOAD ALL IMAGES }

Potrebbero piacerti anche