>>> Programování 3D <<<

(rady pro začínající programátory 3D)

Ing. Miroslav Němeček

(neprošlo jazykovou úpravou)

Základní otázkou začínajícího programátora 3D je - které rozhranní použít? Před výběrem rozhranní zhodnoťte vaše dosavadní zkušenosti a cíle, kterých chcete v 3D oblasti dosáhnout. Nemáte-li s 3D oblastí zatím žádné zkušenosti, vřele doporučuji první kroky v 3D provést v Petrovi. Nemusíte se zabývat technickou realizací 3D grafiky, postačí se soustředit pouze na "uměleckou" část. Po technické stránce je výsledek zaručen. Získáte základní představy o principech 3D grafiky (aniž by vás již na začátku odradil neúspěch a obtížnost realizace základních 3D operací) a můžete se rozhodnout, kterým směrem budete pokračovat.

Jednou z velmi vhodných voleb pro začátek je použití renderovacího programu využívajícího metodu raytracing, typicky program POVRAY (doplněn editorem MORAY). Tato metoda využívá matematické definice modelů a výpočet scény po jednotlivých grafických bodech výsledného obrázku - renderovací paprsky. Touto metodou je možné dosáhnout nejvyšší kvality grafiky, ovšem za cenu nízké vykreslovací rychlosti. Proto se používá především k vytváření kvalitních grafických obrazců v době vytváření programu (tj. předrenderovaných), nikoliv v době provozu programu u uživatele. Je možné vytvářet kvalitní 3D objekty a 3D pozadí, které jsou v programu využívány s využitím běžné 2D grafiky. Tuto metodu využívají 2D programy systému Petr (předrenderované sprajty - auta, postavy). Z komerčních her je to např. hra Invaders, ale i mnoho jiných. Většinou je tato metoda využívána k vytváření úvodních filmů her.

Druhou možností je real-time 3D grafika. Využívá vykreslování objektů pomocí jednoduchých elementů, zpravidla trojúhelníků. Každý objekt je sestaven z těchto nejjednodušších elementů, proto jsou objekty často "hranaté". Tato metoda je využívána u běžných současných 3D her. Grafika je vytvářena za běhu programu, to umožňuje velkou proměnlivost grafiky. Vzhled objektů ovšem není tak kvalitní jako u předešlé metody a navíc jsou kladeny dost vysoké nároky na výkon počítače a na použitou videokartu (poznámka: doufejme, že v blízké době budou obě metody spojeny již v HW videokarty). Chcete-li vytvářet 3D hry, je pro vás použití této metody nevyhnutelností. Raytracing použijte, chcete-li se zaměřit spíše na uměleckou 3D grafiku.

V nedávných dobách se programátoři 3D rozhodovali, zda použít tzv. Retained Direct3D nebo Immediate Direct3D. Retained Direct3D je nadstavba nad Immediate Direct3D a umožňuje snadnou manipulaci s objekty. Je možné přímo načítat a ukládat objekty ve formátu X, objekty mohou být spojovány pomocí rámů (vytváření stromové hiearchie) a je možné s nimi pomocí transformací snadno manipulovat. Rozsáhle je též podporována práce s texturami a animace objektů. Z hlediska snadnosti použití je to téměř ideální nástroj pro 3D programátora. "Téměř" - požadujete-li něco mimo vybavení retained módu (např. blending) nebo potřebujete-li obejít nějakou (z mnoha) chyb retained módu, je to velmi obtížné, lépe řečeno - máte smůlu. Proto byl další vývoj retained módu Microsoftem od verze 6 zastaven, v nápovědě DirectX 8 již o retained módu nenaleznete ani zmínku. Z toho plyne závěr - retained módem DirectX se vůbec nezabývejte.

Mezi další rozhodnutí patří, zda použít OpenGL nebo DirectX. Nechcete-li se vázat pouze na počítače řady IBM-PC s Windows, musíte použít OpenGL, které je jediné multiplatformní. Před mnoha lety se Microsoft podílel na vývoji OpenGL. Proto se OpenGL verze 1.1 objevilo ve Windows 95. Z komerčních (asi) důvodů Microsoft odkoupil grafické rozhranní založené na COM interface a vyvinul své vlastní rozhranní Direct3D. Původní rozhranní nebylo příliš určené pro programování her a tak bylo použití Direct3D v DirectX verze 3 díky používání prováděcích bufferů velmi obtížné a těžkopádné. V dnešní době lze jednoznačně doporučit - prováděcí buffery rozhranní DirectX 3 v žádném případě NE.

Další verze DirectX (verze 5) přinesla v 3D oblasti možnost jednoduššího vykreslování 3D grafiky pomocí příkazů (DrawPrimitive). V nápovědě k DirectX 5 se dočtete - "Sami se rozhodněte, zda použijete prováděcí buffery z DirectX 3 nebo příkazy DrawPrimitive z DirectX 5, obě metody jsou stejně výkonné a stejně snadné v použití". Je to trochu v rozporu s tvrzením v nápovědě DirectX 6 - "Prováděcí buffery DirectX 3 jsou zastaralé a pomalé a nedoporučují se používat". V nápovědě DirectX 7 se o prováděcích bufferech nedočtete již nic.

