DirectX9 - 1. návod - Vykreslovacího zařízení
DirectX9 - 1. návod - Vytvoření vykreslovacího zařízení
1. Vytvoření Vykreslovacího zařízení
Cíl
Příprava
InitD3D - Vytvoření vykreslovacího zařízení
Cleanup - Uvolnění alokovaných proměnných
Render - Funkce pro vykreslení
MsgProc - Zachytávání a zpracování zpráv okna
WinMain - Vstupní bod naší aplikace
Poznámka na závěr
Příklad je zde ke staženíCíl
V tomto prvním návodu se naučíte vytvořit okno a vytvořit pro něho vykreslovací zařízení (Direct3d Device). Pomocí něho se vše v DirectX vykresluje a díky němu se dá i spousta věcí při renderování nastavit.
nahoru
Příprava
Založíme si projekt (viz. Nultý tutorial). A můžeme začít psát zdrojový text... Nejdříve naincludujeme potřebnou DirectX hlavičku, v našem případě tedy napíšeme#include <d3d9.h>Nyní si připravíme globální proměnné, které budeme potřebovat
LPDIRECT3D9 g_pD3D = NULL; // Potřeba k vytvoření D3DDevice LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Samotné vykreslovací zařízeníNyní si vytvoříme funkci InitD3D, ve které provedeme všechny přípravy našeho vykreslovacího zařízení (Direct3D Device)
nahoru
InitD3D - Vytvoření vykreslovacího zařízení
HRESULT InitD3D( HWND hWnd )Většina funkcí v DirectX vrací HRESULT. Je to jakási zpráva, zda funkce skončila chybou, nebo je vše v pořádku. Jediný parametr této funkce je ukazatel na naše okno aplikace, právě do něho se bude vykreslovat.
Nyní vytvoříme D3D objekt, který je potřeba pro vytvoření našeho Direct3D Device
if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
return E_FAIL;
Nyní nastavíme strukturu použitou k vytvoření Direct3D device. Většina paramaterů
je vynulovaných. Nastavíme windowed TRUE, protože chceme vykreslovat
do okna (opakem by byl celoobrazovkový mod). Poté nastavíme SwapEffect
na discart, což je nejefektivnější metoda zobrazování backbufferu
na display. A poté si ještě vyžádáme formát Back bufferu stejný jako je formát
aktuální pracovní plochy.
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
Konečně můžeme přejít k vytvoření Direct3D device. Zde používáme výchozí adaptér
(většina systémů má pouze jednu grafickou kartu) a vyžádáme si typ device "HAL"
(což znamená, že chceme raději hardwarové zařízení, než softwarové - tz. raději
ať vykresluje grafická karta, než procesor počítače). Softwarové zpracování Vertexů (Software Vertex Processing) je nastaveno proto, protože bude fungovat na všech kartách. Na těch kartách, které umožňují i hardwarové zpracování, se můžeme dočkat velkého navýšení výkonu specifikováním Hardware Vertex Processingu.
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice ) ) )
{
return E_FAIL;
}
nahoru
Cleanup - Uvolnění alokovaných proměnných
VOID Cleanup()V tomto jednoduchém příkladu je třeba uvolnit pouze D3D, které jsme použili k vytvoření vykreslovacího zařízení a samotné vykreslovací zařízení
if( g_pd3dDevice != NULL )
g_pd3dDevice->Release();
if( g_pD3D != NULL )
g_pD3D->Release();
nahoru
Render - Funkce pro vykreslení
VOID Render()Nejdříve kontrola, zda jsme nezavolali Vykreslování ještě před vytvořením zařízení
if( NULL == g_pd3dDevice )
return;
Na důkaz, že vše proběhlo vpořádku teď vyčistíme Back Buffer modrou barvou.
Ve hrách je většinou třeba scénu nejdříve mezi každým snímkem vyčistit
a poté teprve vykreslovat. Čištění ale zabírá celkem hodně času a dá se od něho
v jistých případech upustit. Jak to udělat si ale povíme až v některém z budoucích příkladů.
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET,
D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );
Před samotným vykreslováním musíme ještě vykreslovacímu zařízení říct, že se k tomu chystáme.
Zároveň otestujeme, zda se povedlo zahájení vykreslování (Rendrování) a je tedy vše jak má být. Makro SUCCEEDED()
je přímo v hlavičkových souborech Directů a můžeme ho používat v jakékoliv funkci, která má
jako návratový typ HRESULT, k otestování jejího úspěchu. K otestování neúspěchu bychom
pak použili makro FAILED().Po Zahájení vykreslování bychom nejspíše měli něco vykreslit, ale v tomto jednoduchém příkladu se spokojíme s již provedeným vyčištěním na modrou barvu.
Hned proto vykreslování zase ukončíme.
// Zahájení vykreslování
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
// Vykreslení objektů bývá na tomto místě
// Ukončení vykreslování
g_pd3dDevice->EndScene();
}
A ještě nesmíme zapomenout na zobrazení výsledku vykreslování. Většinou je mechanismus takový, že
se prohodí Back Buffer (do kterého vykreslujeme) s
Front Bufferem, který je zase po dobu vykreslování zobrazen.
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
nahoru
MsgProc - Zachytávání a zpracování zpráv okna
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )Jedna ze dvou funkcí, které ještě nakonec musíme uvést, ale se samotnými Directy nemají mnoho společného. Funkce MsgProc a WinMain slouží pouze k vytvoření a práci s oknem v systému Windows. Přesto takové funkce nesmějí chybět a my si je alespoň stručně popíšeme.
Tato funkce se stará o to, když například stiskneme klávesu, aby se něco někde stalo. Navíc má za úkol i zpracování standardních událostí, jako je ukončení aplikace, požadavek operačního systému na překreslení okna aplikace atd.
Uvnitř tedy vytvoříme switch, kterým zpracujeme jednotlivé zprávy odděleně. Kód je následující.
switch( msg )
{
case WM_DESTROY:
Cleanup();
PostQuitMessage( 0 );
return 0;
case WM_PAINT:
Render();
ValidateRect( hWnd, NULL );
return 0;
}
Můžeme si všimnout, že funkce Render, tz překreslení scény, se zde děje jen na dožadavek systému
k překreslení. To není ve hrách moc běžné. Takový požadavek přichází například když okno nejdříve
překrylo jiné a opět odkrylo. Jinak zůstává obsah stejný. Ve hrách je ale třeba překreslovat
scénu permanentně a zajistit tak maximální počet snímků za vteřinu. Takový přístup si ukážeme
již v následujícím tutorialu. Zde nám ale postačí překreslení na vyžádání. Program pak
v době nečinnosti alespoň nezabírá procesorový čas.Pokud jsme zprávě neporozuměli, ještě ji vrátíme.
return DefWindowProc( hWnd, msg, wParam, lParam );
nahoru
WinMain - Vstupní bod naší aplikace
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )Hlavní funkce, po spuštění se volá právě ona. Její pozice na konci souboru není bezúčelná, v této chvíli jsou totiž známy již všechny potřebné funkce a linker (program pro spojování částí programu - např. volání funkce s jejím tělem) již nebude mít problém je správně připojit.
Hned na začátku si vytvoříme a zaregistrujeme třídu našeho okna.
// Registrace třídy okna
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
"Dx9 Tutorial 1", NULL };
RegisterClassEx( &wc );
Teď si okno vytvoříme. Zde se dají nastavit jeho vlastnosti jako
je druh systémových tlačítek, chování okna např. při pokusu o změnu velikosti...
// Vytvoření okna aplikace
HWND hWnd = CreateWindow( "Dx9 Tutorial 1",
"Dx9 1 - Vytvoření vykreslovacího zařízení",
WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
NULL, NULL, wc.hInstance, NULL );
Zatím jsme v této funkci neudělali nic, co by s DirectX souviselo.
To musíme napravit. Zavoláme nyní inicializaci našeho vykreslovacího zařízení,
pokud uspěje, můžeme okno zobrazit a začít zpracovávat jeho události.
// Inicializace Direct3D
if( SUCCEEDED( InitD3D( hWnd ) ) )
{
// Zobrazení okna
ShowWindow( hWnd, SW_SHOWDEFAULT );
UpdateWindow( hWnd );
// Smyčka zpracování zpráv okna
MSG msg;
while( GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
Po vyskočení z této smyčky již aplikace končí. Proto třídu okna odregistrujeme,
což mimojiné ve smyčce zpracování zpráv zapřičiní zavolání funkce Cleanup() pro vyčištění.
UnregisterClass( "Dx9 Tutorial 1", wc.hInstance );
return 0;
nahoru
Poznámka na závěr
Tento text je téměř přesným opisem výsledného zdrojového textu. Vynechány byly částečně komentáře, které nahrazuje tento text. Zdrojový text na konci této stránky ale ony komentáře obsahuje a umožní Vám to lepší orientaci i stálého připojení na tyto stránky.Dále byly vynechány složené závorky jednotlivých těl funkcí a také některé návratové hodnoty těchto funkcí. Zvykněme si na to, že pokud má funkce návratovou hodnotu HRESULT, bude na konci při úspěšném provedení vrácena hodnota S_OK (v případě chyby to může být např obecné selhání E_FAIL)
return S_OK;
Pokud je funkce s návratovou hodnotou VOID, nevrací pochopitelně nic a v případě WinMain a jiných funkcí je
vrácena hodnota 0.
return 0;
nahoru
Příklad je zde ke stažení
- Příklad #1 Src - Zdrojové texty s projektem pro Microsoft Visual Studio 2005
- Příklad #1 Exe - Spustitelný, již zkompilovaný program
nahoru
| Jan Zelený | 22.2.2007 |
© 2008 Jan Zelený | monade.cz





