Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Metody 3D grafiky (2. část, terén)

... pokračování z minulé lekce

V této lekci se budeme zabývat tvorbou venkovních ("outdoor") terénů. Metody tvorby terénu si ukážeme na programu Metody 3D, který si můžete stáhnout na konci lekce.

1. Čtverec

Úplně nejjednodušším typem terénu je prostá čtvercová nebo obdélníková plocha založená na prvku stěna (který tvoří 2 pravoúhlé trojúhelníky). Prvek je roztažen na rozměry terénu a pokryt jednou velkou texturou.

Čtvercový terén má výhodu v jednoduchosti, ovšem za cenu mnoha nevýhod. Kromě toho, že terén nemůžeme výškově členit, je největší nevýhodou potřeba velké textury. Vzhledem k tomu, že si nemůžeme dovolit rozměr textury příliš zvyšovat (např. kvůli omezení grafické karty), je textura takového povrchu značně rozmazaná.

Jistou náplastí je použití multitextur. Modulujeme-li povrch, opatřený rozměrnou texturou, další texturou, ale s vyšší četností opakování, vytvoříme tím na povrchu jemně zrnitý povrch.

Efekt vytvoří v pozorovateli dojem, že povrch má mnohem jemnější členitost než ve skutečnosti má. Rozdíl můžeme porovnat na následujících dvou snímcích. První snímek je čtvercový terén bez multitextur, druhý s multitexturou. Přepnutí je možné klávesou M.

Mezi další nevýhody čtvercového terénu je problematické zobrazení velkých renderovaných ploch. Problém vznikne například při pokusu osvětlit střední část čtvercového terénu. Při výpočtu osvětlení renderovací jednotka nejdříve vypočítá osvětlení ve vrcholech objektu. Poté vykresluje vnitřní části ploch, jejich osvětlení počítá interpolací z vrcholů. Proto zůstane střední část plochy tmavá, přestože do ní umístíme lokální zdroj světla. Naopak, budeme-li tímto zdrojem pohybovat po okruhu kolem terénu, budeme pozorovat, že jednu chvíli je terén tmavý a vzápětí světlý, v závislosti na tom, jak je zdroj světla blízko k některému z vrcholů terénu.

Problém s renderováním velké plochy se může projevit také při renderování mlhy, zapneme-li mód vrcholové mlhy. V tom případě se mlha počítá ve vrcholech plochy a poté se interpoluje, podobně jako při výpočtu osvětlení. Tím vznikne efekt "podivného" chování mlhy, kdy je mlha jednu chvíli naprosto neprůhledná (i v nejbližších místech terénu) a jindy se zas vůbec neprojeví. Naštěstí tento problém není častým případem, protože je běžně podporovaná tabulková mlha, která počítá mlhu pro každý vykreslovaný bod samostatně.

Jen pro zajímavost si uveďme ještě jeden možný typ problému vykreslování velké plochy. Při renderování jednotlivých trojúhelníků objektů postupuje renderovací jednotka tak, že nejdříve vypočítá mapování textury ve vrcholech plošek a poté vykresluje vnitřní části plošek tak, že souřadnici v textuře interpoluje z vrcholových souřadnic. Pokud bychom použili jednoduše interpolovanou texturu při perspektivním zobrazení, vykreslil by se například střed plošky logicky uprostřed trojúhelníku, což ale neodpovídá perspektivní projekci, kde souřadnicově střední část má být opticky mnohem dál od nás, tedy blíže ke vzdálenějšímu konci plošky než k bližšímu. Při pohybu v takovém terénu by povrch terénu před námi neustále jakoby plaval a přeléval se. Naštěstí se tento problém dnes již prakticky nevyskytuje, protože všechny nové grafické karty již podporují perspektivní korekci zobrazení textur, závislou na zvoleném typu projekce.

Jak je z uvedených výhod a nevýhod zřejmé, bude čtvercový terén vhodný spíše jen pro malé plochy, například pro podlahu v místnosti či terén malého prostranství.

2. Čtverec s opakováním