Kdo začínal programovat 3D grafiku v rozhranní OpenGL, byl jistě při setkání s Direct3D šokován obtížností a složitostí použití. Direct3D v DirectX 3 nebylo možné srovnávat s OpenGL vůbec. Verze DirectX 5 se již OpenGL více přiblížila. V obou systémech je možné vykreslovat elementy (trojúhelníky) pomocí samostatných příkazů. Použití Direct3D je mnohem složitější, protože je nutné složitě vytvářet renderovací a texturové povrchy. V Direct3D je nutné zjišťovat vybavení videokarty a podle toho se přizpůsobit. Ovladače v Direct3D mohou být buď softwarové (všechna obsluha 3D grafiky prováděna softwarově bez využití vybavení videokarty) nebo hardwarové (je využit rastrovací modul videokarty pro vykreslování textur, od DirectX 6 též využití transformačního a světelného modulu TnLHAL, instrukcí MMX a 3DNow!). Naproti tomu OpenGL zjišťuje vybavení videokarty samo, funkce nepodporované videokartou jsou simulovány softwarově.

Microsoft dříve porovnával obě rozhranní takto: DirectX je určeno převážně pro hry díky své rychlosti, OpenGL je určeno pro přesné grafické aplikace, kde nevadí nižší rychlost. Toto tvrzení však je zpravidla pravdou pouze u videokaret s neúplným vybavením, kdy OpenGL používá softwarovou náhradu a DirectX se nepodporovanou funkcí vůbec nezabývá. Při běžném použití je zpravidla OpenGL stejně rychlé jako DirectX, ne-li rychlejší. Konkrétní případy závisí na použité videokartě. V tom je trochu kámen úrazu. Ovladače OpenGL i DirectX tvoří výrobci videokaret a tak se u některých videokaret můžeme setkat pouze s jedním z rozhranní, druhé rozhranní v tom případě pracuje čistě softwarově. Ideální by bylo, aby program podporoval obě rozhranní a umožňoval zvolit nejvhodnější variantu. Není to snadné, ale není to zase tak obtížné - jak dokazuje např. aplikace Petr.

DirectX verze 6 přineslo další nové funkce, nejvýznamnějším přínosem je multitexturing (využití např. při světelných mapách). Tímto se DirectX z hlediska vybavení dostalo nad OpenGL. Mám ovšem na mysli OpenGL verze 1.1, které je součástí Windows. OpenGL samozřejmě pokračovalo ve svém vývoji (verze 2), využití novější verze vyžaduje od koncového uživatele přeinstalování OpenGL, čímž ho možná příliš nepotěšíte. DirectX verze 7 je součástí Windows 2000, DirectX verze 6 součástí Windows 98, proto u DirectX je situace trochu jednodušší (ovšem Windows NT verze 4 podporují pouze OpenGL). Např. videokarty GeForce (dnes dobrý standard) se zaměřují spíše na rozhranní OpenGL.

Přes všechny uvedené výhody OpenGL je v dnešní době nejvhodnější zaměřit se na DirectX verze 8. DirectX verze 8 používá poněkud odlišné 3D rozhranní od předešlých verzí Direct3D (rozhraní má název "farenheit"). Výrazně se zjednodušilo použití 3D grafiky. K inicializaci 3D okna postačí jediný příkaz. DirectX 8 přináší mnoho nových vlastností (některé se objevily již u DirectX 7). Jednou z velkých výhod je manažer textur. Není již potřeba se starat o načítání textur do videopaměti a jejich uvolňování. K dispozici je multitexturing - např. snadno vícebarevně osvětlíte texturovanou plochu. Zřejmě největším přínosem do budoucna je programovatelný shader (jak asi nazvat česky - stínovač?). Umožňuje libovolné modifikace povrchu a tvaru objektů za běhu programu. Snadno vytvoříte vlnící se hladinu řeky nebo morfující se či kroutící se objekt. Další zajímavou funkcí jsou bumpmaps - tzv. hrbolkové mapy, umožňující používání hrbolatých povrchů objektů. Zajímavá je též možnost vytváření reálných stínů vrhaných na jiné objekty (volume). Nové funkce nejsou ještě mnoha videokartami podporované (největším lákadlem zřejmě jsou HW programovatelné shadery), ale než do 3D oblasti proniknete, jistě bude situace výrazně lepší.

Čím začít? Chcete-li se pustit do opravdového 3D programování (ne jenom využít Petra nebo PovRay), potřebujete k tomu Microsoft Visual C++ verze minimálně 6 a z WWW stránek Microsoft si stáhnout SDK kit pro DirectX 8 (soubor DX8VCSDK.EXE o velikosti 45 MB). Kit obsahuje mnoho ukázkových příkladů ze všech oblastí. Nevyžadujete-li 2D grafiku, nemusíte se prozatím zabývat studiem DirectDraw. Ukázkové příklady vám pro začátek bohatě vystačí.

