článek

Vytvoř si svou bludišťovku – 2

Vytvoř si svou bludišťovku – 2

Týden se s týdnem sešel a my vám přinášíme druhý díl seriálu, s jehož pomocí byste měli být schopni vytvořit vlastní blušťovku. Doufáme, že vás úvodní část, kterou jsme nechali na úvodní stránce přesně týden, dostatečně upoutala a že se s chutí začtete i dnes.

Vítám vás u druhého dílu seriálu. Nutné zlo s WinApi jsme si odbyli minule a dnes se konečně ponoříme do tajů Direct3D. Pro začátek se však nevyhneme troše teorie. Direct3D je nízkoúrovňové grafické aplikační programové prostředí, které nám umožňuje hardwarovou akceleraci renderování. Zjednodušeně můžeme Direct3D považovat za prostředníka mezi vaší aplikací a grafickým hardwarem. DirectX využívá COM (Component object model), což je technologie, která umožňuje mimo jiné nezávislost na programovacím jazyku. Ukazatelé na třídy tedy získáváme pomocí speciálních funkcí, nikoliv pomocí klíčového slova new. K uvolnění dané třídy použijeme funkci Release().


Přejděme nyní k praxi. Ze všeho nejdříve je potřeba na začátek našeho zdrojového kódu přidat potřebné knihovny a hlavičkové soubory.




#include
#include

#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")



Nyní si vytvoříme globální objekty LPDIRECT3D9 a LPDIRECT3DDEVICE9.


Dovolte mi pár slov o těchto objektech, více až při jejich použití. LPDIRECT3D9 má na starost zjistit informace o vaší grafické kartě a vytvoření LPDIRECT3DDEVICE9, což je zjednodušeně naše cesta ke grafické kartě, kterou budeme velmi často používat.





LPDIRECT3D9 d3d = 0;
LPDIRECT3DDEVICE9 d3ddev = 0;





Pro větší přehlednost jsem se rozhodl náš kód rozdělit do několika funkcí. První z nich bude initD3D





void initD3D(HWND hWnd)
{
...
}



Jak název napovídá, bude mít na starost inicializaci Direct3D a jako jediný parametr má handle okna, do kterého budeme vykreslovat.


Hned ze začátku použijeme funkci Direct3DCreate9 s parametrem D3D_SDK_VERSION. Tím tento objekt vytvoříme a můžem využít jeho dalších služeb.




d3d = Direct3DCreate9(D3D_SDK_VERSION);





Nyní je potřeba zavolat funkci CreateDevice, abychom získali d3ddev. Nejdříve se podíváme na její definici, poté si probereme jednotlivé parametry.





HRESULT IDirect3D9::CreateDevice(
UINT Adapter,
D3DDEVTYPE DeviceType,
HWND hFocusWindow,
DWORD BehaviorFlags,
D3DPRESENT_PARAMETERS *pPresentationParameters,
IDirect3DDevice9** ppReturnedDeviceInterface
);





  • Adapter – udává kterou grafickou kartu použít. Předpokládám, že máte jenom jednu a kdyby ne, tak použijeme tu primární.

  • DeviceType – použijeme D3DDEVTYPE_HAL.

  • hFocusWindow – Handle našeho okna z minulého dílu.

  • BehaviourFlags – Zde si můžeme vybrat, jak se budou zpracovávat vertexy. Volbu máme mezi zpracováním softwarovým nebo hardwarovým. My použijeme hardwarové, abychom tím nezatěžovali CPU.

  • pPresentationParameters – Struktura obsahujucí několik klíčových hodnot pro inicializaci Direct3D. O tom všem za chvíli.

  • ppReturnedDeviceInterface – Finálně získáme LPDIRECT3DDEVICE9.




Nastal čas podívat se blíže na strukturu D3DPRESENT_PARAMETERS.




typedef struct _D3DPRESENT_PARAMETERS_
{
UINT BackBufferWidth;
UINT BackBufferHeight;
D3DFORMAT BackBufferFormat;
UINT BackBufferCount;
D3DMULTISAMPLE_TYPE MultiSampleType;
DWORD MultiSampleQuality;
D3DSWAPEFFECT SwapEffect;
HWND hDeviceWindow;
BOOL Windowed;
BOOL EnableAutoDepthStencil;
D3DFORMAT AutoDepthStencilFormat;
DWORD Flags;
UINT FullScreen_RefreshRateInHz;
UINT PresentationInterval;
} D3DPRESENT_PARAMETERS;





Nebojte, nebudeme potřebovat znát všechno. Podíváme se jen na to nejdůležitější. Připomínám, že kompletní popis této struktury naleznete v se spoustou dalších věcí V Dokumentaci DirectX SDK. Je toho dost, a proto se podíváme jen na to nejdůležitější.