Jistého zlepšení čtvercového terénu dosáhneme, pokud na něj namísto jedné velké textury namapujeme malou texturu, ale s opakováním. Může to být například textura trávy nebo textura dlaždice. V ukázkovém programu se obě textury střídavě přepínají při výběru tohoto typu terénu.

Opakováním textury dosáhneme toho, že textura má mnohem vyšší jemnost a vypadá již přirozeněji. Samozřejmě za cenu toho, že textura na celém terénu musí být stejná. Ale výsledek je již docela použitelný pro mnoho jednodušších aplikací.

3. Plocha

V systému Petr máme pro tvorbu terénu k dispozici prvek terén z plochy. Prvku předáme jako parametr plochu, na které pomocí předmětů vykreslíme vzhled jednotlivých částí terénu a pomocí číselné hodnoty 1 nadefinujeme výšku v každé části terénu.

Prvek vytvoří objekt terénu jako čtvercovou síť plošek, jejíž vrcholy odpovídají zadaným výškám. Obrazy použitých políček sestaví do jedné textury tak, aby sousední políčka na sebe navazovala. Výslednou texturu namapuje na terén.

Tato metoda umožňuje snadno vytvářet terén s přesně specifikovaným vzhledem povrchu. Další velkou předností je možnost používat vestavěnou funkci pro zjištění výšky v terénu, která pro vygenerovaný terén dokáže zjistit výšku terénu v jakémkoliv místě terénu. Tak lze snadno implementovat pohyb hráče po terénu nebo rozmístění objektů po povrchu terénu.

Největší nevýhodou terénu generovaného z plochy je použití políček jako textury, tedy obrázky s rozměry 32 x 32 bodů. Textura takového povrchu je neostrá a to obzvláště použijeme-li velký počet typů políček vyžadující velkou výslednou texturu. Upozorňuji, že není rozhodující počet políček na ploše ale počet typů políček, textury stejných políček se sdílí.

4. Výšková mapa

Dalším prvkem Petra, sloužícím ke generování terénů, je prvek terén z obrázku. Vstupem prvku je tentokrát obrázek, použitý jako výšková mapa.

Prvek opět vygeneruje terén jako čtvercovou síť plošek, ale výšky jednotlivých vrcholů zjistí z výškové mapy. Čím je příslušný grafický bod obrázku světlejší, tím bude výsledný vrchol terénu výše. Při generování terénu se uplatní prvek pro vyhlazení textur, který zajistí, že povrch terénu bude vyhlazen. Na celém povrchu terénu bude namapována jedna textura opakovaně - použili jsme opět texturu trávy jako u terénu čtverce s opakováním. Podobně jako u předešlého typu terénu, i u terénu generovaného z výškové mapy můžeme využít funkci pro zjištění výšky v terénu.

5. Projekce textury

Kombinujeme-li u objektu více textur jako multitextury, jsme omezeni schopnostmi grafické karty. Mnoho dnešních grafický karet již umožňuje používat mnohastupňové multitextury, ale v mnoha případech jsme omezeni pouze na 2 textury nebo některé slabší karty nepodporují multitextury vůbec.

Proto máme v Petrovi k dispozici funkci pro mapování textury, která umožňuje pro některé účely multitexturu simulovat tím, že provede projekci textury do barev vrcholů objektu. Tak můžeme jednou texturou zbarvit vrcholy objektu a druhou texturou pokrýt povrch objektu. To lze s výhodou využít například u terénu.

Použijeme opět předešlý terén, generovaný z výškové mapy. Na celý terén provedeme projekci s nastavenou obarvenou texturou podle následujícícho obrázku, čímž dojde k obarvení vrcholů terénu.

Původní texturu trávy nahradíme jinou texturou, bude to opět stejná textura trávy, ale odbarvená na černobílou barvu.

Textura trávy se obarví barvou vrcholů terénu a jak vidíte na následujícím obrázku, výsledek je skutečně působivý. Můžeme tak snadno vytvářet terény, které vypadají poměrně realisticky. Navíc stále ještě u tohoto terénu můžeme používat funkci pro zjištění výšky terénu.