Při programování 3D grafiky je potřebná dobrá znalost matematiky, především vektorových a maticových operací a goniometrických funkcí. Mnoha problémům se vyhnete, využijete-li doplňkovou knihovnu D3DX8, stejně jak to dělají ukázkové příklady. Knihovna je přilinkována k vašemu programu, který se tím zvětší o pár set KB. Nahrazuje vybavení původního Retained Direct3D aniž by vás omezovala v možnostech použití Direct3D. Provádí všechny potřebné maticové operace, obsluhu souborů formátu X a jiné.

Pro představu o stavbě vašeho programu: Váš program bude začínat inicializací 3D okna (vše uvidíte v ukázkových programech). V inicializaci dále zřejmě načtete všechny X objekty a textury. Objekty používané ve scéně budete mít uloženy ve svých bufferech jako jednotlivé bloky:

- blok vrcholů (jeden vrchol může patřit více trojúhelníkům)

- blok trojúhelníků (spojujících trojice vrcholů)

- blok barev ve vrcholech (nemusí být, má-li objekt jednu barvu)

- blok adres textur ve vrcholech (jak je textura položena na trojúhelníky)

- blok normál (vektory kolmé k povrchu trojúhelníků)

Vrcholy a normály jsou vektory, tj. 3 float čísla následující za sebou. Pozor - 3D rozhranní nastavuje matematický koprocesor na přesnost float (program by neměl přesnost měnit na double).

Při vykreslení jednoho snímku na obrazovku program nejdříve vymaže plochu obrazovky a hloubkový buffer. Používejte výhradně hloubkový buffer (Z-buffer) a dvojitý buffer (tj. buffer na pozadí) a nepředpokládejte použití softwarového renderování. Bez hardwarového urychlování je provoz her dnes již nemyslitelný. Proto můžete vyžadovat použití Z-bufferu (hloubkového bufferu), který je v HW rychlejší než softwarové metody pro vykreslování trojúhelníků. Nemusíte se proto již zabývat hloubkovým tříděním trojúhelníků, BSP stromy (rozdělení prostoru rovinami povrchů objektů) ani portály (tuto metodu použijte až u složitější scény využívající více místností). Budete-li chtít vykreslování později urychlit, rozčleňte prostor na sektory (jednotlivé objekty pomocí rámů připojeny k příslušným sektorům) a testujte viditelnost sektorů a objektů pomocí pohledového kužele (view frustrum) a hraničních kulových (ne kvádrových) ploch kolem objektů.

Po vymazání plochy okna vykreslete všechny objekty ve scéně. Protože využijete Z-buffer, není důležité pořadí vykreslování objektů. Pro zvýšení rychlosti vykreslování se doporučuje vykreslovat za sebou objekty využívající stejnou texturu. Před vykreslením objektu je totiž nutné nastavit jako aktivní texturu, kterou objekt používá. Není-li textura ve videopaměti, manažer textur ji načte do videopaměti. Není-li ve videopaměti dost volného místa, musí před tím uvolnit některou dříve použitou texturu. Opakované načítání textur značně zpomalí rychlost grafiky, proto je při menší videopaměti vhodnější použít menší textury (rozmazanější povrchy). Chcete-li použít obrysy ("děravé" objekty, alpha channel), nastavte alfa složku v obrázku textury nebo použijte některou barvu jako průhlednou (color key). K odříznutí částí textury se využije funkce pro test alfa kanálu. Chcete-li použít průsvitné objekty (blending), musíte je vykreslovat až po vykreslení všech ostatních (neprůsvitných) objektů, protože nelze dodatečně vkreslit něco pod průhledný povrch.

Při vykreslování objektů nejdříve vytvoříte vykreslovací buffer s objektem. Buffer můžete uchovat i do budoucna, proto ho po vykreslení nerušte. Pro více stejných objektů můžete využít stejný buffer. Pro každý objekt musíte uchovávat jeho transformační matici, která definuje polohu objektu v prostoru. Matici musíte po každém pohybu objektu přepočítat. Před vykreslením každého objektu musíte nastavit jeho matici jako matici modelu. Dalšími maticemi je pohledová matice (view matrix) definující polohu kamery v prostoru a projekční matice definující promítání pohledu z kamery do okna. Tyto matice se zpravidla nastavují na začátku vykreslování snímku.

Po vykreslení všech objektů použijete příkaz pro vykreslení snímku, který zajistí přenesení obrazu z bufferu v pozadí na obrazovku. Nevykreslujte přímo na obrazovku (tj. použijte vždy buffer v pozadí), objekty by navzájem problikávaly.

Po všech vykreslovacích operacích zjistěte čtením multimediálního časovače čas, který uplynul od minulého snímku. Rychlost chodu programu bude na různých počítačích velmi odlišná, musíte proto všechny pohyby provádět podle skutečně uplynulého času. Následuje obsluha funkcí programu jako vstup kláves, posuny a transformace objektů atd.

- - - - - - - -

Na závěr si neodpustím ještě jednu poznámku - použijte Petra V2.xx 3D a ničím z výše uvedeného se již nemusíte zabývat.

 

autor