Dovolte mi nyní malé pozdržení nad pojmem BackBuffer. Výsledkem našeho renderování je dvourozměrné pole pixelů, které se vykreslí na váš monitor. Taková věc se zde nazývá buffer. Bufferů existuje samozřejmě více druhů, například vertex buffer. Ale zpět k našemu původnímu tématu. Přišlo se na to, že se vyplatí mít buffery 2 – FrontBuffer a Back buffer. Front buffer se zobrazuje na monitor a do BackBufferu se zapisuje. Jakmile je BackBuffer připraven, prohodí se s Front Bufferem a tím pádem se náš vyrenderovaný snímek vykreslí. Prehození bufferů trvá minimum času, takže se tímto způsobem předchází nepříjemnému blikání monitoru.




  • BackBufferWidth – Horizontální rozlišení.

  • BackBufferHeight – Vertikální rozlišení.

  • BackBufferFormat – Formát pixelů, například 32 bitů.

  • HWND – Již zmiňovaný handle okna. Určuje, kam se má vykreslovat.

  • Windowed – Jestli má aplikace běžet v okně. V našem případě ano.

  • PresentationInterval – Představíme si jeho dvě nejdůležitější hodnoty (D3DPRESENT_INTERVAL_IMMEDIATE – Vykreslování bude probíhat okamžitě, D3DPRESENT_INTERVAL_DEFAULT – Vykreslování se zesynchronizuje s obnovovací frekvencí. )





Takhle to vypadá v praxi:





D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));

d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = screenWidth;
d3dpp.BackBufferHeight = screenHeight;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3d ->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev);




To nejtěžší máme za sebou, nyní můžeme přistoupit k vykreslování. Pro tyto účely si vytvořme funkci render(). Její definice zní jednoduše: void render();


Přesuňme se tedy do jejího těla. Začneme tím, že přemažeme obsah back bufferu námi zvolenou barvou – černou.




D3DPRESENT_PARAMETERS d3dpp;
d3ddev ->Clear(0,
NULL,
D3DCLEAR_TARGET,
D3DCOLOR_XRGB(0, 0, 0),
1.0f,
0);



Pomocí makra D3DCOLOR_XRGB(r,g,b) zadáme námi zvolenou barvu. RGB jsou zkratky pro názvy barev red, green, blue. Každá barva nabývá hodnot v intervalu 0-255 a jejich kombinací lze docílit libovolné barvy. Pár příkladů:




  • D3DCOLOR_XRGB(255,0,0) – červená

  • D3DCOLOR_XRGB(255,255,255) – bílá

  • D3DCOLOR_XRGB(0,0,0) – černá




Je na čase využít služeb naší třídy d3ddev. Předtím, než můžete začít zapisovat do videopaměti, musíte ji nejdříve zamknout a ujistit se tak, že se s ní nebudou dít žádné vámi nechtěné operace. K tomu slouží funkce BeginScene(). Po jejím zavolání provedeme vykreslování (zatím nemáme co vykreslovat) a odemkneme daný buffer funkcí EndScene(). Ve finále nám zbývá zavolat funkci Present() a máme hotovo. Tedy můžeme opakovat cyklus vykreslování.






d3ddev ->BeginScene();
d3ddev ->EndScene();
d3ddev ->Present(NULL, NULL, NULL, NULL);





Zbývá nám už jen uvolnit při ukončování aplikace paměť. Jak jsem se již zmínil, U Direct3D se k tomu používá funkce Release().





if(d3ddev != 0) d3ddev ->Release();
if(d3d != 0) d3d ->Release();



Uvolníme d3d a d3ddev s malou pojistkou, abychom neuvolňovali ukazatel, který nikam neukazuje.


A takhle nějak začíná každá aplikace, která využívá služeb Direct3D. Existuje samozřejmě mnoho dalších věcí, které je potřeba nastavit. O některých z nich bude ještě v průběhu našeho článku řeč. Navíc je zde mnoho grafických enginů, které odvedou spoustu věcí za vás, ale není dobré vědět, jak to vlastně funguje? Nyní mi dovolte malé nastínění toho, co naleznete v příštím článku. Ze začátku nás bude čekat trocha teorie o trojrozměrném prostoru a orientaci v něm a poté si zkusíme s nově nabytými znalostmi něco smysluplného vykreslit na obrazovku. Budu se těšit.



Kompletní zdrojové kódy (všechny díly seriálu): bludistovka_zdroje.zip



Související odkazy:






jan_kohout

autor
/ jan_kohout

Publikováno: 18.11.2007


další články této kategorie





diskuze

odeslat

Nejsi automat? Napiš výsledek 5 + 4 =