Kromě obarvení terénu můžeme projekci textury použít ještě pro stínovou mapu, což je definice osvětlení terénu. Takto můžeme vytvořit osvětlení terénu nezávisle na hlavním osvětlení (ve skutečnosti můžeme osvětlení dokonce vypnout) a také můžeme nasimulovat stíny od velkých statických objektů, jako např. stíny od budov. Stínovou mapu můžeme připravit buď ručním kreslením nebo vyrenderováním v 3D editoru.

6. Dlaždice

Předešlé metody mají nevýhodu v tom, že buď se na povrchu opakuje jedna textura nebo má textura nízké rozlišení. Chceme-li dosáhnout kvalitního vzhledu textur, musíme terén sestavit z více částí a každé části přiřadit samostatnou texturu.

Nejjednodušším případem jsou dlaždice. Použijeme opět plochu s definicí terénu. Budeme programově procházet jednotlivá políčka plochy a na každé pozici vytvoříme jednu dlaždici jako čtvercovou stěnu (položenou vodorovně). Dlaždici přiřadíme texturu s vyšším rozlišením podle políčka na pozici.

U textur bychom měli řešit jejich vzájemné navazování. To zajistíme především tím, že je budeme připravovat z bezešvých textur, jejichž začátky a konce na sebe navazují. Dále musíme u každé textury zajistit správné adresování. Pokud na sebe navazuje okraj s protějším okrajem, zapneme adresování s opakováním. Při odlišných okrajích musíme použít adresování s ořezáním textury. Chceme-li se zbavit ostrého přechodu mezi texturami v módu opakování, můžeme to zajistit tím, že spojovací řada texelů bude pro obě navazující textury přesně stejná.

7. Segmenty

Dlaždicový terén umožňuje již dosáhnout kvalitních textur, je to však stále ještě jedna rovina. Chceme-li zajistit i různou výšku částí terénu, musíme namísto jednoduchých dlaždic použít generované 3D objekty, segmenty. K programovému generování 3D objektů můžeme použít prvek objekt z textu (u plné verze Petra též prvek vytvoření 3D objektu z paměťových bloků).

Při generování modelu jednoho segmentu musíme vyjít z defince formátu DirectX souboru x v textorém tvaru. Generujeme souřadnice vrcholů (relativně ke středu segmentu), normály ve vrcholech, indexy plošek a mapování souřadnic textur. Zde je příklad jednoho vygenerovaného segmentu:

xof 0303txt 0032

Mesh {
  4;
  -10;16.40225;-10;,
  -10;2.60224999999998;10;,
  10;-15.50675;10;,
  10;-3.49774999999998;-10;;

  2;
  3;0,1,2;,
  3;0,2,3;;

  MeshNormals {
    4;
    0.338181010771736;0.939391696588159;0.0563635017952893;,
    0.175885430692562;0.836653255761983;0.518725018572429;,
    0.368685553271484;0.814369768118581;0.448188401884061;,
    0.370316746357589;0.744355269060483;0.555698426117102;;

    2;
    3;0,1,2;,
    3;0,2,3;;
  }

  MeshTextureCoords {
    4;
    0;1;,
    0;0;,
    1;0;,
    1;1;;
  }
}

Souřadnice vrcholů X a Z jsou konstanty, stejně jako indexy vrcholů trojúhelníků a souřadnice mapování textur. Souřadnice Y vrcholů zjistíme snadno z definiční plochy, od které terén odvozujeme. Nejtěžším úkolem je výpočet normál. Nemůžeme použít funkci pro automatický výpočet normál, protože segmenty nejsou spolu spojeny do jednoho objektu. Musíme proto normály počítat.

Odvodíme si vztahy pro výpočet normály v jednom vrcholu terénu. Uvažujme, že šířka jednoho segmentu terénu je w a výška (resp. hloubka) je h. Z plochy si načteme výšky vrcholů Y0 (střed), Y1 (vlevo), Y2 (vpravo), Y3 (nahoře) a Y4 (dole). Vrcholy tedy budou mít souřadnice:

  • V0 = [0, Y0, 0]
  • V1 = [-w, Y1, 0]
  • V2 = [w, Y2, 0]
  • V3 = [0, Y3, h]
  • V4 = [0, Y4, -h]

Z rozdílů souřadnic vrcholů vypočteme směrové vektory hran segmenů vycházejících ze středového vrcholu:

  • v1 = V1 - V0 = [-w, Y1 - Y0, 0]
  • v2 = V2 - V0 = [w, Y2 - Y0, 0]
  • v3 = V3 - V0 = [0, Y3 - Y0, h]
  • v4 = V4 - V0 = [0, Y4 - Y0, -h]

Vynásobíme-li směrové vektory hran segmentů pomocí vektorového součinu, obdržíme vektory normál sousedních segmentů. Vektorový součin c = a x b počítáme jako: cx = ay*bz - az*by; cy = az*bx - ax*bz; cz = ax*by - ay*bx (slovně: násobek zbylých složek v přímém směru mínus násobek v opačném směru). Jeden z vektorů přitom otáčíme, takže:

  • n14 = - v1 x v4 = [h(Y1 - Y0), wh, w(Y4 - Y0)]
  • n42 = - v4 x v2 = [-h(Y2 - Y0), wh, w(Y4 - Y0)]
  • n23 = - v2 x v3 = [-h(Y2 - Y0), wh, -w(Y3 - Y0)]
  • n31 = - v3 x v1 = [h(Y1 - Y0), wh, -w(Y3 - Y0)]

Výsledný normálový vektor n získáme jako součet normál sousedních segmentů (neboť se jedná o zprůměrovanou normálu).

  • n = n14 + n42 + n23 + n31 = [2h(Y1 - Y2), 4wh, 2w(Y4 - Y3)]

Pro zjednodušení můžeme vektor skalárně zkrátit, získáme tak výsledný vztah pro výpočet normály:

  • n = [h(Y1 - Y2), 2wh, w(Y4 - Y3)]

Po výpočtu normálového vektoru musíme vektor normalizovat - což znamená, že jednotlivé složky vydělíme délkou vektoru. Délku vektoru vypočteme jako odmocninu ze součtu druhých mocnin jednotlivých složek vektoru.

Dalším důležitou operací je výpočet výšky v terénu. U programově generovaného terénu nám již nepomůže systém Petr a musíme výšku počítat sami. Ve skutečnosti jsme tento výpočet potřebovali již dříve, k výpočtu normál terénu.

Pří výpočtu výšky si nejdříve připravíme výšky vrcholů segmentu, do kterého daná souřadnice patří. Vzhledem k tomu, že výška udávaná v prvku plochy se vztahuje k levému hornímu rohu segmentu (při pohledu shora), potřebujeme ke zjištění výšek aktuální políčko, políčko vpravo a obdobná políčka o řádek níže.

Výšku v terénu nemůžeme jen jednoduše interpolovat mezi vrcholy segmentu. Musíme počítat s tím, že segment se skládá ze dvou trojúhelníků, jejichž zlom prochází středem segmentu a to konkrétně z pravého horního rohu do levého dolního rohu. Proto musíme výpočet rozdělit na dva případy podle toho, na kterém z trojúhelníků se testovaný bod nachází. Rozlišení provedeme jednoduše porovnáním souřadnice X se souřadnicí Z (pracujeme v této chvíli již se zlomkovou částí souřadnic, která je relativní v aktuálním segmentu). Je-li souřadnice X větší než souřadnice Z, pohybujeme se na pravém dolním trojúhelníku, v opačném případě to bude levý horní trojúhelník. Po rozlišení trojúhelníku již můžeme provést jednoduchou interpolaci výšky podle aktuální souřadnice.

.... pokračování příště


 

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 251x (6.09 MB)
Aplikace je včetně zdrojových kódů v jazyce Petr Lite (jsou obsaženy v EXE souboru, který lze v programu přímo otevřít)

 

Všechny články v sekci
3D grafika
Článek pro vás napsal Panda38
Avatar
Uživatelské hodnocení:
Ještě nikdo nehodnotil, buď první!
Programátor C++, WinAPI, ASM.
Aktivity